00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArArgumentBuilder.h"
00030 #include "ArArgumentParser.h"
00031 #include "ArLog.h"
00032 #include "ariaUtil.h"
00033 #include <stdarg.h>
00034
00035 std::list<std::string> ArArgumentParser::ourDefaultArgumentLocs;
00036 std::list<bool> ArArgumentParser::ourDefaultArgumentLocIsFile;
00041 ArArgumentParser::ArArgumentParser(int *argc, char **argv)
00042 {
00043 myArgc = argc;
00044 myArgv = argv;
00045 myUsingBuilder = false;
00046 myBuilder = NULL;
00047 myOwnBuilder = false;
00048
00049 myEmptyArg[0] = '\0';
00050 }
00051
00056 ArArgumentParser::ArArgumentParser(ArArgumentBuilder *builder)
00057 {
00058 myUsingBuilder = true;
00059 myBuilder = builder;
00060 myOwnBuilder = false;
00061 myEmptyArg[0] = '\0';
00062 }
00063
00064 ArArgumentParser::~ArArgumentParser()
00065 {
00066 if (myOwnBuilder)
00067 {
00068 delete myBuilder;
00069 myBuilder = NULL;
00070 }
00071 }
00072
00073 bool ArArgumentParser::checkArgumentVar(char *argument, ...)
00074 {
00075 char arg[2048];
00076 va_list ptr;
00077 va_start(ptr, argument);
00078 vsnprintf(arg, sizeof(arg), argument, ptr);
00079 va_end(ptr);
00080 return checkArgument(arg);
00081 }
00082
00092 bool ArArgumentParser::checkArgument(char *argument)
00093 {
00094 size_t i;
00095 std::string extraHyphen;
00096 extraHyphen = "-";
00097 extraHyphen += argument;
00098 for (i = 0; i < getArgc(); i++)
00099 {
00100 if (strcasecmp(argument, getArgv()[i]) == 0 ||
00101 strcasecmp(extraHyphen.c_str(), getArgv()[i]) == 0)
00102 {
00103 removeArg(i);
00104
00105
00106 return true;
00107 }
00108 }
00109 return false;
00110 }
00111
00128 bool ArArgumentParser::checkParameterArgumentStringVar(
00129 bool *wasReallySet, const char **dest, char *argument, ...)
00130 {
00131 char arg[2048];
00132 va_list ptr;
00133 va_start(ptr, argument);
00134 vsnprintf(arg, sizeof(arg), argument, ptr);
00135 va_end(ptr);
00136 return checkParameterArgumentString(arg, dest, wasReallySet);
00137 }
00138
00157 bool ArArgumentParser::checkParameterArgumentString(
00158 char *argument, const char **dest, bool *wasReallySet,
00159 bool returnFirst)
00160 {
00161 char *param;
00162 param = checkParameterArgument(argument, returnFirst);
00163
00164 if (param == NULL)
00165 {
00166 if (wasReallySet)
00167 *wasReallySet = false;
00168 return true;
00169 }
00170 else if (param[0] != '\0')
00171 {
00172 *dest = param;
00173 if (wasReallySet)
00174 *wasReallySet = true;
00175 return true;
00176 }
00177 else
00178 {
00179 ArLog::log(ArLog::Normal, "No argument given to %s", argument);
00180 return false;
00181 }
00182 }
00183
00200 bool ArArgumentParser::checkParameterArgumentBoolVar(
00201 bool *wasReallySet, bool *dest, char *argument, ...)
00202 {
00203 char arg[2048];
00204 va_list ptr;
00205 va_start(ptr, argument);
00206 vsnprintf(arg, sizeof(arg), argument, ptr);
00207 va_end(ptr);
00208 return checkParameterArgumentBool(arg, dest, wasReallySet);
00209 }
00210
00229 bool ArArgumentParser::checkParameterArgumentBool(char *argument,
00230 bool *dest,
00231 bool *wasReallySet,
00232 bool returnFirst)
00233 {
00234 char *param;
00235 param = checkParameterArgument(argument, returnFirst);
00236
00237 if (param == NULL)
00238 {
00239 if (wasReallySet)
00240 *wasReallySet = false;
00241 return true;
00242 }
00243 else if (param[0] != '\0')
00244 {
00245 if (strcasecmp(param, "true") == 0 || strcmp(param, "1") == 0)
00246 {
00247 *dest = true;
00248 if (wasReallySet)
00249 *wasReallySet = true;
00250 return true;
00251 }
00252 else if (strcasecmp(param, "false") == 0 || strcmp(param, "0") == 0)
00253 {
00254 *dest = false;
00255 if (wasReallySet)
00256 *wasReallySet = true;
00257 return true;
00258 }
00259 else
00260 {
00261 ArLog::log(ArLog::Normal,
00262 "Argument given to %s was not a bool (true, false, 1, 0) it was the string %s",
00263 argument, param);
00264 return false;
00265 }
00266
00267 }
00268 else
00269 {
00270 ArLog::log(ArLog::Normal, "No argument given to %s", argument);
00271 return false;
00272 }
00273
00274 }
00275
00292 bool ArArgumentParser::checkParameterArgumentIntegerVar(
00293 bool *wasReallySet, int *dest, char *argument, ...)
00294 {
00295 char arg[2048];
00296 va_list ptr;
00297 va_start(ptr, argument);
00298 vsnprintf(arg, sizeof(arg), argument, ptr);
00299 va_end(ptr);
00300 return checkParameterArgumentInteger(arg, dest, wasReallySet);
00301 }
00302
00321 bool ArArgumentParser::checkParameterArgumentInteger(
00322 char *argument, int *dest, bool *wasReallySet, bool returnFirst)
00323 {
00324 char *param;
00325 char *endPtr;
00326 int intVal;
00327
00328 param = checkParameterArgument(argument, returnFirst);
00329
00330 if (param == NULL)
00331 {
00332 if (wasReallySet)
00333 *wasReallySet = false;
00334 return true;
00335 }
00336 else if (param[0] != '\0')
00337 {
00338 intVal = strtol(param, &endPtr, 10);
00339 if (endPtr[0] == '\0')
00340 {
00341 *dest = intVal;
00342 if (wasReallySet)
00343 *wasReallySet = true;
00344 return true;
00345 }
00346 else
00347 {
00348 ArLog::log(ArLog::Normal,
00349 "Argument given to %s was not an integer it was the string %s",
00350 argument, param);
00351 return false;
00352 }
00353
00354 }
00355 else
00356 {
00357 ArLog::log(ArLog::Normal, "No argument given to %s", argument);
00358 return false;
00359 }
00360
00361 }
00362
00374 char *ArArgumentParser::checkParameterArgumentVar(char *argument, ...)
00375 {
00376 char arg[2048];
00377 va_list ptr;
00378 va_start(ptr, argument);
00379 vsnprintf(arg, sizeof(arg), argument, ptr);
00380 va_end(ptr);
00381 return checkParameterArgument(arg);
00382 }
00396 char * ArArgumentParser::checkParameterArgument(char *argument,
00397 bool returnFirst)
00398 {
00399 char *ret;
00400 char *retRecursive;
00401 size_t i;
00402 std::string extraHyphen;
00403
00404 extraHyphen = "-";
00405 extraHyphen += argument;
00406
00407 for (i = 0; i < getArgc(); i++)
00408 {
00409 if (strcasecmp(argument, getArgv()[i]) == 0 ||
00410 strcasecmp(extraHyphen.c_str(), getArgv()[i]) == 0)
00411 {
00412
00413 if (getArgc() > i+1)
00414 {
00415 ret = getArgv()[i+1];
00416 }
00417 else
00418 {
00419 ret = myEmptyArg;
00420 }
00421
00422 removeArg(i);
00423
00424 if (ret != NULL && ret != myEmptyArg)
00425 removeArg(i);
00426
00427 if (returnFirst)
00428 {
00429 return ret;
00430 }
00431 else if ((retRecursive = checkParameterArgument(argument)) != NULL)
00432 {
00433 return retRecursive;
00434 }
00435
00436 else
00437 {
00438 return ret;
00439 }
00440 }
00441 }
00442 return NULL;
00443 }
00444
00445 void ArArgumentParser::removeArg(size_t which)
00446 {
00447 if (which >= getArgc())
00448 {
00449 ArLog::log(ArLog::Terse, "ArArgumentParser::removeArg: %d is greater than the number of arguments which is %d", which, getArgc());
00450 return;
00451 }
00452 if (myUsingBuilder)
00453 {
00454 myBuilder->removeArg(which);
00455 }
00456 else
00457 {
00458 size_t i;
00459 for (i = which; i < getArgc() - 1; i++)
00460 myArgv[i] = myArgv[i+1];
00461 *myArgc -= 1;
00462 }
00463 }
00464
00465 size_t ArArgumentParser::getArgc(void) const
00466 {
00467 if (myUsingBuilder)
00468 return myBuilder->getArgc();
00469 else
00470 return *myArgc;
00471 }
00472
00473 char** ArArgumentParser::getArgv(void) const
00474 {
00475 if (myUsingBuilder)
00476 return myBuilder->getArgv();
00477 else
00478 return myArgv;
00479 }
00480
00481 const char* ArArgumentParser::getArg(size_t whichArg) const
00482 {
00483 if (whichArg >= getArgc())
00484 return NULL;
00485 else
00486 return getArgv()[whichArg];
00487 }
00488
00489 void ArArgumentParser::log(void) const
00490 {
00491 size_t i;
00492 ArLog::log(ArLog::Terse, "Num arguments: %d", getArgc());
00493 for (i = 0; i < getArgc(); ++i)
00494 ArLog::log(ArLog::Terse, "Arg %d: %s", i, getArgv()[i]);
00495 }
00496
00497 void ArArgumentParser::addDefaultArgument(const char *argument)
00498 {
00499 if (!myUsingBuilder)
00500 {
00501 myBuilder = new ArArgumentBuilder;
00502 myBuilder->addStrings(myArgv, *myArgc);
00503 myOwnBuilder = true;
00504 myUsingBuilder = true;
00505 }
00506 myBuilder->add(argument);
00507 }
00508
00521 void ArArgumentParser::loadDefaultArguments(void)
00522 {
00523 std::list<std::string>::iterator it;
00524 std::list<bool>::iterator bIt;
00525 const char *str;
00526 char *argumentsPtr;
00527 char arguments[1024];
00528
00529 if (!myUsingBuilder)
00530 {
00531 myBuilder = new ArArgumentBuilder;
00532 myBuilder->addStrings(myArgv, *myArgc);
00533 myOwnBuilder = true;
00534 myUsingBuilder = true;
00535 }
00536
00537 for (it = ourDefaultArgumentLocs.begin(),
00538 bIt = ourDefaultArgumentLocIsFile.begin();
00539 it != ourDefaultArgumentLocs.end();
00540 it++, bIt++)
00541 {
00542 str = (*it).c_str();
00543
00544 if (!(*bIt) && (argumentsPtr = getenv(str)) != NULL)
00545 {
00546 myBuilder->addPlain(argumentsPtr, 1);
00547 ArLog::log(ArLog::Normal,
00548 "Added arguments from environmental variable '%s'", str);
00549 }
00550
00551 else if ((*bIt) &&
00552 ArUtil::getStringFromFile(str, arguments, sizeof(arguments)))
00553 {
00554 myBuilder->addPlain(arguments, 1);
00555 ArLog::log(ArLog::Normal, "Added arguments from file '%s'",
00556 str);
00557 }
00558
00559
00560 else
00561 {
00562 ArLog::log(ArLog::Verbose,
00563 "Could not load from environmental variable or file '%s'",
00564 str);
00565 }
00566 }
00567 }
00568
00572 void ArArgumentParser::addDefaultArgumentFile(const char *file)
00573 {
00574 ourDefaultArgumentLocs.push_back(file);
00575 ourDefaultArgumentLocIsFile.push_back(true);
00576 }
00577
00578
00583 void ArArgumentParser::addDefaultArgumentEnv(const char *env)
00584 {
00585 ourDefaultArgumentLocs.push_back(env);
00586 ourDefaultArgumentLocIsFile.push_back(false);
00587 }
00588
00589 void ArArgumentParser::logDefaultArgumentLocations(void)
00590 {
00591 std::list<std::string>::iterator it;
00592 std::list<bool>::iterator bIt;
00593
00594 ArLog::log(ArLog::Normal,
00595 "Default argument files or environmental variables:");
00596 for (it = ourDefaultArgumentLocs.begin(),
00597 bIt = ourDefaultArgumentLocIsFile.begin();
00598 it != ourDefaultArgumentLocs.end();
00599 it++, bIt++)
00600 {
00601 if (*bIt)
00602 ArLog::log(ArLog::Normal, "%10s%-10s%s", "", "file", (*it).c_str());
00603 else
00604 ArLog::log(ArLog::Normal, "%10s%-10s%s", "", "envVar", (*it).c_str());
00605 }
00606 }
00613 bool ArArgumentParser::checkHelpAndWarnUnparsed(
00614 unsigned int numArgsOkay)
00615 {
00616 if (checkArgument("-help") || checkArgument("-h") || checkArgument("/?") ||
00617 checkArgument("/h"))
00618 return false;
00619
00620 if (getArgc() <= 1 + numArgsOkay)
00621 return true;
00622
00623 size_t i;
00624 char buf[2048];
00625 sprintf(buf, "Unhandled arguments to program:");
00626 for (i = 1 + (int)numArgsOkay; i < getArgc(); i++)
00627 sprintf(buf, "%s %s", buf, getArg(i));
00628 ArLog::log(ArLog::Normal, buf);
00629 ArLog::log(ArLog::Normal,
00630 "Program will continue but to see the help listing type '%s -help'",
00631 getArg(0));
00632 return true;
00633 }
00634