BLCommand.hh

Go to the documentation of this file.
00001 //      BLCommand.hh
00002 /*
00003 This source file is part of G4beamline, http://g4beamline.muonsinc.com
00004 Copyright (C) 2003,2004,2005,2006 by Tom Roberts, all rights reserved.
00005 
00006 This program is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU General Public License
00008 as published by the Free Software Foundation; either version 2
00009 of the License, or (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 http://www.gnu.org/copyleft/gpl.html
00017 */
00018 
00019 #ifndef BLCOMMAND_HH
00020 #define BLCOMMAND_HH
00021 
00022 #include <vector>
00023 #include <map>
00024 #include <iostream>
00025 #include <fstream>
00026 
00027 #include "globals.hh"
00028 #include "G4RotationMatrix.hh"
00029 #include "G4VisAttributes.hh"
00030 #include "G4Material.hh"
00031 
00032 #include "BLEvaluator.hh"
00033 
00034 typedef std::vector<G4String> BLArgumentVector;
00035 typedef std::map<G4String,G4String> BLArgumentMap;
00036 
00037 const G4String IndentDesc("             ");
00038 const G4String IndentArg("                           ");
00039 
00040 const G4String DefaultDoubleFmt = "%.4g";
00041 
00042 /**     class BLCommandPos - postion of the command input
00043  *      (used to get the input position for do loops)
00044  *      see also: BLCommand::setPos().
00045  **/
00046 class BLCommandPos {
00047         std::istream *in;
00048         std::streampos pos;
00049         friend class BLCommand;
00050 public:
00051         BLCommandPos(std::istream *_in) {
00052                 in = _in;
00053                 pos = in->tellg();
00054         }
00055         bool isValid() { return pos != (std::streampos)-1; }
00056 };
00057 
00058 /**     enum BLCmdType -- types of commands (for help index).
00059  **/
00060 enum BLCmdType {BLCMDTYPE_HELP,BLCMDTYPE_CONTROL,BLCMDTYPE_LAYOUT,
00061                 BLCMDTYPE_BEAM,BLCMDTYPE_AUX,BLCMDTYPE_ELEMENT,
00062                 BLCMDTYPE_PLACE,BLCMDTYPE_CUTS,BLCMDTYPE_DATA,BLCMDTYPE_OTHER };
00063 
00064 
00065 /**     class BLCommand - interface to define a command.
00066  *
00067  *      The standard usage for a command without a BLElement is to derive
00068  *      from this class and define a static instance using the default 
00069  *      constructor. In the derived-class default constructor the command is 
00070  *      registered, calls to setSynopsis() and setDescription() provide help
00071  *      text, and initial values are given to all class variables. This
00072  *      instance is used to execute the command, and normally no other
00073  *      instances are needed.
00074  *
00075  *      The static instance is used to keep the default arguments for the
00076  *      element.
00077  *
00078  *      Standard usage for a command for a BLElement is to derive a class
00079  *      from BLElement (which is derived from BLCommand), and do the above
00080  *      in its default constructor. The derived command() function then
00081  *      creates an instance of the class. Only the static instance is used
00082  *      to execute the command, but other instances implement the various
00083  *      elements (to be placed later in the input file).
00084  *
00085  *      See BLCMDdemo.cc and BLCMDtubs.cc for examples (.hh files are
00086  *      not needed for most commands, as their classes are not needed
00087  *      anywhere but in their implementation file).
00088  *
00089  *      NOTE: ONLY the default object should use the default constructor!
00090  **/
00091 class BLCommand {
00092         enum TokenType { NONE, ARGNAME, ARGVALUE };
00093         static std::map<G4String,BLCommand*> *mapCommand;
00094         static int errors;
00095         /// nextToken() will return the next token in line; called only by
00096         /// doCommand(). Side-effect: updates place and sets type.
00097         static G4String nextToken(const G4String& line, 
00098                                 G4String::size_type& place, TokenType& type);
00099         /// printArgDesc will print the description of an argument, using
00100         /// wrapWords().
00101         void printArgDesc(G4String name, G4String _description);
00102         static std::istream *in;
00103         friend class BLCMDplace;
00104 protected:
00105         enum ArgumentMode { PROCESS, COUNT, HELP, PRINT, CHANGE };
00106         ArgumentMode argMode;
00107         bool argFound;
00108         G4String argName;
00109         G4String argValue;
00110         G4String synopsis;
00111         G4String description;
00112         G4String printArgString;
00113         int nArgs;
00114         int nFixed;
00115         int nTunable;
00116         BLCmdType type;
00117         friend class BLCMDhelp;
00118 protected:
00119         /// Default Constructor.
00120         BLCommand() : synopsis(), description()
00121                 { }
00122 
00123         /// Destructor.
00124         virtual ~BLCommand();
00125 
00126         /// Copy Constructor.
00127         BLCommand(const BLCommand& r) : synopsis(), description()
00128                 { }
00129 
00130         // general functions for use by derived classes:
00131 
00132         /// registerCommand() registers the command.
00133         /// Used only in the default constructor -- ensures mapCommand is
00134         /// properly initialized regardless of order.
00135         void registerCommand(BLCmdType _type);
00136 
00137         /// deleteCommand() will delete a command by name
00138         void deleteCommand(G4String &name)
00139                 { if(mapCommand) mapCommand->erase(name); }
00140 
00141         /// setSynopsis() gives a 1-line (64 char) description of what the 
00142         /// command does. Used by the help command with no arguments.
00143         /// The string should be 64 characters or less, and should not contain
00144         /// any newline; no word wrapping.
00145         /// Used only in the default constructor.
00146         void setSynopsis(const char * _synopsis) 
00147                 { synopsis = _synopsis; }
00148 
00149         /// setDescription() gives a more complete description of the command,
00150         /// when help for this specific command is requested.
00151         /// When printed by the help() function, word wrapping is performed,
00152         /// but lines beginning with whitespace are kept intact.
00153         /// Named arguments are automatically described by the help() function,
00154         /// but positional arguments should be described here.
00155         /// Words are wrapped using wrapWords().
00156         /// Used only in the default constructor.
00157         void setDescription(const char * _description) 
00158                 { description = _description; }
00159 
00160         /// argString() declares a string-valued argument. name should be a
00161         /// valid C identifier 15 chars or less, and description should be
00162         /// a short description (wrapWords() is used).
00163         /// Used only in the defineNamedArgs() function.
00164         /// permitChange affects whether this argument can be set when
00165         /// an element is placed.
00166         void argString(G4String& var, G4String name, G4String description,
00167                         bool permitChange=true);
00168 
00169         /// argDouble() declares a G4double-valued argument. name should be a
00170         /// valid C identifier 15 chars or less, and description should be
00171         /// a short description (wrapWords() is used).
00172         /// Used only in the defineNamedArgs() function.
00173         /// units should be the human units for the argument, because
00174         /// the value of var is always in internal units. fmt and units are
00175         /// used when argMode=PRINT.
00176         /// permitChange affects whether this argument can be set when
00177         /// an element is placed.
00178         void argDouble(G4double& var, G4String name, G4String description,
00179                 G4double units=1.0, G4String fmt=DefaultDoubleFmt,
00180                 bool permitChange=true);
00181 
00182         /// argTunable() declares a G4double-valued argument that is tunable 
00183         /// (see the tune command in BLCMDtune.cc). name should be a
00184         /// valid C identifier 15 chars or less, and description should be
00185         /// a short description (wrapWords() is used).
00186         /// Used only in the defineNamedArgs() function.
00187         /// units should be the human units for the argument, because
00188         /// the value of var is always in internal units. fmt and units are
00189         /// used when argMode=PRINT.
00190         /// Tunable arguments can always be set when an element is placed,
00191         /// and will be changed during the tracking of the Tune Particle
00192         /// if their value includes a tune variable. See BLTune.hh for a 
00193         /// description of how tunable arguments are handled.
00194         void argTunable(G4double& var, G4String name, G4String description,
00195                 G4double units=1.0, G4String fmt=DefaultDoubleFmt);
00196 
00197         /// argInt() declares a integer-valued argument. name should be a
00198         /// valid C identifier 15 chars or less, and description should be
00199         /// a short description (wrapWords() is used).
00200         /// Used only in the defineNamedArgs() function.
00201         /// permitChange affects whether this argument can be set when
00202         /// an element is placed.
00203         void argInt(G4int& var, G4String name, G4String description,
00204                         bool permitChange=true);
00205 
00206         /// handleNamedArgs() handles all named arguments to the command (i.e.
00207         /// those defined in defineNamedArgs()). For use in the command() 
00208         /// function.
00209         /// returns 0 if OK, -1 on error.
00210         int handleNamedArgs(BLArgumentMap& namedArgs);
00211 
00212         /// help() prints the help information for this command.
00213         /// detailed=false prints only the name and synopsis; true prints
00214         /// the description and arguments also.
00215         virtual void help(bool detailed);
00216 
00217         /// wrapWords() will wrap words for descriptions in help().
00218         /// In text, lines beginning with whitespace are preserved as is,
00219         /// including blank lines. Otherwise, newlines aren't needed in text.
00220         /// indent1 is the start of the first line, and indent is used
00221         /// at the start of succeeding lines ("" is OK); indents are counted
00222         /// in the line width. The returned string always ends with "\n".
00223         G4String wrapWords(G4String text, G4String indent1, G4String indent,
00224                                                         G4String::size_type width=79);
00225 
00226         /// printArgs() will print (to stdout) the named arguments of the
00227         /// command entered, for log purposes.
00228         /// Calls defineNamedArgs() with argMode=PRINT to print the args.
00229         /// indent1 is the indent for the first line.
00230         void printArgs(G4String indent1);
00231 public:
00232         // Functions implemented by the derived class:
00233 
00234         /// commandName() returns the name of the command.
00235         virtual G4String commandName() = 0;
00236 
00237         /// command() executes the command associated with this element.
00238         /// argv and namedArgs come from parsing the command-line:
00239         /// argv has a vector of any positional arguments (without "=");
00240         /// namedArgs has a map of any named arguments of the form name=value.
00241         /// Returns 0 if OK, -1 on error.
00242         /// NOTE: for classes derived via BLElement.hh, arguments can be given
00243         /// when an object is defined and when it is placed. For that to work,
00244         /// argument values must not be used in the command() function unless
00245         /// they are defined with permitChange=false (in the above argString...
00246         /// functions). Also the correct units must be given to argDouble().
00247         virtual int command(BLArgumentVector& argv,
00248                                                 BLArgumentMap& namedArgs) = 0;
00249 
00250         /// defineNamedArgs() defines the named arguments for the command. 
00251         /// This function should consist ONLY of a series of calls to
00252         /// argString(), argDouble(), and argInt().
00253         /// Used by handleNamedArgs(), help(), and print() (they manipulate
00254         /// the behavior of the argXXX() functions via argMode).
00255         virtual void defineNamedArgs();
00256 
00257         /// argChanged() will be called whenever some argument value has
00258         /// changed. Derived classes should define it and perform any internal
00259         /// computations that depend on argument values. Many/most derived
00260         /// classes won't need to use it. In particular, after argChanged()
00261         /// returns the functions getHeight(), getWidth() and getLength()
00262         /// must return the correct values for the current arguments.
00263         /// BEWARE: a single argument change may call this multiple times.
00264         /// Applies only to named arguments, not positional ones.
00265         virtual void argChanged() { }
00266 
00267         /// print() will print to stdout the command. The default versions
00268         /// will do for most commands and elements. name can be "".
00269         /// prints commandname() and name in the space of IndentArg, followed
00270         /// by the values of all named arguments, in the order they appear
00271         /// in defineNamedArgs().
00272         virtual void print(G4String name);
00273 
00274         /// Print() -- alternate version for commands with special arguments.
00275         /// does not use defineNamedArgs() to print arguments, but rather
00276         /// prints namedArgs.
00277         void print(G4String name, BLArgumentMap& namedArgs);
00278 
00279         /// getName() returns the element's name; do not confuse this with
00280         /// commandName(). Re-defined by BLElement.
00281         virtual G4String getName() const { return "??"; }
00282 
00283 public:
00284         // general functions:
00285 
00286         /// getCmdType() returns the type of this command
00287         BLCmdType getCmdType() { return type; }
00288 
00289         /// isValidCommand() returns true if cmd is a valid command.
00290         static bool isValidCommand(G4String& cmd)
00291                 { return mapCommand != 0 && mapCommand->count(cmd) > 0; }
00292 
00293         /// doCommand() will parse line and perform a single command.
00294         /// Returns 0 if OK, -1 if error.
00295         static int doCommand(G4String& line);
00296 
00297         /// parseArgs() will parse the arguments of a command line.
00298         /// Arguments are appended to argv[] and added to namedArgs.
00299         /// Returns 0 if OK, -1 if syntax error.
00300         static int parseArgs(const G4String &line, BLArgumentVector &argv,
00301                                                 BLArgumentMap &namedArgs);
00302 
00303         /// readFile() reads a file of commands and executes them.
00304         /// "-" is stdin. Returns the number of errors encountered,
00305         /// or -1 if filename cannot be read.
00306         static int readFile(G4String filename);
00307 
00308         /// printError() prints an error message, using sprintf-style args.
00309         /// It also increments the errorCount.
00310         static void printError(const char *fmt, ...);
00311 
00312         /// getErrorCount() will return the number of errors so far.
00313         static int getErrorCount() { return errors; }
00314 
00315         /// getNextCommand() returns the next command. backslash-newline has
00316         /// been handled, and the line is stripped of whitespace at both ends.
00317         /// returns 0 if error or EOF. The pointer should NOT be deleted.
00318         static G4String *getNextCommand();
00319 
00320         /// getPos() returns the current position of the Command input stream
00321         static BLCommandPos getPos();
00322 
00323         /// setPos() will set the Command input stream to a specified position
00324         void setPos(BLCommandPos &pos);
00325 
00326         // general utility functions for use by other classes
00327 
00328         /// getMaterial() searches the G4Material list and returns the entry
00329         /// corresponding to name. Searches the NIST database if the material
00330         /// is not already defined. Prepends "G4_" if necessary.
00331         /// prints an error and exits if the material is not found, so all
00332         /// materials MUST be defined before they are used, unless they can
00333         /// be found in the geant4 NIST database.
00334         static G4Material *getMaterial(G4String materialName, bool error=true);
00335 
00336         /// getVisAttrib() returns the appropriate G4VisAttributes.
00337         static G4VisAttributes *getVisAttrib(G4String color);
00338 
00339         /// stringToRotationMatrix() converts a string "X90,Y45" into a 
00340         /// G4RotationMatrix.
00341         /// This is an active rotation, in that the object is first rotated
00342         /// around the parent's X axis by 90 degrees, then the object is
00343         /// further rotated around the parent's Y axis by 45 degrees.
00344         /// The return value points to a G4RotationMatrix on the heap, so
00345         /// it is persistent. Angles are in degrees, can have decimals,
00346         /// and can be negative. Axes are X, Y, Z.
00347         static G4RotationMatrix *stringToRotationMatrix(G4String rotation);
00348 
00349         /// dumpRotation() dumps info about a rotation matrix to stdout.
00350         static void dumpRotation(const G4RotationMatrix *rot, const char *str);
00351 
00352         /// splitString() splits a string at each instance of any character
00353         /// in delim, returning a vector<G4String>. If trim is true, each
00354         /// returned string has whitespace removed from its front and rear.
00355         /// Successive delimiters, or delimiters at the beginning or end,
00356         /// generate an empty string.
00357         static std::vector<G4String> splitString(const G4String &s, 
00358                                         const G4String &delim, bool trim=false);
00359 
00360         /// getDouble() converts a string to a double, returning nan if
00361         /// the string is not a valid expression using double constants and
00362         /// standard C operators and functions; whitespace is permitted as in C
00363         /// but an empty or all-whitespace string is invalid.
00364         /// Callers can use std::isnan(double) or gsl_isnan(double) to test
00365         /// for validity.
00366         static double getDouble(const G4String &s)
00367                 { BLEvaluator e; return e.evaluate(s); }
00368 
00369         /// getList() converts a string containing a delimited list
00370         /// of double expressions to a vector<G4double>. Any character in
00371         /// delim separates entries. Functions and operators known to
00372         /// BLEvaluator can be used in each entry of the list.
00373         /// Empty entries (null or consisting only of whitespace) are invalid.
00374         /// Returns an empty list if any entry is an invalid expression.
00375         static std::vector<G4double> getList(const G4String &s,
00376                                                         const G4String &delim);
00377 };
00378 
00379 #endif // BLCOMMAND_HH
g4beamline