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 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ArArgumentBuilder.h"
00029 #include "ArArgumentParser.h"
00030 #include "ArLog.h"
00031 #include "ariaUtil.h"
00032 #include <stdarg.h>
00033
00034 std::list<std::string> ArArgumentParser::ourDefaultArgumentLocs;
00035 std::list<bool> ArArgumentParser::ourDefaultArgumentLocIsFile;
00040 AREXPORT ArArgumentParser::ArArgumentParser(int *argc, char **argv)
00041 {
00042 myArgc = argc;
00043 myArgv = argv;
00044 myUsingBuilder = false;
00045 myBuilder = NULL;
00046 myOwnBuilder = false;
00047
00048 myEmptyArg[0] = '\0';
00049 }
00050
00054 AREXPORT ArArgumentParser::ArArgumentParser(ArArgumentBuilder *builder)
00055 {
00056 myUsingBuilder = true;
00057 myBuilder = builder;
00058 myOwnBuilder = false;
00059 myEmptyArg[0] = '\0';
00060 }
00061
00062 AREXPORT ArArgumentParser::~ArArgumentParser()
00063 {
00064 if (myOwnBuilder)
00065 {
00066 delete myBuilder;
00067 myBuilder = NULL;
00068 }
00069 }
00070
00071 AREXPORT bool ArArgumentParser::checkArgumentVar(char *argument, ...)
00072 {
00073 char arg[2048];
00074 va_list ptr;
00075 va_start(ptr, argument);
00076 vsnprintf(arg, sizeof(arg), argument, ptr);
00077 va_end(ptr);
00078 return checkArgument(arg);
00079 }
00080
00081
00091 AREXPORT bool ArArgumentParser::checkArgument(const char *argument)
00092 {
00093 size_t i;
00094 std::string extraHyphen;
00095 extraHyphen = "-";
00096 extraHyphen += argument;
00097 for (i = 0; i < getArgc(); i++)
00098 {
00099 if (strcasecmp(argument, getArgv()[i]) == 0 ||
00100 strcasecmp(extraHyphen.c_str(), getArgv()[i]) == 0)
00101 {
00102 removeArg(i);
00103
00104
00105 return true;
00106 }
00107 }
00108 return false;
00109 }
00110
00132 AREXPORT bool ArArgumentParser::checkParameterArgumentStringVar(
00133 bool *wasReallySet, const char **dest, char *argument, ...)
00134 {
00135 char arg[2048];
00136 va_list ptr;
00137 va_start(ptr, argument);
00138 vsnprintf(arg, sizeof(arg), argument, ptr);
00139 va_end(ptr);
00140 return checkParameterArgumentString(arg, dest, wasReallySet);
00141 }
00142
00166 AREXPORT bool ArArgumentParser::checkParameterArgumentString(
00167 char *argument, const char **dest, bool *wasReallySet,
00168 bool returnFirst)
00169 {
00170 char *param;
00171 param = checkParameterArgument(argument, returnFirst);
00172
00173 if (param == NULL)
00174 {
00175 if (wasReallySet)
00176 *wasReallySet = false;
00177 return true;
00178 }
00179 else if (param[0] != '\0')
00180 {
00181 *dest = param;
00182 if (wasReallySet)
00183 *wasReallySet = true;
00184 return true;
00185 }
00186 else
00187 {
00188 ArLog::log(ArLog::Normal, "No argument given to %s", argument);
00189 return false;
00190 }
00191 }
00192
00216 AREXPORT bool ArArgumentParser::checkParameterArgumentBoolVar(
00217 bool *wasReallySet, bool *dest, char *argument, ...)
00218 {
00219 char arg[2048];
00220 va_list ptr;
00221 va_start(ptr, argument);
00222 vsnprintf(arg, sizeof(arg), argument, ptr);
00223 va_end(ptr);
00224 return checkParameterArgumentBool(arg, dest, wasReallySet);
00225 }
00226
00252 AREXPORT bool ArArgumentParser::checkParameterArgumentBool(char *argument,
00253 bool *dest,
00254 bool *wasReallySet,
00255 bool returnFirst)
00256 {
00257 char *param;
00258 param = checkParameterArgument(argument, returnFirst);
00259
00260 if (param == NULL)
00261 {
00262 if (wasReallySet)
00263 *wasReallySet = false;
00264 return true;
00265 }
00266 else if (param[0] != '\0')
00267 {
00268 if (strcasecmp(param, "true") == 0 || strcmp(param, "1") == 0)
00269 {
00270 *dest = true;
00271 if (wasReallySet)
00272 *wasReallySet = true;
00273 return true;
00274 }
00275 else if (strcasecmp(param, "false") == 0 || strcmp(param, "0") == 0)
00276 {
00277 *dest = false;
00278 if (wasReallySet)
00279 *wasReallySet = true;
00280 return true;
00281 }
00282 else
00283 {
00284 ArLog::log(ArLog::Normal,
00285 "Argument given to %s was not a bool (true, false, 1, 0) it was the string %s",
00286 argument, param);
00287 return false;
00288 }
00289
00290 }
00291 else
00292 {
00293 ArLog::log(ArLog::Normal, "No argument given to %s", argument);
00294 return false;
00295 }
00296
00297 }
00298
00320 AREXPORT bool ArArgumentParser::checkParameterArgumentIntegerVar(
00321 bool *wasReallySet, int *dest, char *argument, ...)
00322 {
00323 char arg[2048];
00324 va_list ptr;
00325 va_start(ptr, argument);
00326 vsnprintf(arg, sizeof(arg), argument, ptr);
00327 va_end(ptr);
00328 return checkParameterArgumentInteger(arg, dest, wasReallySet);
00329 }
00330
00354 AREXPORT bool ArArgumentParser::checkParameterArgumentInteger(
00355 char *argument, int *dest, bool *wasReallySet, bool returnFirst)
00356 {
00357 char *param;
00358 char *endPtr;
00359 int intVal;
00360
00361 param = checkParameterArgument(argument, returnFirst);
00362
00363 if (param == NULL)
00364 {
00365 if (wasReallySet)
00366 *wasReallySet = false;
00367 return true;
00368 }
00369 else if (param[0] != '\0')
00370 {
00371 intVal = strtol(param, &endPtr, 10);
00372 if (endPtr[0] == '\0')
00373 {
00374 *dest = intVal;
00375 if (wasReallySet)
00376 *wasReallySet = true;
00377 return true;
00378 }
00379 else
00380 {
00381 ArLog::log(ArLog::Normal,
00382 "Argument given to %s was not an integer it was the string %s",
00383 argument, param);
00384 return false;
00385 }
00386
00387 }
00388 else
00389 {
00390 ArLog::log(ArLog::Normal, "No argument given to %s", argument);
00391 return false;
00392 }
00393
00394 }
00395
00408 AREXPORT bool ArArgumentParser::checkParameterArgumentFloat(
00409 char *argument, float *dest, bool *wasReallySet, bool returnFirst)
00410 {
00411 char *param = checkParameterArgument(argument, returnFirst);
00412 if (param == NULL)
00413 {
00414 if (wasReallySet) *wasReallySet = false;
00415 return true;
00416 }
00417 else if (param[0] != '\0')
00418 {
00419 char *endPtr;
00420 float floatVal = strtod(param, &endPtr);
00421 if(endPtr == param)
00422 {
00423 ArLog::log(ArLog::Normal, "Argument given with %s was not a valid number", argument);
00424 return false;
00425 }
00426 else
00427 {
00428 *dest = floatVal;
00429 if (wasReallySet) *wasReallySet = true;
00430 return true;
00431 }
00432 }
00433 else
00434 {
00435 ArLog::log(ArLog::Normal, "No argument given with %s", argument);
00436 return false;
00437 }
00438 }
00439
00440
00452 AREXPORT char *ArArgumentParser::checkParameterArgumentVar(char *argument, ...)
00453 {
00454 char arg[2048];
00455 va_list ptr;
00456 va_start(ptr, argument);
00457 vsnprintf(arg, sizeof(arg), argument, ptr);
00458 va_end(ptr);
00459 return checkParameterArgument(arg);
00460 }
00474 AREXPORT char * ArArgumentParser::checkParameterArgument(char *argument,
00475 bool returnFirst)
00476 {
00477 char *ret;
00478 char *retRecursive;
00479 size_t i;
00480 std::string extraHyphen;
00481
00482 extraHyphen = "-";
00483 extraHyphen += argument;
00484
00485 for (i = 0; i < getArgc(); i++)
00486 {
00487 if (strcasecmp(argument, getArgv()[i]) == 0 ||
00488 strcasecmp(extraHyphen.c_str(), getArgv()[i]) == 0)
00489 {
00490
00491 if (getArgc() > i+1)
00492 {
00493 ret = getArgv()[i+1];
00494 }
00495 else
00496 {
00497 ret = myEmptyArg;
00498 }
00499
00500 removeArg(i);
00501
00502 if (ret != NULL && ret != myEmptyArg)
00503 removeArg(i);
00504
00505 if (returnFirst)
00506 {
00507 return ret;
00508 }
00509 else if ((retRecursive = checkParameterArgument(argument)) != NULL)
00510 {
00511 return retRecursive;
00512 }
00513
00514 else
00515 {
00516 return ret;
00517 }
00518 }
00519 }
00520 return NULL;
00521 }
00522
00523 void ArArgumentParser::removeArg(size_t which)
00524 {
00525 if (which >= getArgc())
00526 {
00527 ArLog::log(ArLog::Terse, "ArArgumentParser::removeArg: %d is greater than the number of arguments which is %d", which, getArgc());
00528 return;
00529 }
00530 if (myUsingBuilder)
00531 {
00532 myBuilder->removeArg(which);
00533 }
00534 else
00535 {
00536 size_t i;
00537 for (i = which; i < getArgc() - 1; i++)
00538 myArgv[i] = myArgv[i+1];
00539 *myArgc -= 1;
00540 }
00541 }
00542
00543 AREXPORT size_t ArArgumentParser::getArgc(void) const
00544 {
00545 if (myUsingBuilder)
00546 return myBuilder->getArgc();
00547 else
00548 return *myArgc;
00549 }
00550
00551 AREXPORT char** ArArgumentParser::getArgv(void) const
00552 {
00553 if (myUsingBuilder)
00554 return myBuilder->getArgv();
00555 else
00556 return myArgv;
00557 }
00558
00559 AREXPORT const char* ArArgumentParser::getArg(size_t whichArg) const
00560 {
00561 if (whichArg >= getArgc())
00562 return NULL;
00563 else
00564 return getArgv()[whichArg];
00565 }
00566
00567 AREXPORT void ArArgumentParser::log(void) const
00568 {
00569 size_t i;
00570 ArLog::log(ArLog::Terse, "Num arguments: %d", getArgc());
00571 for (i = 0; i < getArgc(); ++i)
00572 ArLog::log(ArLog::Terse, "Arg %d: %s", i, getArgv()[i]);
00573 }
00574
00575 AREXPORT void ArArgumentParser::addDefaultArgument(const char *argument, int position)
00576 {
00577 if (!myUsingBuilder)
00578 {
00579 myBuilder = new ArArgumentBuilder;
00580 myBuilder->addStringsAsIs(*myArgc, myArgv);
00581 myOwnBuilder = true;
00582 myUsingBuilder = true;
00583 }
00584 myBuilder->addPlain(argument, position);
00585 }
00586
00598 AREXPORT void ArArgumentParser::loadDefaultArguments(int position)
00599 {
00600 std::list<std::string>::iterator it;
00601 std::list<bool>::iterator bIt;
00602 const char *str;
00603 char *argumentsPtr;
00604 char arguments[1024];
00605
00606 if (!myUsingBuilder)
00607 {
00608 myBuilder = new ArArgumentBuilder;
00609 myBuilder->addStringsAsIs(*myArgc, myArgv);
00610 myOwnBuilder = true;
00611 myUsingBuilder = true;
00612 }
00613
00614 for (it = ourDefaultArgumentLocs.begin(),
00615 bIt = ourDefaultArgumentLocIsFile.begin();
00616 it != ourDefaultArgumentLocs.end();
00617 it++, bIt++)
00618 {
00619 str = (*it).c_str();
00620
00621 if (!(*bIt) && (argumentsPtr = getenv(str)) != NULL)
00622 {
00623 ArArgumentBuilder compressed;
00624 compressed.add(argumentsPtr);
00625 compressed.compressQuoted(true);
00626 myBuilder->addStringsAsIs(compressed.getArgc(), compressed.getArgv(),
00627 position);
00628 ArLog::log(ArLog::Normal,
00629 "Added arguments from environmental variable '%s'", str);
00630 }
00631
00632 else if ((*bIt) &&
00633 ArUtil::getStringFromFile(str, arguments, sizeof(arguments)))
00634 {
00635 ArArgumentBuilder compressed;
00636 compressed.add(arguments);
00637 compressed.compressQuoted(true);
00638 myBuilder->addStringsAsIs(compressed.getArgc(), compressed.getArgv(),
00639 position);
00640 ArLog::log(ArLog::Normal, "Added arguments from file '%s'",
00641 str);
00642 }
00643
00644
00645 else
00646 {
00647 ArLog::log(ArLog::Verbose,
00648 "Could not load from environmental variable or file '%s'",
00649 str);
00650 }
00651 }
00652 }
00653
00658 AREXPORT void ArArgumentParser::addDefaultArgumentFile(const char *file)
00659 {
00660 ourDefaultArgumentLocs.push_back(file);
00661 ourDefaultArgumentLocIsFile.push_back(true);
00662 }
00663
00664
00670 AREXPORT void ArArgumentParser::addDefaultArgumentEnv(const char *env)
00671 {
00672 ourDefaultArgumentLocs.push_back(env);
00673 ourDefaultArgumentLocIsFile.push_back(false);
00674 }
00675
00676 AREXPORT void ArArgumentParser::logDefaultArgumentLocations(void)
00677 {
00678 std::list<std::string>::iterator it;
00679 std::list<bool>::iterator bIt;
00680
00681 ArLog::log(ArLog::Normal,
00682 "Default argument files or environmental variables:");
00683 for (it = ourDefaultArgumentLocs.begin(),
00684 bIt = ourDefaultArgumentLocIsFile.begin();
00685 it != ourDefaultArgumentLocs.end();
00686 it++, bIt++)
00687 {
00688 if (*bIt)
00689 ArLog::log(ArLog::Normal, "%10s%-10s%s", "", "file", (*it).c_str());
00690 else
00691 ArLog::log(ArLog::Normal, "%10s%-10s%s", "", "envVar", (*it).c_str());
00692 }
00693 }
00705 AREXPORT bool ArArgumentParser::checkHelpAndWarnUnparsed(
00706 unsigned int numArgsOkay)
00707 {
00708 if (checkArgument("-help") || checkArgument("-h") || checkArgument("/?") ||
00709 checkArgument("/h"))
00710 return false;
00711
00712 if (getArgc() <= 1 + numArgsOkay)
00713 return true;
00714
00715 size_t i;
00716 char buf[2048];
00717 sprintf(buf, "Unhandled arguments to program:");
00718 for (i = 1 + (int)numArgsOkay; i < getArgc(); i++)
00719 sprintf(buf, "%s %s", buf, getArg(i));
00720 ArLog::log(ArLog::Normal, buf);
00721 ArLog::log(ArLog::Normal,
00722 "Program will continue but to see the help listing type '%s -help'",
00723 getArg(0));
00724 return true;
00725 }
00726