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, unsigned int& place, 00098 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 unsigned 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