00001
00002
00003 #include "CommandLineProcessor.hh"
00004
00005
00006 #include "PackageInfo.hh"
00007 #include "CommandQueue.hh"
00008 #include "CommandLineOption.hh"
00009
00010
00011 #include "getopt.h"
00012
00013
00014 #include <sstream>
00015 #include <cassert>
00016
00017 using std::stringstream;
00018 using std::left;
00019
00020 namespace slic
00021 {
00022 CommandLineProcessor::CommandLineProcessor()
00023 : Module("CommandLineProcessor"),
00024 m_help_flag(0),
00025 m_interactive_flag(0),
00026 m_version_flag(0)
00027 {
00028 registerOptions();
00029 createOptionsString();
00030 }
00031
00032 CommandLineProcessor::~CommandLineProcessor()
00033 {}
00034
00035 void CommandLineProcessor::process(int argc, char** argv)
00036 {
00037
00038 static struct option long_options[] = {
00039 {"help", no_argument, 0, 'h'},
00040 {"help", no_argument, 0, '?'},
00041 {"version", no_argument, 0, 'v'},
00042 {"interactive", no_argument, 0, 'n'},
00043 {"macro", required_argument, 0, 'm'},
00044 {"event-file", required_argument, 0, 'i'},
00045 {"lcdd-url", required_argument, 0, 'g'},
00046 {"lcio-file", required_argument, 0, 'o'},
00047 {"lcio-path", required_argument, 0, 'p'},
00048 {"autoname", optional_argument, 0, 'O'},
00049 {"lcio-delete", no_argument, 0, 'x'},
00050 {"run-events", required_argument, 0, 'r'},
00051 {"skip-events", required_argument, 0, 's'},
00052 {"physics-list", required_argument, 0, 'l'},
00053 {"log-file", required_argument, 0, 'L'},
00054 {"seed", required_argument, 0, 'd'},
00055 {"dump-gdml", required_argument, 0, 'G'},
00056 {"optical", no_argument, 0, 'c'},
00057 {0, 0, 0, 0}
00058 };
00059
00060 const char* optstr = m_getoptOptions.c_str();
00061
00062 while (1) {
00063
00064 int option_index = 0;
00065 int c;
00066
00067
00068 c = getopt_long (argc,
00069 argv,
00070 optstr,
00071 long_options,
00072 &option_index);
00073
00074 #ifdef SLIC_LOG
00075 log() << LOG::verbose << "Handling option <" << c << ">." << LOG::done;
00076 #endif
00077
00078
00079 if ( c == -1 )
00080 break;
00081
00082
00083 switch (c) {
00084
00085 case 'h':
00086 m_help_flag=1;
00087 break;
00088
00089 case '?':
00090 m_help_flag=1;
00091 break;
00092
00093 case 'n':
00094 m_interactive_flag=1;
00095 break;
00096
00097 case 'v':
00098 m_version_flag=1;
00099 break;
00100
00101 default:
00102
00103 stringstream ostr;
00104 char cc = (char)c;
00105 ostr << cc;
00106 string theopt = ostr.str();
00107
00108 if ( optarg ) {
00109 m_commandline.push_back( OptionsPair( theopt, optarg ) );
00110 }
00111 else {
00112 m_commandline.push_back( OptionsPair( theopt, "" ) );
00113 }
00114
00115 break;
00116 }
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 if ( m_version_flag ) {
00140 printVersion();
00141 abort();
00142 }
00143
00144
00145 else if ( m_help_flag || argc == 1 ) {
00146 printUsage();
00147 abort();
00148 }
00149
00150 else if ( argc == 2 && optind < argc ) {
00151 stringstream str;
00152 str << "/control/execute ";
00153 str << argv[1];
00154 m_g4q.add( str.str() );
00155 }
00156
00157 else if ( optind == 1 || optind < argc ) {
00158 printUsage();
00159 abort();
00160 }
00161
00162 else {
00163 processOptions();
00164 }
00165 }
00166
00167 void CommandLineProcessor::printUsage()
00168 {
00169 printVersion();
00170
00171 log() << LOG::okay << LOG::done;
00172 log() << LOG::okay << "**************" << LOG::done;
00173 log() << LOG::okay << "* SLIC Usage *" << LOG::done;
00174 log() << LOG::okay << "**************" << LOG::done;
00175
00176 log() << LOG::okay << LOG::done;
00177 log() << LOG::okay << "Command line usage: " << LOG::done;
00178 log() << LOG::okay << LOG::done;
00179 log() << LOG::okay << "slic [single_macro_path]" << LOG::done;
00180 log() << LOG::okay << "slic [options]" << LOG::done;
00181
00182 log() << LOG::okay << LOG::done;
00183
00184 log() << LOG::okay << "Interactive usage: " << LOG::done;
00185 log() << LOG::okay << LOG::done;
00186 log() << LOG::okay << "slic -n" << LOG::done;
00187
00188 log() << LOG::okay << LOG::done;
00189
00190 printOptions();
00191
00192 log() << LOG::okay << LOG::done;
00193 }
00194
00195 void CommandLineProcessor::abort()
00196 {
00197 exit(0);
00198 }
00199
00200 void CommandLineProcessor::registerOptions()
00201 {
00202
00203 addOption(new CommandLineOption("h",
00204 "help",
00205 "Print SLIC usage.",
00206 0,
00207 0,
00208 "/slic/usage"));
00209
00210
00211 addOption(new CommandLineOption("?",
00212 "help",
00213 "Print SLIC usage.",
00214 0,
00215 0,
00216 "/slic/usage"));
00217
00218
00219 addOption(new CommandLineOption("n",
00220 "interactive",
00221 "Start a Geant4 interactive session.",
00222 0,
00223 0,
00224 "/control/interactive"));
00225
00226
00227 addOption(new CommandLineOption("v",
00228 "version",
00229 "Print SLIC version.",
00230 0,
00231 0,
00232 "/slic/version"));
00233
00234
00235 addOption(new CommandLineOption("m",
00236 "macro",
00237 "Execute Geant4 commands from a file.",
00238 1,
00239 1,
00240 "/control/execute"));
00241
00242
00243 addOption(new CommandLineOption("g",
00244 "lcdd-url",
00245 "Set LCDD geometry file URL.",
00246 1,
00247 1,
00248 "/lcdd/url"));
00249
00250
00251 addOption(new CommandLineOption("i",
00252 "event-file",
00253 "Set event input file full path.",
00254 1,
00255 1,
00256 "/generator/filename"));
00257
00258
00259 addOption(new CommandLineOption("o",
00260 "lcio-file",
00261 "Set name of LCIO output file.",
00262 1,
00263 1,
00264 "/lcio/filename"));
00265
00266
00267 addOption(new CommandLineOption("p",
00268 "lcio-path",
00269 "Set directory for LCIO output.",
00270 1,
00271 1,
00272 "/lcio/path"));
00273
00274
00275 addOption(new CommandLineOption("O",
00276 "autoname",
00277 "Automatically name the LCIO output file.",
00278 0,
00279 1,
00280 "/lcio/autoname"));
00281
00282
00283 addOption(new CommandLineOption("x",
00284 "lcio-delete",
00285 "Delete an existing LCIO file.",
00286 0,
00287 0,
00288 "/lcio/fileExists delete"));
00289
00290
00291 addOption(new CommandLineOption("r",
00292 "run-events",
00293 "Run # of events.",
00294 1,
00295 1,
00296 "/run/beamOn"));
00297
00298
00299 addOption(new CommandLineOption("s",
00300 "skip-events",
00301 "Set number of events to skip.",
00302 1,
00303 1,
00304 "/generator/skipEvents"));
00305
00306
00307 addOption(new CommandLineOption("l",
00308 "physics-list",
00309 "Set Geant4 physics list.",
00310 1,
00311 1,
00312 "/physics/select"));
00313
00314
00315 addOption(new CommandLineOption("L",
00316 "log-file",
00317 "Set logfile name.",
00318 0,
00319 0,
00320 "/log/filename"));
00321
00322
00323 addOption(new CommandLineOption("d",
00324 "seed",
00325 "Set the random seed. (No argument seeds with time.)",
00326 0,
00327 1,
00328 "/random/seed"));
00329
00330
00331 addOption(new CommandLineOption("G",
00332 "dump-gdml",
00333 "Dump geometry to GDML file.",
00334 1,
00335 1,
00336 "/lcdd/dumpGDML"));
00337
00338
00339 addOption(new CommandLineOption("c",
00340 "optical",
00341 "Enable optical physics processes.",
00342 0,
00343 0,
00344 "/physics/enableOptical"));
00345 }
00346
00347 void CommandLineProcessor::processOption(const string& opt)
00348 {
00349
00350 for ( CommandLineArguments::iterator it = m_commandline.begin();
00351 it != m_commandline.end();
00352 it++ ) {
00353
00354
00355 if ( it->first == opt ) {
00356
00357
00358 CommandLineOption* cmdlineopt = getCommandLineOption(opt);
00359
00360
00361 assert(cmdlineopt != 0);
00362
00363
00364 string cmdstr = cmdlineopt->getG4CommandString();
00365
00366
00367 if ( it->second != "" ) {
00368 cmdstr += " ";
00369 cmdstr += it->second;
00370 }
00371
00372
00373 m_g4q.add(cmdstr);
00374 }
00375 }
00376 }
00377
00378 void CommandLineProcessor::addOption(CommandLineOption* opt)
00379 {
00380 m_cmds.push_back(opt);
00381 }
00382
00383 void CommandLineProcessor::processOptions()
00384 {
00385
00386 processOption("L");
00387
00388
00389 processOption("g");
00390
00391
00392 processOption("c");
00393
00394
00395 processOption("l");
00396
00397
00398
00399
00400
00401 if ( hasOption("g") ) {
00402 m_g4q.add("/run/initialize");
00403 }
00404
00405
00406 processOption("G");
00407
00408
00409 processOption("d");
00410
00411
00412 processOption("i");
00413
00414
00415 processOption("p");
00416
00417
00418 processOption("x");
00419
00420
00421 processOption("o");
00422
00423
00424 processOption("O");
00425
00426
00427 processOption("m");
00428
00429
00430 processOption("s");
00431
00432
00433 processOption("r");
00434
00435
00436 if (m_interactive_flag) {
00437 m_g4q.add("/control/interactive");
00438 }
00439 }
00440
00441 void CommandLineProcessor::printOptions()
00442 {
00443 log() << LOG::okay << "************************" << LOG::done;
00444 log() << LOG::okay << "* Command Line Options *" << LOG::done;
00445 log() << LOG::okay << "************************" << LOG::done;
00446 log() << LOG::okay << LOG::done;
00447
00448 static const int opt_width = 8;
00449 static const int descr_width = 15;
00450 static const int name_width = 16;
00451 static const int cmd_width = 24;
00452 static const int sep_width = 60;
00453
00454 log().getOutputStream().width(opt_width);
00455 log().getOutputStream() << left;
00456
00457 log().getOutputStream() << left;
00458 log() << LOG::okay << "Option";
00459
00460 log().getOutputStream().width(name_width);
00461 log().getOutputStream() << left;
00462 log() << LOG::okay << "Full Name";
00463
00464 log().getOutputStream().width(cmd_width);
00465 log().getOutputStream() << left;
00466 log() << LOG::okay << "Macro Command";
00467
00468 log().getOutputStream().width(descr_width);
00469 log().getOutputStream() << left;
00470 log() << LOG::okay << "Description";
00471
00472 log().getOutputStream().fill('-');
00473 log().getOutputStream().width(sep_width);
00474
00475 log() << LOG::okay << LOG::done;
00476 log() << LOG::okay << '-' << LOG::done;
00477
00478 log().getOutputStream().fill(' ');
00479
00480 for ( OptionsList::const_iterator iter = m_cmds.begin();
00481 iter != m_cmds.end();
00482 iter++ ) {
00483 CommandLineOption* cl_opt = (*iter);
00484
00485 std::string opt_str = "-" + cl_opt->getShortName();
00486 log().getOutputStream().width(opt_width);
00487 log().getOutputStream() << left;
00488 log() << LOG::okay << opt_str;
00489
00490 std::string name_str = "--" + cl_opt->getLongName();
00491 log().getOutputStream().width(name_width);
00492 log().getOutputStream() << left;
00493 log() << LOG::okay << name_str;
00494
00495 log().getOutputStream().width(cmd_width);
00496 log().getOutputStream() << left;
00497 log() << LOG::okay << cl_opt->getG4CommandString();
00498
00499 log().getOutputStream().width(descr_width);
00500 log().getOutputStream() << left;
00501 log() << LOG::okay << cl_opt->getDescription();
00502
00503 log() << LOG::okay << LOG::done;
00504 }
00505 }
00506
00507 CommandLineOption* CommandLineProcessor::getCommandLineOption(const std::string& opt)
00508 {
00509 CommandLineOption* clo = 0;
00510 for ( OptionsList::const_iterator iter = m_cmds.begin();
00511 iter != m_cmds.end();
00512 iter++ ) {
00513 if ( (*iter)->getShortName() == opt ) {
00514 clo = (*iter);
00515 break;
00516 }
00517 }
00518 return clo;
00519 }
00520
00521 bool CommandLineProcessor::hasOption(const std::string& opt)
00522 {
00523 bool hasoption = false;
00524 for ( CommandLineArguments::iterator it = m_commandline.begin();
00525 it != m_commandline.end();
00526 it++ ) {
00527 if ( (*it).first == opt ) {
00528 hasoption=true;
00529 break;
00530 }
00531 }
00532 return hasoption;
00533 }
00534
00535 void CommandLineProcessor::createOptionsString()
00536 {
00537 m_getoptOptions="";
00538 for ( OptionsList::iterator it = m_cmds.begin();
00539 it != m_cmds.end();
00540 it++ ) {
00541 CommandLineOption* opt = *it;
00542 m_getoptOptions += opt->getShortName();
00543 if ( opt->getMinArgs() ) {
00544 m_getoptOptions += ":";
00545 }
00546 else if ( opt->getMaxArgs() ) {
00547 m_getoptOptions += "::";
00548 }
00549 }
00550 }
00551 }