// // Programmer: Craig Stuart Sapp // Copyright: Copyright 1998-1999 Craig Stuart Sapp, All Rights Reserved // Creation Date: Sun Apr 5 13:07:18 PDT 1998 // Last Modified: Mon Apr 6 21:33:54 PDT 1998 // Last Modified: Mon Jan 11 00:32:54 PST 1999 // Last Modified: Sat Mar 27 18:17:06 PST 1999 // Filename: ...sig/code/base/Options.cpp // Syntax: C++ // 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; } 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; 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) { cout << "Error: no \"=\" in option definition: " << aDefinition << 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 ) { cout << "Error: unknown option type \'" << optionType << "\' in defintion: " << aDefinition << 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; } ////////////////////////////// // // Options::getArg -- returns the specified argument. // argurment 0 is the command name. // char* Options::getArg(int index) { if (index < 0 || index >= argument.getSize()) { cout << "Error: argument " << index << " does not exist." << 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 -- // int Options::getArgumentCount(void) { return getArgumentCount(); } ////////////////////////////// // // Options::getBoolean -- returns true if the option was // used on the command line. // int Options::getBoolean(const char* optionName) { if (optionRegister[getRegIndex(optionName)]->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 ind = getRegIndex(optionName); return optionRegister[ind]->getOption(); } ////////////////////////////// // // Options::print -- // void Options::print(void) { for (int i=0; igetDefinition() << 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) { return optionRegister[getRegIndex(optionName)]->getType(); } ////////////////////////////// // // Options::process -- same as verify // default value: error_check = 1; // void Options::process(int argc, char** argv, int error_check) { setOptions(argc, argv); verify(error_check); } void Options::process(int error_check) { verify(); } ////////////////////////////// // // Options::verify -- // default value: error_check = 1; // void Options::verify(int error_check) { options_error_check = error_check; int gargp = 1; int optionend = 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) { cout << "Error: unknown option \"" << optionName << "\"." << endl; } exit(1); return 0; // for dumb visual C++ v5.0 compiler } ////////////////////////////// // // 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; 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 (gargv[gargp][position] == '=') { if (optionType == OPTION_BOOLEAN_TYPE) { cout << "Error: boolean variable cannot have any options: " << tempname << endl; exit(1); } position++; } break; } 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) { cout << "Error: last option requires a parameter" << endl; exit(1); } setModified(tempname, &gargv[gargp][position]); if (!running) { gargp++; } return gargp; } /////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // optionListCompare -- // 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() << endl; return strcmp((*((option_list**)a))->getName(), (*((option_list**)b))->getName()); }