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