Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

ArArgumentParser.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (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      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
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       // MPL took this out so you could add the same arg multiple times
00104       //checkArgument(argument);
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       // see if we have a ret, we don't if the ret would be beyond argc
00491       if (getArgc() > i+1)
00492       {
00493     ret = getArgv()[i+1];
00494       }
00495       else
00496       {
00497     ret = myEmptyArg;
00498       }
00499       // remove our argument
00500       removeArg(i);
00501       // if we have a return remove that one too
00502       if (ret != NULL && ret != myEmptyArg)
00503     removeArg(i);
00504       // now see if there are any more, if so return that
00505       if (returnFirst)
00506       {
00507     return ret;
00508       }
00509       else if ((retRecursive = checkParameterArgument(argument)) != NULL)
00510       {
00511     return retRecursive;
00512       }
00513       // otherwise return what we found
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     // see if its an environmental variable
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     // see if we have a file
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     // the file or env didn't exit
00644     // this'll return true otherwise it'll return false)
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 

Generated on Tue Feb 20 10:51:38 2007 for Aria by  doxygen 1.4.0