modules/up/src/util/Argv.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. ParseArgv
  2. PrintUsage

   1 /*
   2  * Argv.c --
   3  *
   4  *      Targvle contains a procedure that handles table-based
   5  *      argv-argc parsing.
   6  *
   7  * Copyright (c) 1990-1994 The Regents of the University of California.
   8  * Copyright (c) 1994 Sun Microsystems, Inc.
   9  *
  10 This software is copyrighted by the Regents of the University of
  11 California, Sun Microsystems, Inc., and other parties.  The following
  12 terms apply to all files associated with the software unless explicitly
  13 disclaimed in individual files.
  14 
  15 The authors hereby grant permission to use, copy, modify, distribute,
  16 and license this software and its documentation for any purpose, provided
  17 that existing copyright notices are retained in all copies and that this
  18 notice is included verbatim in any distributions. No written agreement,
  19 license, or royalty fee is required for any of the authorized uses.
  20 Modifications to this software may be copyrighted by their authors
  21 and need not follow the licensing terms described here, provided that
  22 the new terms are clearly indicated on the first page of each file where
  23 they apply.
  24 
  25 IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
  26 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  27 ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
  28 DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
  29 POSSIBILITY OF SUCH DAMAGE.
  30 
  31 THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
  32 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  33 FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
  34 IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
  35 NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
  36 MODIFICATIONS.
  37 
  38 RESTRICTED RIGHTS: Use, duplication or disclosure by the government
  39 is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
  40 of the Rights in Technical Data and Computer Software Clause as DFARS
  41 252.227-7013 and FAR 52.227-19.
  42  *
  43  */
  44 
  45 #include "config.h"
  46 #include <iostream.h>
  47 #include <cstring>
  48 #include <cstdlib>
  49 #include "Argv.hh"
  50 #include "version.hh"   /* For version control */
  51 
  52 /*
  53  * Default table of argument descriptors.  These are normally available
  54  * in every application.
  55  */
  56 
  57 static ArgvInfo defaultTable[] = {
  58     {"-help",   ARGV_HELP,      (char *) NULL,  (char *) NULL,
  59         "Print summary of command-line options and abort"},
  60     {NULL,      ARGV_END,       (char *) NULL,  (char *) NULL,
  61         (char *) NULL}
  62 };
  63 
  64 /*
  65  * Forward declarations for procedures defined in this file:
  66  */
  67 
  68 static void PrintUsage(ArgvInfo *argTable, int flags);
  69 
  70 /*
  71  *----------------------------------------------------------------------
  72  *
  73  * ParseArgv --
  74  *
  75  *      Process an argv array according to a table of expected
  76  *      command-line options.  See the manual page for more details.
  77  *
  78  * Results:
  79  *      Under normal conditions, both *argcPtr and *argv are modified
  80  *      to return the arguments that couldn't be processed here (they
  81  *      didn't match the option table, or followed an ARGV_REST
  82  *      argument).
  83  *
  84  * Side effects:
  85  *      Variables may be modified, or procedures may be called.  It
  86  *      all depends on the arguments
  87  *      and their entries in argTable.  See the user documentation
  88  *      for details.
  89  *
  90  *----------------------------------------------------------------------
  91  */
  92 
  93 int ParseArgv(int *argcPtr, char **argv, ArgvInfo *argTable, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
  94     /* argcPtr: Number of arguments in argv.  Modified
  95      * to hold # args left in argv at end. */
  96     /* argv: Array of arguments.  Modified to hold
  97      * those that couldn't be processed here. */
  98     /* argTable: Array of option descriptions */
  99     /* flags: Or'ed combination of various flag bits,
 100      * such as ARGV_NO_DEFAULTS. */
 101 {
 102     register ArgvInfo *infoPtr;
 103                                 /* Pointer to the current entry in the
 104                                  * table of argument descriptions. */
 105     ArgvInfo *matchPtr; /* Descriptor that matches current argument. */
 106     char *curArg;               /* Current argument */
 107     register char c;            /* Second character of current arg (used for
 108                                  * quick check for matching;  use 2nd char.
 109                                  * because first char. will almost always
 110                                  * be '-'). */
 111     int srcIndex;               /* Location from which to read next argument
 112                                  * from argv. */
 113     int dstIndex;               /* Index into argv to which next unused
 114                                  * argument should be copied (never greater
 115                                  * than srcIndex). */
 116     int argc;                   /* # arguments in argv still to process. */
 117     int length;                 /* Number of characters in current argument. */
 118     int i;
 119 
 120     /* Try to fill the name of current program into ProjectGoal[64] -- wlee@ISI.EDU */
 121     int len = strlen(argv[0]);
 122     char *pGoal = argv[0] + len;
 123     while (*pGoal != '/' && *pGoal != '\\' && --len >= 0) pGoal--;
 124     strcpy(ProjectGoal, pGoal);
 125 
 126     if (flags & ARGV_DONT_SKIP_FIRST_ARG) {
 127         srcIndex = dstIndex = 0;
 128         argc = *argcPtr;
 129     } else {
 130         srcIndex = dstIndex = 1;
 131         argc = *argcPtr-1;
 132     }
 133 
 134     while (argc > 0) {
 135         curArg = argv[srcIndex];
 136         srcIndex++;
 137         argc--;
 138         length = strlen(curArg);
 139         if (length > 0) {
 140             c = curArg[1];
 141         } else {
 142             c = 0;
 143         }
 144 
 145         /*
 146          * Loop throught the argument descriptors searching for one with
 147          * the matching key string.  If found, leave a pointer to it in
 148          * matchPtr.
 149          */
 150 
 151         matchPtr = NULL;
 152         for (i = 0; i < 2; i++) {
 153             if (i == 0) {
 154                 infoPtr = argTable;
 155             } else {
 156                 infoPtr = defaultTable;
 157             }
 158             for (; (infoPtr != NULL) && (infoPtr->type != ARGV_END);
 159                     infoPtr++) {
 160                  if (infoPtr->key == NULL) {
 161                      continue;
 162                  }
 163                  if ((infoPtr->key[1] != c)
 164                          || (strncmp(infoPtr->key, curArg, length) != 0)) {
 165                      continue;
 166                  }
 167                  if (infoPtr->key[length] == 0) {
 168                      matchPtr = infoPtr;
 169                      goto gotMatch;
 170                  }
 171                  if (flags & ARGV_NO_ABBREV) {
 172                      continue;
 173                  }
 174                  if (matchPtr != NULL) {
 175                     cerr << "ambiguous option \"" << curArg << "\"";
 176                      return ARGV_ERROR;
 177                  }
 178                  matchPtr = infoPtr;
 179             }
 180         }
 181         if (matchPtr == NULL) {
 182 
 183             /*
 184              * Unrecognized argument.  Just copy it down, unless the caller
 185              * prefers an error to be registered.
 186              */
 187 
 188             if (flags & ARGV_NO_LEFTOVERS) {
 189                cerr << "unrecognized argument \"" << curArg << "\"";
 190                 return ARGV_ERROR;
 191             }
 192             argv[dstIndex] = curArg;
 193             dstIndex++;
 194             continue;
 195         }
 196 
 197         /*
 198          * Take the appropriate action based on the option type
 199          */
 200 
 201         gotMatch:
 202         infoPtr = matchPtr;
 203         switch (infoPtr->type) {
 204             case ARGV_BOOL:
 205                 *((bool *) infoPtr->dst) = ! *((bool *) infoPtr->dst);
 206                 break;
 207             case ARGV_CONSTANT:
 208                 *((int *) infoPtr->dst) = (int) infoPtr->src;
 209                 break;
 210             case ARGV_INT:
 211                 if (argc == 0) {
 212                     goto missingArg;
 213                 } else {
 214                     char *endPtr;
 215 
 216                     *((int *) infoPtr->dst) =
 217                             strtol(argv[srcIndex], &endPtr, 0);
 218                     if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
 219                        cerr << "expected integer argument for \"" 
 220                             << infoPtr->key << "\" but got \""
 221                             << argv[srcIndex] << "\"";
 222                         return ARGV_ERROR;
 223                     }
 224                     srcIndex++;
 225                     argc--;
 226                 }
 227                 break;
 228             case ARGV_STRING:
 229                 if (argc == 0) {
 230                     goto missingArg;
 231                 } else {
 232                     *((char **)infoPtr->dst) = argv[srcIndex];
 233                     srcIndex++;
 234                     argc--;
 235                 }
 236                 break;
 237             case ARGV_REST:
 238                 *((int *) infoPtr->dst) = dstIndex;
 239                 goto argsDone;
 240             case ARGV_FLOAT:
 241                 if (argc == 0) {
 242                     goto missingArg;
 243                 } else {
 244                     char *endPtr;
 245 
 246                     *((double *) infoPtr->dst) =
 247                             strtod(argv[srcIndex], &endPtr);
 248                     if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
 249                        cerr << "expected floating-point argument for \""
 250                             << infoPtr->key << "\" but got \""
 251                             << argv[srcIndex] <<  "\"";
 252                         return ARGV_ERROR;
 253                     }
 254                     srcIndex++;
 255                     argc--;
 256                 }
 257                 break;
 258             case ARGV_FUNC: {
 259                 int (*handlerProc)(...);
 260 
 261                 handlerProc = (int (*)(...))infoPtr->src;
 262                 
 263                 if ((*handlerProc)(infoPtr->dst, infoPtr->key,
 264                         argv[srcIndex])) {
 265                     srcIndex += 1;
 266                     argc -= 1;
 267                 }
 268                 break;
 269             }
 270             case ARGV_GENFUNC: {
 271                 int         (*handlerProc)(...);
 272 
 273                 handlerProc = (int (*)(...))infoPtr->src;
 274 
 275                 argc = (*handlerProc)(infoPtr->dst, infoPtr->key,
 276                         argc, argv+srcIndex);
 277                 if (argc < 0) {
 278                     return ARGV_ERROR;
 279                 }
 280                 break;
 281             }
 282             case ARGV_HELP:
 283                 PrintUsage (argTable, flags);
 284                 return ARGV_ERROR;
 285             default:
 286                cerr << "bad argument type %d in ArgvInfo" << infoPtr->type;
 287                 return ARGV_ERROR;
 288         }
 289     }
 290 
 291     /*
 292      * If we broke out of the loop because of an OPT_REST argument,
 293      * copy the remaining arguments down.
 294      */
 295 
 296     argsDone:
 297     while (argc) {
 298         argv[dstIndex] = argv[srcIndex];
 299         srcIndex++;
 300         dstIndex++;
 301         argc--;
 302     }
 303     argv[dstIndex] = (char *) NULL;
 304     *argcPtr = dstIndex;
 305     return ARGV_OK;
 306 
 307     missingArg:
 308     cerr << "\"" << curArg << "\" option requires an additional argument";
 309     return ARGV_ERROR;
 310 }
 311 
 312 /*
 313  *----------------------------------------------------------------------
 314  *
 315  * PrintUsage --
 316  *
 317  *      Print (in cerr) a help string describing command-line options.
 318  *
 319  * Results:
 320  *      None.
 321  *
 322  * Side effects:
 323  *      None.
 324  *
 325  *----------------------------------------------------------------------
 326  */
 327 
 328 static void
 329 PrintUsage(ArgvInfo *argTable, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
 330    /* argTable: Array of command-specific argument
 331     * descriptions. */
 332    /* flags: If the ARGV_NO_DEFAULTS bit is set
 333     * in this word, then don't generate
 334     * information for default options. */
 335 {
 336     register ArgvInfo *infoPtr;
 337     int width, i, numSpaces;
 338 #define NUM_SPACES 20
 339     static char spaces[] = "                    ";
 340     char tmp[30];
 341 
 342     /*
 343      * First, compute the width of the widest option key, so that we
 344      * can make everything line up.
 345      */
 346 
 347     width = 4;
 348     for (i = 0; i < 2; i++) {
 349         for (infoPtr = i ? defaultTable : argTable;
 350                 infoPtr->type != ARGV_END; infoPtr++) {
 351             int length;
 352             if (infoPtr->key == NULL) {
 353                 continue;
 354             }
 355             length = strlen(infoPtr->key);
 356             if (length > width) {
 357                 width = length;
 358             }
 359         }
 360     }
 361 
 362     // Added by wlee@isi.edu
 363     cerr << endl;
 364 
 365     cerr << "Command-specific options:";
 366     for (i = 0; ; i++) {
 367         for (infoPtr = i ? defaultTable : argTable;
 368                 infoPtr->type != ARGV_END; infoPtr++) {
 369             if ((infoPtr->type == ARGV_HELP) && (infoPtr->key == NULL)) {
 370                cerr << "\n" << infoPtr->help;
 371                 continue;
 372             }
 373             // Modified by wlee@isi.edu to get rid of ':' 
 374             cerr << "\n " << infoPtr->key << " ";
 375 //          cerr << "\n " << infoPtr->key << ":";
 376             numSpaces = width + 1 - strlen(infoPtr->key);
 377             while (numSpaces > 0) {
 378                 if (numSpaces >= NUM_SPACES) {
 379                    cerr << spaces;
 380                 } else {
 381                    cerr << spaces+NUM_SPACES-numSpaces;
 382                 }
 383                 numSpaces -= NUM_SPACES;
 384             }
 385             cerr << infoPtr->help;
 386             switch (infoPtr->type) {
 387                 case ARGV_INT: {
 388                     cerr << "\n\t\tDefault value: " << *((int *) infoPtr->dst);
 389                     break;
 390                 }
 391                 case ARGV_FLOAT: {
 392                     cerr << "\n\t\tDefault value: " << *((double *) infoPtr->dst);
 393                     break;
 394                 }
 395                 case ARGV_STRING: {
 396                     char *string;
 397 
 398                     string = *((char **) infoPtr->dst);
 399                     if (string != NULL) {
 400                        cerr << "\n\t\tDefault value: \"" << string << "\"";
 401                     }
 402                     break;
 403                 }
 404                 default: {
 405                     break;
 406                 }
 407             }
 408         }
 409 
 410         if ((flags & ARGV_NO_DEFAULTS) || (i > 0)) {
 411             break;
 412         }
 413         cerr << "\nGeneric options for all commands:";
 414     }
 415     // Added by wlee@isi.edu
 416     cerr << endl;
 417 }
 418 
 419 
 420 

/* [<][>][^][v][top][bottom][index][help] */