1: /*
   2:  * Copyright (c) 1990 Michael A. Cooper.
   3:  * This software may be freely distributed provided it is not sold for
   4:  * profit and the author is credited appropriately.
   5:  */
   6: 
   7: #if !defined(lint) && defined(DOSCCS)
   8: static char *RCSid = "$Header: options.c,v 1.13.1 96/3/23 18:13:28 sms Exp $";
   9: #endif
  10: 
  11: /*
  12:  * $Log:	options.c,v $
  13:  * Revision 1.13  90/12/15  18:13:28  mcooper
  14:  * Add copywrite notice.
  15:  *
  16:  * Revision 1.12  90/12/15  17:51:46  mcooper
  17:  * Add #ifdef HAS_VARARGS around include for <varargs>.
  18:  *
  19:  * Revision 1.11  90/11/13  16:39:28  mcooper
  20:  * Add #ifdef HAS_VARARGS for systems without
  21:  * varargs.
  22:  *
  23:  * Revision 1.10  90/11/13  15:28:01  mcooper
  24:  * - Add OptBool cvtarg routine.
  25:  * - Print default values in HelpOptions()
  26:  *   when appropriate.
  27:  *
  28:  * Revision 1.9  90/11/13  15:19:00  mcooper
  29:  * Added supported for options being both
  30:  * SepArg and StickyArg.
  31:  *
  32:  * Revision 1.8  90/10/30  21:02:31  mcooper
  33:  * Need to exit() if -help is specified.
  34:  *
  35:  * Revision 1.7  90/10/30  20:24:33  mcooper
  36:  * Fixed bug in UsageString().
  37:  *
  38:  * Revision 1.6  90/10/30  19:53:05  mcooper
  39:  * Cleaned up some NeXT cc and lint stuff.
  40:  *
  41:  * Revision 1.5  90/10/30  19:45:31  mcooper
  42:  * Remove unneeded paramter to HelpOptions().
  43:  *
  44:  * Revision 1.4  90/10/29  14:47:42  mcooper
  45:  * Added real function UsageString() to
  46:  * handle formating usage option strings.
  47:  *
  48:  * Revision 1.3  90/10/29  14:17:00  mcooper
  49:  * Allow options to be abbreviated
  50:  * (for all non StickArg options).
  51:  *
  52:  * Revision 1.2  90/10/26  15:56:11  mcooper
  53:  * - Fix bug in SepArg code that ate arguments.
  54:  * - Cleanup help message.
  55:  * - Add ArgHidden code.
  56:  *
  57:  * Revision 1.1  90/10/26  14:42:51  mcooper
  58:  * Initial revision
  59:  *
  60:  */
  61: 
  62: /*
  63:  * Functions to parse options.
  64:  */
  65: 
  66: #include "options.h"
  67: #ifdef HAS_VARARGS
  68: #include <varargs.h>
  69: #endif
  70: 
  71: char *OptionChars = "-+";   /* Default option switching characters */
  72: char *ProgramName = NULL;   /* Name of this program */
  73: char *UsageString();
  74: static int isopt();
  75: static int suppress_help_msg = 0;
  76: char *strcat();
  77: 
  78: /*
  79:  * ParseOptions - Parse options found in argv using "options".
  80:  *		  Returns the number of options parsed if there
  81:  *		  were no errors.  Returns -1 if an error occurs.
  82:  */
  83: int ParseOptions(options, num_options, argc, argv)
  84:      OptionDescRec *options;
  85:      int num_options;
  86:      int argc;
  87:      char **argv;
  88: {
  89:     OptionDescRec *opt;
  90:     register int x;
  91:     char *p;
  92: 
  93:     if (ProgramName == NULL)
  94:     ProgramName = argv[0];
  95: 
  96: #ifdef OPTION_DEBUG
  97:     (void) printf("Option list is:\n");
  98:     for (x = 0; x < num_options; ++x) {
  99:     opt = &options[x];
 100:     (void) printf("%s\n", opt->option);
 101:     }
 102: 
 103:     (void) printf("Arguments (%d):", argc);
 104:     for (x = 0; x < argc; ++x) {
 105:     (void) printf(" %s", argv[x]);
 106:     }
 107:     (void) printf("\n");
 108: #endif /* OPTION_DEBUG */
 109: 
 110:     for (x = 1; x < argc; ++x) {
 111:     if (strcmp(HELPSTR, argv[x]) == 0) {
 112:         HelpOptions(options, num_options, (char **)NULL);
 113:         exit(0);
 114:     }
 115: 
 116:     opt = FindOption(options, num_options, argv[x]);
 117:     if (opt == NULL) {
 118:         if (isopt(argv[x])) { /* this was suppose to be an option */
 119:         UsageOptions(options, num_options, argv[x]);
 120:         return(-1);
 121:         } else { /* must be end of options */
 122:         break;
 123:         }
 124:     }
 125: 
 126:     if (opt->flags & NoArg) {
 127:         if (!(*opt->cvtarg)(opt, opt->value, FALSE)) {
 128:         UsageOptions(options, num_options, opt->option);
 129:         return(-1);
 130:         }
 131:     } else if (opt->flags & IsArg) {
 132:         if (!(*opt->cvtarg)(opt, opt->option, FALSE)) {
 133:         UsageOptions(options, num_options, opt->option);
 134:         return(-1);
 135:         }
 136:     } else if ((opt->flags & StickyArg) && (opt->flags & SepArg)) {
 137:         p = (char *) &argv[x][strlen(opt->option)];
 138:         if (!*p) {      /*** SepArg ***/
 139:         if (x + 1 >= argc || isopt(argv[x+1])) {
 140:             if (opt->value == (caddr_t) NULL) {
 141:             UserError("%s: Option requires an argument.", argv[x]);
 142:             UsageOptions(options, num_options, opt->option);
 143:             return(-1);
 144:             }
 145:             p = opt->value;
 146:         } else {
 147:             p = argv[++x];
 148:         }
 149:         }
 150:         if (!(*opt->cvtarg)(opt, p, TRUE)) {
 151:         UsageOptions(options, num_options, opt->option);
 152:         return(-1);
 153:         }
 154:     } else if (opt->flags & StickyArg) {
 155:         p = (char *) &argv[x][strlen(opt->option)];
 156:         if (!*p) {
 157:         if (opt->value == (caddr_t) NULL) {
 158:             UserError("%s: Option requires an argument.", argv[x]);
 159:             UsageOptions(options, num_options, opt->option);
 160:             return(-1);
 161:         } else {
 162:             p = opt->value;
 163:         }
 164:         }
 165:         if (!(*opt->cvtarg)(opt, p, TRUE)) {
 166:         UsageOptions(options, num_options, opt->option);
 167:         return(-1);
 168:         }
 169:     } else if (opt->flags & SepArg) {
 170:         if (x + 1 >= argc || isopt(argv[x+1])) {
 171:         if (opt->value == (caddr_t) NULL) {
 172:             UserError("%s: Option requires an argument.", argv[x]);
 173:             UsageOptions(options, num_options, opt->option);
 174:             return(-1);
 175:         } else {
 176:             p = opt->value;
 177:         }
 178:         } else {
 179:         p = argv[++x];
 180:         }
 181:         if (!(*opt->cvtarg)(opt, p, TRUE)) {
 182:         UsageOptions(options, num_options, opt->option);
 183:         return(-1);
 184:         }
 185:     } else if (opt->flags & SkipArg) {
 186:         x += 2;
 187:     } else if (opt->flags & SkipLine) {
 188:         return(x);
 189:     } else if (opt->flags & SkipNArgs) {
 190:         if (opt->value) {
 191:         x += atoi(opt->value);
 192:         } else {
 193:         UserError("Internal Error: No 'value' set for SkipNArgs.");
 194:         return(-1);
 195:         }
 196:     } else {
 197:         UserError("Internal Error: Unknown argument type for option '%s'.",
 198:              opt->option);
 199:         return(-1);
 200:     }
 201:     }
 202: 
 203:     return(x);
 204: }
 205: 
 206: /*
 207:  * FindOption - Find "option" in "options".  Returns NULL if not found.
 208:  */
 209: OptionDescRec *FindOption(options, num_options, option)
 210:      OptionDescRec *options;
 211:      int num_options;
 212:      char *option;
 213: {
 214:     OptionDescRec *opt;
 215:     register int x;
 216: 
 217:     for (x = 0; x < num_options; ++x) {
 218:     opt = &options[x];
 219:     if (opt->flags & StickyArg) {
 220:         if (strncmp(option, opt->option, strlen(opt->option)) == 0)
 221:         return(opt);
 222:     } else {
 223:         if (strncmp(option, opt->option, strlen(option)) == 0)
 224:         return(opt);
 225:     }
 226:     }
 227: 
 228:     return(NULL);
 229: }
 230: 
 231: /*
 232:  * isopt - Is "str" an option string?  Compare first char of str against
 233:  *	   list of option switch characters.  Returns TRUE if it is an option.
 234:  */
 235: static int isopt(str)
 236:      char *str;
 237: {
 238:     register char *p;
 239: 
 240:     for (p = OptionChars; p && *p; *++p) {
 241:     if (*str == *p) {
 242:         return(TRUE);
 243:     }
 244:     }
 245: 
 246:     return(FALSE);
 247: }
 248: 
 249: /*
 250:  * UsageOptions - Print a usage message based on "options".
 251:  */
 252: void UsageOptions(options, num_opts, badOption)
 253:      OptionDescRec *options;
 254:      int num_opts;
 255:      char *badOption;
 256: {
 257:     OptionDescRec *opt;
 258:     char *optstr;
 259:     register int x;
 260:     int col, len;
 261: 
 262:     if (badOption)
 263:     (void) fprintf (stderr, "%s:  bad command line option \"%s\"\r\n\n",
 264:             ProgramName, badOption);
 265: 
 266:     (void) fprintf (stderr, "usage:  %s", ProgramName);
 267:     col = 8 + strlen(ProgramName);
 268:     for (x = 0; x < num_opts; x++) {
 269:     opt = &options[x];
 270:     if (opt->flags & ArgHidden)
 271:         continue;
 272:     optstr = UsageString(opt);
 273:     len = strlen(optstr) + 3;   /* space [ string ] */
 274:     if (col + len > 79) {
 275:         (void) fprintf (stderr, "\r\n   ");  /* 3 spaces */
 276:         col = 3;
 277:     }
 278:     (void) fprintf (stderr, " [%s]", optstr);
 279:     col += len;
 280:     }
 281: 
 282:     if (suppress_help_msg)
 283:     (void) fprintf(stderr, "\r\n\n");
 284:     else
 285:     (void) fprintf(stderr,
 286:                "\r\n\nType \"%s %s\" for a full description.\r\n\n",
 287:                ProgramName, HELPSTR);
 288: }
 289: 
 290: /*
 291:  * HelpOptions - Print a nice help/usage message based on options.
 292:  */
 293: void HelpOptions(options, num_opts, message)
 294:      OptionDescRec *options;
 295:      int num_opts;
 296:      char **message;
 297: {
 298:     OptionDescRec *opt;
 299:     register int x;
 300:     char **cpp;
 301: 
 302:     suppress_help_msg = 1;
 303:     UsageOptions(options, num_opts, (char *)NULL);
 304:     suppress_help_msg = 0;
 305: 
 306:     (void) fprintf (stderr, "where options include:\n");
 307:     for (x = 0; x < num_opts; x++) {
 308:     opt = &options[x];
 309:     if (opt->flags & ArgHidden)
 310:         continue;
 311:     (void) fprintf (stderr, "    %-28s %s\n", UsageString(opt),
 312:          (opt->desc) ? opt->desc : "");
 313:     if (opt->value && opt->cvtarg != OptBool)
 314:         (void) fprintf (stderr, "    %-28s [ Default value is %s ]\n",
 315:                 "", opt->value);
 316:     }
 317: 
 318:     if (message) {
 319:     (void) putc ('\n', stderr);
 320:     for (cpp = message; *cpp; cpp++) {
 321:         (void) fputs (*cpp, stderr);
 322:         (void) putc ('\n', stderr);
 323:     }
 324:     (void) putc ('\n', stderr);
 325:     }
 326: }
 327: 
 328: /*
 329:  * UserError - Print a user error.
 330:  */
 331: #ifdef HAS_VARARGS
 332: void UserError(va_alist)
 333:      va_dcl
 334: {
 335:     va_list args;
 336:     char *fmt;
 337: 
 338:     va_start(args);
 339:     if (ProgramName)
 340:     (void) fprintf(stderr, "%s: ", ProgramName);
 341:     fmt = (char *) va_arg(args, char *);
 342:     (void) vfprintf(stderr, fmt, args);
 343:     va_end(args);
 344:     (void) fprintf(stderr, "\n");
 345: }
 346: #else
 347: void UserError(fmt, a1, a2, a3, a4, a5, a6)
 348:      char *fmt;
 349: {
 350:     if (ProgramName)
 351:     (void) fprintf(stderr, "%s: ", ProgramName);
 352:     (void) fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6);
 353:     (void) fprintf(stderr, "\n");
 354: }
 355: #endif
 356: 
 357: OptBool(opt, value, docopy)
 358:      OptionDescRec *opt;
 359:      caddr_t value;
 360:      int docopy; /*ARGSUSED*/
 361: {
 362:     char *vpp;
 363: 
 364:     *(int *) opt->valp = (int) strtol(value, &vpp, 0);
 365:     if (*vpp) {
 366:     UserError("Invalid integer argument for '%s'.", opt->option);
 367:     return(FALSE);
 368:     } else {
 369:     return(TRUE);
 370:     }
 371: }
 372: 
 373: OptInt(opt, value, docopy)
 374:      OptionDescRec *opt;
 375:      caddr_t value;
 376:      int docopy; /*ARGSUSED*/
 377: {
 378:     char *vpp;
 379: 
 380:     *(int *) opt->valp = (int) strtol(value, &vpp, 0);
 381:     if (*vpp) {
 382:     UserError("Invalid integer argument for '%s'.", opt->option);
 383:     return(FALSE);
 384:     } else {
 385:     return(TRUE);
 386:     }
 387: }
 388: 
 389: OptShort(opt, value, docopy)
 390:      OptionDescRec *opt;
 391:      caddr_t value;
 392:      int docopy; /*ARGSUSED*/
 393: {
 394:     char *vpp;
 395: 
 396:     *(short *) opt->valp = (short) strtol(value, &vpp, 0);
 397:     if (*vpp) {
 398:     UserError("Invalid integer argument for '%s'.", opt->option);
 399:     return(FALSE);
 400:     } else {
 401:     return(TRUE);
 402:     }
 403: }
 404: 
 405: OptLong(opt, value, docopy)
 406:      OptionDescRec *opt;
 407:      caddr_t value;
 408:      int docopy; /*ARGSUSED*/
 409: {
 410:     char *vpp;
 411: 
 412:     *(long *) opt->valp = (long) strtol(value, &vpp, 0);
 413:     if (*vpp) {
 414:     UserError("Invalid integer argument for '%s'.", opt->option);
 415:     return(FALSE);
 416:     } else {
 417:     return(TRUE);
 418:     }
 419: }
 420: 
 421: OptStr(opt, value, docopy)
 422:      OptionDescRec *opt;
 423:      caddr_t value;
 424:      int docopy;
 425: {
 426:     char *p;
 427: 
 428:     if (docopy) {
 429:     if ((p = (char *) malloc((unsigned)strlen(value)+1)) == NULL) {
 430:         UserError("Cannot malloc memory.");
 431:         return(FALSE);
 432:     }
 433:     (void) strcpy(p, value);
 434:     } else {
 435:     p = value;
 436:     }
 437: 
 438:     *(char **) opt->valp = p;
 439: 
 440:     return(TRUE);
 441: }
 442: 
 443: static char *UsageString(opt)
 444:      OptionDescRec *opt;
 445: {
 446:     static char buf[BUFSIZ], buf2[BUFSIZ];
 447: 
 448:     (void) sprintf(buf, opt->option);
 449:     (void) strcpy(buf2, "");
 450:     if (opt->usage) {
 451:     (void) sprintf(buf2, "%s%s%s%s",
 452:                ((opt->flags & StickyArg) &&
 453:             !((opt->flags & StickyArg) && (opt->flags & SepArg)))
 454:                ? "" : " ",
 455:                (opt->value) ? "[" : "",
 456:                opt->usage,
 457:                (opt->value) ? "]" : ""
 458:                );
 459:     }
 460:     (void) strcat(buf, buf2);
 461: 
 462:     return(buf);
 463: }

Defined functions

FindOption defined in line 209; used 2 times
HelpOptions defined in line 293; used 2 times
OptBool defined in line 357; used 2 times
OptInt defined in line 373; used 1 times
OptLong defined in line 405; used 1 times
OptShort defined in line 389; used 1 times
OptStr defined in line 421; used 1 times
ParseOptions defined in line 83; used 2 times
UsageOptions defined in line 252; used 11 times
UsageString defined in line 443; used 3 times
UserError defined in line 347; used 11 times
isopt defined in line 235; used 4 times

Defined variables

OptionChars defined in line 71; used 1 times
ProgramName defined in line 72; used 10 times
RCSid defined in line 8; never used
suppress_help_msg defined in line 75; used 3 times
Last modified: 1996-03-23
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1648
Valid CSS Valid XHTML 1.0 Strict