// // Copyright 1998-2000 by Craig Stuart Sapp, All Rights Reserved. // Programmer: Craig Stuart Sapp // Creation Date: Sun Apr 5 13:07:18 PDT 1998 // Last Modified: Sat Mar 27 18:17:06 PST 1999 // Last Modified: Thu Apr 13 14:02:52 PDT 2000 (added 2nd define function) // Last Modified: Fri May 5 17:52:01 PDT 2000 (added --options suppression) // Last Modified: Tue May 1 01:25:58 PDT 2001 (fixed getArgumentCount()) // Filename: ...sig/maint/code/sigBase/Options.cpp // Web Address: http://sig.sapp.org/src/sigBase/Options.cpp // Documentation: http://sig.sapp.org/doc/classes/Options // Syntax: C++ // // Description: Handles command-line options in a graceful manner. // int optionListCompare(const void* a, const void* b); #include "Options.h" #include "Options_private.h" #include #include #include #include ////////////////////////////// // // Options::Options -- // Options::Options(void) { optionFlag = '-'; gargc = -1; gargv = NULL; argument.setSize(0); argument.allowGrowth(); optionRegister.setSize(0); optionRegister.allowGrowth(); optionList.setSize(0); optionList.allowGrowth(); processedQ = 0; sortedQ = 0; commandString = NULL; options_error_check = 1; suppressQ = 0; optionsArgument = 0; } Options::Options(int argc, char** argv) { optionFlag = '-'; gargc = -1; gargv = NULL; argument.setSize(0); argument.allowGrowth(); optionRegister.setSize(0); optionRegister.allowGrowth(); optionList.setSize(0); optionList.allowGrowth(); processedQ = 0; sortedQ = 0; commandString = NULL; options_error_check = 1; suppressQ = 0; optionsArgument = 0; setOptions(argc, argv); } ////////////////////////////// // // Options::~Options -- // Options::~Options() { reset(); } ////////////////////////////// // // Options::argc -- returns the argument count as from main(). // int Options::argc(void) const { return gargc; } ////////////////////////////// // // Options::argv -- returns the arguments strings as from main(). // char** Options::argv(void) const { return gargv; } ////////////////////////////// // // Options::define -- define an option entry in the option register // void Options::define(const char* aDefinition) { sortedQ = 0; // have to sort option list later option_register* definitionEntry; option_list* optionListEntry; // error if the definition string doesn't contain an equals sign. if (strchr(aDefinition, '=') == NULL) { std::cout << "Error: no \"=\" in option definition: " << aDefinition << std::endl; exit(1); } // get the length of the definition string int len = strlen(aDefinition); // put space before and after the equals sign so that strtok works char* definitionString; definitionString = new char[len + 3]; int i = 0; while (aDefinition[i] != '=' && i < len) { definitionString[i] = aDefinition[i]; i++; } definitionString[i] = ' '; i++; definitionString[i] = '='; i++; definitionString[i] = ' '; for (int k=i; ksetType(optionType); i++; // check to make sure that the type is correct. if (optionType != OPTION_STRING_TYPE && optionType != OPTION_INT_TYPE && optionType != OPTION_FLOAT_TYPE && optionType != OPTION_DOUBLE_TYPE && optionType != OPTION_BOOLEAN_TYPE && optionType != OPTION_CHAR_TYPE ) { std::cout << "Error: unknown option type \'" << optionType << "\' in defintion: " << aDefinition << std::endl; exit(1); } // skip any white space after option type. while (isspace(definitionString[i]) && i < len) { i++; } // there can only be two characters now: '\0' or ':' if (i >= len || definitionString[i] == '\0') { goto option_finish; } else if (i= len || definitionString[i] == '\0') { goto option_finish; } // now at beginnng of default option string which continues // until the end of the definition string. definitionEntry->setDefault(&definitionString[i]); option_finish: optionRegister.append(definitionEntry); delete [] definitionString; delete [] tempstr; } void Options::define(const char* aDefinition, const char* description) { define(aDefinition); // now find some place to store the description... } ////////////////////////////// // // Options::getArg -- returns the specified argument. // argurment 0 is the command name. // char* Options::getArg(int index) { if (index < 0 || index >= argument.getSize()) { std::cout << "Error: argument " << index << " does not exist." << std::endl; exit(1); } return argument[index]; } ////////////////////////////// // // Options::getArgument -- same as getArg // char* Options::getArgument(int index) { return getArg(index); } ////////////////////////////// // // Options::getArgCount -- number of arguments on command line. // does not count the options or the command name. // int Options::getArgCount(void) { return argument.getSize() - 1; } ////////////////////////////// // // Options::getArgumentCount -- Same as getArgCount(). // int Options::getArgumentCount(void) { return getArgCount(); } ////////////////////////////// // // Options::getBoolean -- returns true if the option was // used on the command line. // int Options::getBoolean(const char* optionName) { int index = getRegIndex(optionName); if (index < 0) { return 0; } if (optionRegister[index]->getModifiedQ() == 1) { return 1; } else { return 0; } } ////////////////////////////// // // Options::getCommand -- returns argv[0] // const char* Options::getCommand(void) { if (argument.getSize() == 0) { return ""; } else { return argument[0]; } } ////////////////////////////// // // Options::getCommandLine -- returns a string which contains the // command-line call to the program. // const char* Options::getCommandLine(void) { if (commandString != NULL) { return commandString; } int length = 0; int i; for (i=0; igetName()) == 0) { return optionRegister[optionList[i]->getIndex()]->getDefinition(); } } return (const char*)NULL; } ////////////////////////////// // // Options::getDouble -- returns the double float associated // with the given option. Returns 0 if there is no // number associated with the option. // double Options::getDouble(const char* optionName) { return strtod(getString(optionName), (char**)NULL); } ////////////////////////////// // // Options::getFlag -- // char Options::getFlag(void) { return optionFlag; } ////////////////////////////// // // Options::getFloat -- returns the floating point number // associated with the given option. // float Options::getFloat(const char* optionName) { return (float)getDouble(optionName); } ////////////////////////////// // // Options::getInt -- returns the integer argument. Can handle // hexadecimal, decimal, and octal written in standard // C syntax. // int Options::getInt(const char* optionName) { return (int)strtol(getString(optionName), (char**)NULL, 0); } int Options::getInteger(const char* optionName) { return getInt(optionName); } ////////////////////////////// // // Options::getString -- // const char* Options::getString(const char* optionName) { int index = getRegIndex(optionName); if (index < 0) { return "UNKNOWN OPTION"; } else { return optionRegister[index]->getOption(); } } ////////////////////////////// // // Options::optionsArg -- returns true if the --options is present // on the command line, otherwise returns false. // int Options::optionsArg(void) { return optionsArgument; } ////////////////////////////// // // Options::print -- // void Options::print(void) { for (int i=0; igetDefinition() << std::endl; } } ////////////////////////////// // // Options::reset -- // void Options::reset(void) { int i; for (i=0; isetModified(aString); } ////////////////////////////// // // setOptions -- // void Options::setOptions(int argc, char** argv) { processedQ = 0; gargc = argc; gargv = argv; } ////////////////////////////// // // Options:getType -- returns the type of the option // char Options::getType(const char* optionName) { int index = getRegIndex(optionName); if (index < 0) { return -1; } else { return optionRegister[getRegIndex(optionName)]->getType(); } } ////////////////////////////// // // Options::process -- same as verify // default values: error_check = 1, suppress = 0; // void Options::process(int argc, char** argv, int error_check, int suppress) { setOptions(argc, argv); verify(error_check, suppress); } void Options::process(int error_check, int suppress) { verify(error_check, suppress); } ////////////////////////////// // // Options::verify -- // default value: error_check = 1, suppress = 0; // void Options::verify(int error_check, int suppress) { options_error_check = error_check; int gargp = 1; int optionend = 0; if (suppress) { suppressQ = 1; } else { suppressQ = 0; } // if calling verify again, must remove previous argument list. if (argument.getSize() != 0) { for (int j=0; jgetIndex(); } else if (strcmp("options", optionName) == 0) { print(); exit(1); } if (options_error_check) { std::cout << "Error: unknown option \"" << optionName << "\"." << std::endl; print(); exit(1); } return -1; } ////////////////////////////// // // optionQ -- returns true if the string is an option // "--" is not an option, also '-' is not an option. // aString is assumed to not be NULL. // int Options::optionQ(const char* aString, int& argp) { if (aString[0] == getFlag()) { if (aString[1] == '\0') { argp++; return 0; } else if (aString[1] == getFlag()) { if (aString[2] == '\0') { argp++; return 0; } else { return 1; } } else { return 1; } } else { return 0; } } ////////////////////////////// // // sortOptionNames -- // void Options::sortOptionNames(void) { qsort(optionList.getBase(), optionList.getSize(), sizeof(option_list*), optionListCompare); sortedQ = 1; } ////////////////////////////// // // storeOption -- // #define OPTION_FORM_SHORT 0 #define OPTION_FORM_LONG 1 #define OPTION_FORM_CONTINUE 2 int Options::storeOption(int gargp, int& position, int& running) { int optionForm; char tempname[1024]; char optionType = '\0'; if (running) { optionForm = OPTION_FORM_CONTINUE; } else if (gargv[gargp][1] == getFlag()) { optionForm = OPTION_FORM_LONG; } else { optionForm = OPTION_FORM_SHORT; } switch (optionForm) { case OPTION_FORM_CONTINUE: position++; tempname[0] = gargv[gargp][position]; tempname[1] = '\0'; optionType = getType(tempname); if (optionType != OPTION_BOOLEAN_TYPE) { running = 0; position++; } break; case OPTION_FORM_SHORT: position = 1; tempname[0] = gargv[gargp][position]; tempname[1] = '\0'; optionType = getType(tempname); if (optionType != OPTION_BOOLEAN_TYPE) { position++; } break; case OPTION_FORM_LONG: position = 2; while (gargv[gargp][position] != '=' && gargv[gargp][position] != '\0') { tempname[position-2] = gargv[gargp][position]; position++; } tempname[position-2] = '\0'; optionType = getType(tempname); if (optionType == -1) { // suppressed --options option optionsArgument = 1; break; } if (gargv[gargp][position] == '=') { if (optionType == OPTION_BOOLEAN_TYPE) { std::cout << "Error: boolean variable cannot have any options: " << tempname << std::endl; exit(1); } position++; } break; } if (optionType == -1) { // suppressed --options option optionsArgument = 1; gargp++; position = 0; return gargp; } if (gargv[gargp][position] == '\0' && optionType != OPTION_BOOLEAN_TYPE) { gargp++; position = 0; } if (optionForm != OPTION_FORM_LONG && optionType == OPTION_BOOLEAN_TYPE && gargv[gargp][position+1] != '\0') { running = 1; } else if (optionType == OPTION_BOOLEAN_TYPE && gargv[gargp][position+1] == '\0') { running = 0; } if (gargp >= gargc) { std::cout << "Error: last option requires a parameter" << std::endl; exit(1); } setModified(tempname, &gargv[gargp][position]); if (!running) { gargp++; } return gargp; } /////////////////////////////////////////////////////////////////////////// // // helping function // ////////////////////////////// // // optionListCompare -- for sorting the option list // int optionListCompare(const void* a, const void* b) { //cerr << " comparing: " << (*((option_list**)a))->getName() // << " i=" << (*((option_list**)a))->getIndex() // << " :to: " // << (*((option_list**)b))->getName() // << " i=" << (*((option_list**)b))->getIndex() << std::endl; return strcmp((*((option_list**)a))->getName(), (*((option_list**)b))->getName()); } // md5sum: 63584ffabc92170fdb9ef5caedb5a3f6 - Options.cpp =css= 20030102