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

ArArgumentParser.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
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 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
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       // MPL took this out so you could add the same arg multiple times
00105       //checkArgument(argument);
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       // see if we have a ret, we don't if the ret would be beyond argc
00413       if (getArgc() > i+1)
00414       {
00415         ret = getArgv()[i+1];
00416       }
00417       else
00418       {
00419         ret = myEmptyArg;
00420       }
00421       // remove our argument
00422       removeArg(i);
00423       // if we have a return remove that one too
00424       if (ret != NULL && ret != myEmptyArg)
00425         removeArg(i);
00426       // now see if there are any more, if so return that
00427       if (returnFirst)
00428       {
00429         return ret;
00430       }
00431       else if ((retRecursive = checkParameterArgument(argument)) != NULL)
00432       {
00433         return retRecursive;
00434       }
00435       // otherwise return what we found
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     // see if its an environmental variable
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     // see if we have a file
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     // the file or env didn't exit
00559     // this'll return true otherwise it'll return false)
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 

Generated on Wed Oct 19 12:56:34 2005 for Aria by  doxygen 1.4.0