Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

pgetopt.C

Go to the documentation of this file.
00001 
00002 //  pgetopt.C: portable and simplified version of getopt() in UNIX, system V
00003 //.............................................................................
00004 //    version 1:  Nov 1989   Piet Hut               email: piet@iassns.bitnet
00005 //                           Institute for Advanced Study, Princeton, NJ, USA
00006 //    version 2:  Dec 1992   Piet Hut  --  adopted to the new C++-based starlab
00007 //    version 3:  Aug 1999   Steve McMillan
00008 //                              allow up to 16 arguments per option
00009 //                              allow single optional arguments
00010 //.............................................................................
00011 //  non-local function: 
00012 //    pgetopt
00013 //.............................................................................
00014 //
00015 //  Command line argument passing is done in System V UNIX style. However,
00016 //  instead of the function  getopt() , we use a private, portable version
00017 //  pgetopt(), given here.  The reason for providing our own function is that
00018 //  there are non-system V UNIX versions, such as some Berkeley UNICES, which
00019 //  do not provide  getopt().  By always using our own  pgetopt() we guarantee
00020 //  uniform behavior, independent of the UNIX version used.
00021 //
00022 //     Restrictions: the length of an option is one character, and the argument
00023 //                   has to follow the corresponding option, but separated by
00024 //                   a space (or tab).
00025 //                   Options have to start with a minus sign, but more than one
00026 //                   option can be combined after the same minus sign.
00027 //
00028 //  Examples: The following command lines all give the same effect:
00029 //              mumble -a -b 10 -c
00030 //              mumble  -c -a -b 10
00031 //              mumble -b 10 -ca
00032 //              mumble -acb 10
00033 //  but the following versions are illegal, and will give error messages:      
00034 //              mumble -a -b10 -c
00035 //              mumble -ab10c
00036 //              mumble -a -c -b
00037 //.............................................................................
00038 
00039 #include "stdinc.h"
00040 
00041 #ifndef TOOLBOX
00042 
00043 #define VERSION_OPTION_A   "-version"
00044 #define VERSION_OPTION_B   "--version"
00045 
00046 char *poptarg;                          // global variable
00047 
00048 // New version (Steve, 8/99): allow up to 16 numeric arguments to be
00049 // associated with an option.  Store the pointers in the global array
00050 // poparr[N_POP_ARG].  Retain poptarg for compatibility, but note that
00051 // poparr[0] is the same thing.
00052 
00053 #define N_POP_ARG       16
00054 
00055 char *poparr[N_POP_ARG];                // global array
00056 
00057 //-----------------------------------------------------------------------------
00058 //  pgetopt  --  each call to  pgetopt()  returns the next option encountered
00059 //               on the command line, starting from the beginning. If the 
00060 //               option occurs in the  optstr  string as well, the option 
00061 //               itself is returned (as the int value of the character; 
00062 //               options are limited to one char). Otherwise, the character '?'
00063 //               is returned. If the end of the string is reached, the value 
00064 //               -1 is returned.  If an option is followed by the character ':'
00065 //               in  optstr , then a command line argument is expected, 
00066 //               separated by spaces. If such an argument if found, the pointer
00067 //                poptarg  is pointed at that string, so that the calling 
00068 //               function can access the argument.  If such an argument is not
00069 //               found, an error message is given.
00070 //
00071 //               ..............................................................
00072 //
00073 //               See above note for extension to this scheme, as of 8/99.
00074 //               Also added optional arguments, indicated by "." in optstr.
00075 //
00076 //               Optional arguments *may not* start with "-", as that character
00077 //               is used to identify the start of the next option string...
00078 //
00079 //               ..............................................................
00080 //
00081 //               This function is quite unforgiving of errors in the format
00082 //               of the command line.  In typical use, there is no check in
00083 //               the calling program that poptarg (etc.) are properly set, or
00084 //               that the number of arguments is correct.  No default values
00085 //               are set, and errors generally cause the program to stop
00086 //                -- caveat emptor!
00087 //
00088 //               NOTE: The option "-version" or "--version" to any Starlab
00089 //                     program is legal, and will result in the program
00090 //                     printing the current version number on cerr and
00091 //                     terminating.
00092 //
00093 //----------------------------------------------------------------------------
00094 
00095 int  pgetopt(int argc, char ** argv, char * optstr)
00096 {
00097     static int argv_counter = 1;        // argument counter
00098                                         // skip argv[0], the command name
00099     static int argv_offset  = 0;        // character counter within argument
00100                                         // (multiple switches per argument
00101                                         //  are allowed)
00102 
00103     if (argv_counter >= argc)
00104         return -1;                      // signal that we've run out of options
00105 
00106     if (argv_offset == 0) {
00107         if (argv[argv_counter][argv_offset] != '-') {
00108             cerr << "pgetopt: warning: command line argument \""
00109                  << argv[argv_counter]
00110                  << "\" does not begin with \"-\"\n";
00111 
00112             // exit(1);         // too severe...
00113 
00114             argv_counter++;
00115             return '?';
00116 
00117         } else
00118             argv_offset++;
00119     }
00120 
00121     //  We have a legal switch.  First check to see if all we want to
00122     //  know is the STARLAB version number.
00123 
00124     if (streq(argv[argv_counter], VERSION_OPTION_A)
00125         || streq(argv[argv_counter], VERSION_OPTION_B)) {
00126         cerr << "Starlab version " << STARLAB_VERSION << endl;
00127         exit(0);
00128     }
00129 
00130     char option_char = argv[argv_counter][argv_offset];
00131 
00132     // Locate the next character in the argument list in optstr.
00133 
00134     int optstr_counter = 0;
00135     while (optstr[optstr_counter] != option_char) {
00136 
00137         if (optstr[optstr_counter] == '\0') {
00138 
00139             // Prepare for the next call to pgetopt.
00140 
00141             if (argv[argv_counter][++argv_offset] == '\0') {
00142                 argv_counter++;
00143                 argv_offset = 0;
00144             }
00145             return '?';                 // couldn't find the specified
00146                                         // command-line option in optstr
00147 
00148         } else
00149 
00150             optstr_counter++;
00151     }
00152 
00153     // Current command-line option is option_char, and it exists in
00154     // optstr, at position optstr_counter.
00155 
00156     poptarg = poparr[0] = NULL;         // default: no/optional argument
00157 
00158     // Look for arguments, and set up pointers to them.
00159 
00160     char opt;
00161     int narg = 0;
00162 
00163     while ((opt = optstr[++optstr_counter]) == ':' || opt == '.') {
00164 
00165         // Options must always be immediately followed by their arguments.
00166 
00167         if (narg == 0) {
00168             if (argv[argv_counter][argv_offset + 1] != '\0') {
00169                 cerr << "pgetopt: option \"-" << option_char
00170                      << "\" not followed by a space";
00171                 if (opt == ':') cerr << " and argument";
00172                 cerr << endl;
00173                 exit(1);
00174             }
00175         } else if (narg >= N_POP_ARG) {
00176 
00177             // Shouldn't happen...
00178 
00179             cerr << "pgetopt: too many arguments requested for option \"-"
00180                  << option_char << "\"" << endl;
00181             exit(1);
00182         }
00183 
00184         // Move to the next argument and check that it exists.
00185 
00186         if (++argv_counter >= argc && opt == ':') {
00187             cerr << "pgetopt: option \"-" << option_char
00188                  << "\" requires space-separated argument(s)\n";
00189             exit(1);
00190         }
00191 
00192         // Check for a single optional argument.
00193 
00194         if (opt == '.'
00195             && (argv_counter >= argc || argv[argv_counter][0] == '-')) {
00196             argv_counter--;
00197             break;
00198         }
00199 
00200         // Comptibility:
00201 
00202         if (narg == 0) poptarg = argv[argv_counter];
00203 
00204         poparr[narg++] = argv[argv_counter];
00205 
00206     }
00207 
00208     // Prepare for the next call to pgetopt.
00209 
00210     if (poptarg || argv[argv_counter][++argv_offset] == '\0') {
00211 
00212         argv_counter++;
00213         argv_offset = 0;
00214 
00215     }
00216     
00217     return option_char;
00218 }
00219 
00220 
00221 #else
00222 
00223 void main(char argc, char ** argv)
00224 {
00225     extern char *poptarg;
00226     extern char *poparr[];                              // new (8/99)
00227     int c;
00228     char* param_string = "ab:c::d:::e::::fg.h";
00229 
00230     while ((c = pgetopt(argc, argv, param_string)) != -1) {
00231         switch (c) {
00232 
00233             case 'a':   cerr << "option a: no arguments"
00234                              << endl;
00235                         break;
00236 
00237             case 'b':   cerr << "option b: argument: "
00238                              << poptarg << " = " << poparr[0]
00239                              << endl;
00240                         break;
00241 
00242             case 'c':   cerr << "option c: arguments: "
00243                              << poparr[0] << "  " << poparr[1]
00244                              << endl;
00245                         break;
00246 
00247             case 'd':   cerr << "option d: arguments: "
00248                              << poparr[0] << "  " << poparr[1] << "  "
00249                              << poparr[2]
00250                              << endl;
00251                         break;
00252 
00253             case 'e':   cerr << "option e: arguments: "
00254                              << poparr[0] << "  " << poparr[1] << "  "
00255                              << poparr[2] << "  " << poparr[3]
00256                              << endl;
00257                         break;
00258 
00259             case 'f':   cerr << "option f: no arguments"
00260                              << endl;
00261                         break;
00262 
00263             case 'g':   if (poptarg)
00264                             cerr << "option g: optional argument: "
00265                                  << poptarg << " = " << poparr[0]
00266                                  << endl;
00267                         else
00268                             cerr << "option g: no optional argument"
00269                                  << endl;
00270                         break;
00271 
00272             case 'h':   cerr << "option h: no arguments"
00273                              << endl;
00274                         break;
00275 
00276         }
00277     }
00278 }
00279 
00280 #endif

Generated at Sun Feb 24 09:57:11 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001