This is cmdargs.c in view mode; [Download] [Up]
//------------------------------------------------------------------------ // ^FILE: cmdargs.c - implement the various predefined CmdArg subclasses // // ^DESCRIPTION: // This file implements the CmdArg derived classes that are declared // in <cmdargs.h> // // ^HISTORY: // 03/25/92 Brad Appleton <brad@ssd.csd.harris.com> Created // // 03/03/93 Brad Appleton <brad@ssd.csd.harris.com> // - Added exit_handler() and quit() member-functions to CmdLine //-^^--------------------------------------------------------------------- #include <stdlib.h> #include <iostream.h> #include <string.h> #include <ctype.h> #include "cmdargs.h" #include "exits.h" #include "fifolist.h" // return values for operator() enum { SUCCESS = 0, FAILURE = -1 } ; //----------------------------------------------------------------------------- // ^FUNCTION: compile, operator() - handle an argument from the command-line // // ^SYNOPSIS: // int operator()(arg, cmd); // int compile(arg, cmd, value); // int compile(arg, cmd, value, default_value); // // ^PARAMETERS: // const char * & arg; // -- the prospective value for this command argument. // upon returning this value should be updated to point to the first // character of "arg" that was NOT used as part of the value for this // argument (set "arg" to NULL if all of it was used). // // CmdLine & cmd; // -- the command that matched this argument on its command-line // // <Type> & value; // -- The internal value (of some appropriate type) that is "managed" // by this command argument. // // unsigned default_value; // -- What to assign to "value" if "arg" is NOT a value for this command // argument. // // ^DESCRIPTION: // These member functions are responsible for taking whatever action // is appropriate when its corresponding command argument is matched // on the command-line. For argument-types that simply "compile" // their argument into some kind of internal value, "compile()" does // all the work and operator() merely calls compile() with the proper // value as a reference parameter. // // ^REQUIREMENTS: // The "arg_flags" data member of this command-argument must have been // set appropriately (by "cmd") to indicate to us exactly how "arg" was // specified on the command-line for this (and only this) occurrence of // "arg". // // ^SIDE-EFFECTS: // - If (cmd.flags() & QUIET) is NOT TRUE and FAILURE is to be returned, // then error messages should be printed using cmd.error(). // // - arg is modified to be NULL of to point to the unused portion of itself. // // - If (cmd.flags() & TEMP) is TRUE and we need the value of "arg" // to stick around, then storage is allocated in order to make // a copy of "arg" (and the command-argument is responsible for // de-allocating this storage). // // ^RETURN-VALUE: // FAILURE (non-zero) If something went wrong when performing the // desired actions for this command-argument. // A common problem would be that "arg" is // syntactically incorrect. // // SUCCESS (zero) If "arg" is NULL and/or we were able to succesfully // perform all desired actions for this command argument. //-^^-------------------------------------------------------------------------- //-------------------------------------------------------------- Dummy Argument CmdArgDummy::~CmdArgDummy(void) {} int CmdArgDummy::is_dummy(void) { return 1; } // For a CmdArgDummy - operator() is a No-OP and should NEVER // be called. // int CmdArgDummy::operator()(const char * & , CmdLine & ) { return SUCCESS; } //-------------------------------------------------------------- Usage Argument CmdArgUsage::CmdArgUsage(char optchar, const char * keyword, const char * description, ostream * osp) : CmdArg(optchar, keyword, description, CmdArg::isOPT), os_ptr(osp) { if (os_ptr == NULL) os_ptr = &cout; } CmdArgUsage::~CmdArgUsage(void) {} void CmdArgUsage::ostream_ptr(ostream * osp) { os_ptr = (osp != NULL) ? osp : &cout ; } // Just need to call cmd.usage and exit. // int CmdArgUsage::operator()(const char * & , CmdLine & cmd) { cmd.usage(*os_ptr, CmdLine::VERBOSE_USAGE); cmd.quit(e_USAGE); return SUCCESS; } //----------------------------------------------------------- Integer Arguments CmdArgIntCompiler::~CmdArgIntCompiler(void) {} // Compile a string into an integer value. int CmdArgIntCompiler::compile(const char * & arg, CmdLine & cmd, int & value) { const char * ptr = NULL ; long result = 0 ; if (arg == NULL) { return SUCCESS ; // no value given - nothing to do } else if (! *arg) { if (! (cmd.flags() & CmdLine::QUIET)) { cmd.error() << "empty integer value specified." << endl ; } return FAILURE ; } // compile the string into an integer result = ::strtol(arg, (char **) &ptr, 0); // watch out for -c0xa vs -axc0! if (ptr == arg) { // do we have a valid integer? if (! (cmd.flags() & CmdLine::QUIET)) { cmd.error() << "invalid integer value \"" << arg << "\"." << endl ; } return FAILURE ; } value = (int) result; arg = ptr; return SUCCESS ; } CmdArgInt::~CmdArgInt(void) {} int CmdArgInt::operator()(const char * & arg, CmdLine & cmd) { return compile(arg, cmd, val); } ostream & operator<<(ostream & os, const CmdArgInt & int_arg) { return (os << (int) int_arg) ; } //---------------------------------------------------- Floating-point Arguments CmdArgFloatCompiler::~CmdArgFloatCompiler(void) {} // Compile a string into a floating-point value. int CmdArgFloatCompiler::compile(const char * & arg, CmdLine & cmd, float & value) { const char * ptr = NULL ; double result = 0 ; if (arg == NULL) { return SUCCESS ; // no value given -- nothing to do } else if (! *arg) { if (! (cmd.flags() & CmdLine::QUIET)) { cmd.error() << "empty floating-point value specified." << endl ; } return FAILURE ; } result = ::strtod(arg, (char **) &ptr); // compile the string into a float if (ptr == arg) { // do we have a valid float? if (! (cmd.flags() & CmdLine::QUIET)) { cmd.error() << "invalid floating-point value \"" << arg << "\"." << endl ; } return FAILURE ; } value = (float) result; arg = ptr; return SUCCESS ; } CmdArgFloat::~CmdArgFloat(void) {} int CmdArgFloat::operator()(const char * & arg, CmdLine & cmd) { return compile(arg, cmd, val); } ostream & operator<<(ostream & os, const CmdArgFloat & float_arg) { return (os << (float) float_arg) ; } //--------------------------------------------------------- Character Argumrnts CmdArgCharCompiler::~CmdArgCharCompiler(void) {} int CmdArgCharCompiler::compile(const char * & arg, CmdLine & cmd, char & value) { if (arg == NULL) { return SUCCESS ; // no value given - nothing to do } // If "arg" contains more than 1 character, then the other characters // are either extraneous, or they are options (bundled together). // if (*arg && *(arg+1) && ((! (flags() & CmdArg::OPTION)) || (flags() & CmdArg::VALSEP))) { if (! (cmd.flags() & CmdLine::QUIET)) { cmd.error() << "invalid character value \"" << arg << "\"." << endl ; } return FAILURE ; } value = *arg; if (*arg) { ++arg; } else { arg = NULL; } return SUCCESS ; } CmdArgChar::~CmdArgChar(void) {} int CmdArgChar::operator()(const char * & arg, CmdLine & cmd) { return compile(arg, cmd, val); } ostream & operator<<(ostream & os, const CmdArgChar & char_arg) { return (os << (char) char_arg) ; } //------------------------------------------------------------ String Arguments typedef CmdArgStrCompiler::casc_string CmdArgString ; #ifndef __GNUG__ CmdArgString::~casc_string(void) { if (is_alloc) delete [] (char *)str; } #endif // Copy a string (allocating storage if necessary) void CmdArgString::copy(unsigned is_temporary, const char * s) { if (is_alloc) delete [] (char *)str; is_alloc = (is_temporary) ? 1 : 0; str = s; if (is_alloc && s) { char * new_s = new char[::strlen(s) + 1] ; (void) ::strcpy(new_s, s); str = new_s; } } CmdArgStrCompiler::~CmdArgStrCompiler(void) {} int CmdArgStrCompiler::compile(const char * & arg, CmdLine & cmd, CmdArgString & value) { if (arg == NULL) { return SUCCESS; // no value given -- nothing to do } value.copy((cmd.flags() & CmdLine::TEMP), arg); arg = NULL; return SUCCESS; } CmdArgStr::~CmdArgStr(void) {} int CmdArgStr::operator()(const char * & arg, CmdLine & cmd) { return compile(arg, cmd, val); } ostream & operator<<(ostream & os, const CmdArgStrCompiler::casc_string & str) { return (os << str.str) ; } ostream & operator<<(ostream & os, const CmdArgStr & str_arg) { return (os << (const char *) str_arg) ; } //-------------------------------------------------------------- List Arguments //------------------- Integer List ------------------- DECLARE_FIFO_LIST(IntList, int); struct CmdArgIntListPrivate { IntList list; IntListArray array; CmdArgIntListPrivate(void); } ; CmdArgIntListPrivate::CmdArgIntListPrivate(void) : array(list) { list.self_cleaning(1); } // Compile the argument into an integer and append it to the list int CmdArgIntList::operator()(const char * & arg, CmdLine & cmd) { int value; const char * save_arg = arg; int rc = compile(arg, cmd, value); if (save_arg && (rc == SUCCESS)) { if (val == NULL) val = new CmdArgIntListPrivate; int * new_value = new int; *new_value = value; val->list.add(new_value); } return rc; } unsigned CmdArgIntList::count(void) const { return (val) ? val->list.count() : 0 ; } int & CmdArgIntList::operator[](unsigned index) { return val->array[index]; } CmdArgIntList::~CmdArgIntList(void) {} //------------------- Float List ------------------- DECLARE_FIFO_LIST(FloatList, float); struct CmdArgFloatListPrivate { FloatList list; FloatListArray array; CmdArgFloatListPrivate(void); } ; CmdArgFloatListPrivate::CmdArgFloatListPrivate(void) : array(list) { list.self_cleaning(1); } // Compile the argument into a float and append it to the list int CmdArgFloatList::operator()(const char * & arg, CmdLine & cmd) { float value; const char * save_arg = arg; int rc = compile(arg, cmd, value); if (save_arg && (rc == SUCCESS)) { if (val == NULL) val = new CmdArgFloatListPrivate; float * new_value = new float; *new_value = value; val->list.add(new_value); } return rc; } unsigned CmdArgFloatList::count(void) const { return (val) ? val->list.count() : 0 ; } float & CmdArgFloatList::operator[](unsigned index) { return val->array[index]; } CmdArgFloatList::~CmdArgFloatList(void) {} //------------------- String List ------------------- DECLARE_FIFO_LIST(StringList, CmdArgString); struct CmdArgStrListPrivate { StringList list; StringListArray array; CmdArgStrListPrivate(void); } ; CmdArgStrListPrivate::CmdArgStrListPrivate(void) : array(list) { list.self_cleaning(1); } int CmdArgStrList::operator()(const char * & arg, CmdLine & cmd) { CmdArgString * value = new CmdArgString ; const char * save_arg = arg; int rc = compile(arg, cmd, *value); if (save_arg && (rc == SUCCESS)) { if (val == NULL) val = new CmdArgStrListPrivate; val->list.add(value); } else { delete value; } return rc; } unsigned CmdArgStrList::count(void) const { return (val) ? val->list.count() : 0 ; } CmdArgString & CmdArgStrList::operator[](unsigned index) { return val->array[index]; } CmdArgStrList::~CmdArgStrList(void) {} //----------------------------------------------------------- Boolean Arguments CmdArgBoolCompiler::~CmdArgBoolCompiler(void) {} int CmdArgBoolCompiler::compile(const char * & arg, CmdLine & cmd, unsigned & value, unsigned default_value) { if (arg == NULL) { // if no argument was given use the default value = default_value ; } else { char ch = *arg; const char * kwd = arg++; // Map the argument to the corresponding value. We will accept // the following (case insensitive): // // "+", "1", "ON", or "YES" means set the value // "-", "0", "OFF", or "NO" means clear the value // "~", "^", or "!" means toggle the value // // Anything else is considered to be an argument that is NOT // meant for us but for some other argument so we just use the // default value that was supplied and return SUCCESS. // if (isupper(ch)) ch = tolower(ch); switch(ch) { case '1' : case '+' : value = 1 ; break; case '0' : case '-' : value = 0 ; break; case '~' : case '^' : case '!' : value = (! value) ; break; default: if (flags() & CmdArg::KEYWORD) { char ch2 = *arg; arg = NULL; if (cmd.strmatch(kwd, "yes") != CmdLine::str_NONE) { value = 1 ; return SUCCESS ; } else if (cmd.strmatch(kwd, "no") != CmdLine::str_NONE) { value = 0 ; return SUCCESS ; } else if (cmd.strmatch(kwd, "true") != CmdLine::str_NONE) { value = 1 ; return SUCCESS ; } else if (cmd.strmatch(kwd, "false") != CmdLine::str_NONE) { value = 0 ; return SUCCESS ; } else if ((ch == 'o') && (! ch2)) { // ambiguous - could be "ON" or "OFF" if (! (cmd.flags() & CmdLine::QUIET)) { cmd.error() << "ambiguous boolean value \"" << kwd << "\"." << endl ; } return FAILURE ; } else if (cmd.strmatch(kwd, "on") != CmdLine::str_NONE) { value = 1 ; return SUCCESS ; } else if (cmd.strmatch(kwd, "off") != CmdLine::str_NONE) { value = 0 ; return SUCCESS ; } else { // unknown if (! (cmd.flags() & CmdLine::QUIET)) { cmd.error() << "unknown boolean value \"" << kwd << "\"." << endl ; } return FAILURE ; } } //if keyword arg = kwd; // no characters used! value = default_value ; break; } //switch } //else return SUCCESS ; } ostream & operator<<(ostream & os, const CmdArgBool & bool_arg) { return (os << ((int)bool_arg)) ; } //------------------------------------------------------------------ CmdArgBool CmdArgBool::~CmdArgBool(void) {} int CmdArgBool::operator()(const char * & arg, CmdLine & cmd) { unsigned value = val; int rc = compile(arg, cmd, value, 1); val = value; return rc; } //----------------------------------------------------------------- CmdArgClear CmdArgClear::~CmdArgClear(void) {} int CmdArgClear::operator()(const char * & arg, CmdLine & cmd) { unsigned value = val; int rc = compile(arg, cmd, value, 0); val = value; return rc; } //---------------------------------------------------------------- CmdArgToggle CmdArgToggle::~CmdArgToggle(void) {} int CmdArgToggle::operator()(const char * & arg, CmdLine & cmd) { unsigned value = val; int rc = compile(arg, cmd, value, (! value)); val = value; return rc; } //--------------------------------------------------------------- CmdArgBoolRef CmdArgBoolRef::~CmdArgBoolRef(void) {} int CmdArgBoolRef::operator()(const char * & arg, CmdLine & cmd) { unsigned val = ref; int rc = ref.compile(arg, cmd, val, 1); ref = val; return rc; } //-------------------------------------------------------------- CmdArgClearRef CmdArgClearRef::~CmdArgClearRef(void) {} int CmdArgClearRef::operator()(const char * & arg, CmdLine & cmd) { unsigned val = ref; int rc = ref.compile(arg, cmd, val, 0); ref = val; return rc; } //------------------------------------------------------------- CmdArgToggleRef CmdArgToggleRef::~CmdArgToggleRef(void) {} int CmdArgToggleRef::operator()(const char * & arg, CmdLine & cmd) { unsigned val = ref; int rc = ref.compile(arg, cmd, val, (! val)); ref = val; return rc; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.