Back to index

tetex-bin  3.0
parseargs.c
Go to the documentation of this file.
00001 /*
00002  * parseargs.h
00003  *
00004  * Command line argument parser.
00005  *
00006  * Copyright 1996-2003 Glyph & Cog, LLC
00007  */
00008 
00009 #include <stdio.h>
00010 #include <stddef.h>
00011 #include <string.h>
00012 #include <stdlib.h>
00013 #include <ctype.h>
00014 #include "parseargs.h"
00015 
00016 static ArgDesc *findArg(ArgDesc *args, char *arg);
00017 static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]);
00018 
00019 GBool parseArgs(ArgDesc *args, int *argc, char *argv[]) {
00020   ArgDesc *arg;
00021   int i, j;
00022   GBool ok;
00023 
00024   ok = gTrue;
00025   i = 1;
00026   while (i < *argc) {
00027     if (!strcmp(argv[i], "--")) {
00028       --*argc;
00029       for (j = i; j < *argc; ++j)
00030        argv[j] = argv[j+1];
00031       break;
00032     } else if ((arg = findArg(args, argv[i]))) {
00033       if (!grabArg(arg, i, argc, argv))
00034        ok = gFalse;
00035     } else {
00036       ++i;
00037     }
00038   }
00039   return ok;
00040 }
00041 
00042 void printUsage(char *program, char *otherArgs, ArgDesc *args) {
00043   ArgDesc *arg;
00044   char *typ;
00045   int w, w1;
00046 
00047   w = 0;
00048   for (arg = args; arg->arg; ++arg) {
00049     if ((w1 = strlen(arg->arg)) > w)
00050       w = w1;
00051   }
00052 
00053   fprintf(stderr, "Usage: %s [options]", program);
00054   if (otherArgs)
00055     fprintf(stderr, " %s", otherArgs);
00056   fprintf(stderr, "\n");
00057 
00058   for (arg = args; arg->arg; ++arg) {
00059     fprintf(stderr, "  %s", arg->arg);
00060     w1 = 9 + w - strlen(arg->arg);
00061     switch (arg->kind) {
00062     case argInt:
00063     case argIntDummy:
00064       typ = " <int>";
00065       break;
00066     case argFP:
00067     case argFPDummy:
00068       typ = " <fp>";
00069       break;
00070     case argString:
00071     case argStringDummy:
00072       typ = " <string>";
00073       break;
00074     case argFlag:
00075     case argFlagDummy:
00076     default:
00077       typ = "";
00078       break;
00079     }
00080     fprintf(stderr, "%-*s", w1, typ);
00081     if (arg->usage)
00082       fprintf(stderr, ": %s", arg->usage);
00083     fprintf(stderr, "\n");
00084   }
00085 }
00086 
00087 static ArgDesc *findArg(ArgDesc *args, char *arg) {
00088   ArgDesc *p;
00089 
00090   for (p = args; p->arg; ++p) {
00091     if (p->kind < argFlagDummy && !strcmp(p->arg, arg))
00092       return p;
00093   }
00094   return NULL;
00095 }
00096 
00097 static GBool grabArg(ArgDesc *arg, int i, int *argc, char *argv[]) {
00098   int n;
00099   int j;
00100   GBool ok;
00101 
00102   ok = gTrue;
00103   n = 0;
00104   switch (arg->kind) {
00105   case argFlag:
00106     *(GBool *)arg->val = gTrue;
00107     n = 1;
00108     break;
00109   case argInt:
00110     if (i + 1 < *argc && isInt(argv[i+1])) {
00111       *(int *)arg->val = atoi(argv[i+1]);
00112       n = 2;
00113     } else {
00114       ok = gFalse;
00115       n = 1;
00116     }
00117     break;
00118   case argFP:
00119     if (i + 1 < *argc && isFP(argv[i+1])) {
00120       *(double *)arg->val = atof(argv[i+1]);
00121       n = 2;
00122     } else {
00123       ok = gFalse;
00124       n = 1;
00125     }
00126     break;
00127   case argString:
00128     if (i + 1 < *argc) {
00129       strncpy((char *)arg->val, argv[i+1], arg->size - 1);
00130       ((char *)arg->val)[arg->size - 1] = '\0';
00131       n = 2;
00132     } else {
00133       ok = gFalse;
00134       n = 1;
00135     }
00136     break;
00137   default:
00138     fprintf(stderr, "Internal error in arg table\n");
00139     n = 1;
00140     break;
00141   }
00142   if (n > 0) {
00143     *argc -= n;
00144     for (j = i; j < *argc; ++j)
00145       argv[j] = argv[j+n];
00146   }
00147   return ok;
00148 }
00149 
00150 GBool isInt(char *s) {
00151   if (*s == '-' || *s == '+')
00152     ++s;
00153   while (isdigit(*s))
00154     ++s;
00155   if (*s)
00156     return gFalse;
00157   return gTrue;
00158 }
00159 
00160 GBool isFP(char *s) {
00161   int n;
00162 
00163   if (*s == '-' || *s == '+')
00164     ++s;
00165   n = 0;
00166   while (isdigit(*s)) {
00167     ++s;
00168     ++n;
00169   }
00170   if (*s == '.')
00171     ++s;
00172   while (isdigit(*s)) {
00173     ++s;
00174     ++n;
00175   }
00176   if (n > 0 && (*s == 'e' || *s == 'E')) {
00177     ++s;
00178     if (*s == '-' || *s == '+')
00179       ++s;
00180     n = 0;
00181     if (!isdigit(*s))
00182       return gFalse;
00183     do {
00184       ++s;
00185     } while (isdigit(*s));
00186   }
00187   if (*s)
00188     return gFalse;
00189   return gTrue;
00190 }