00001 #include "stdlib.h"
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 #include <stdio.h>
00059 #ifndef NULL
00060 
00061 #include <stddef.h>
00062 #endif
00063 #ifdef KR_headers
00064 extern double atof();
00065 #else
00066 #include "stdlib.h"
00067 #include "string.h"
00068 #endif
00069 #include "parse.h"
00070 #include <math.h>            
00071 #include <ctype.h>
00072 
00073 #define MAX_INPUT_SIZE 1000
00074 
00075 #define arg_prefix(x) ((x).prefix)
00076 #define arg_string(x) ((x).string)
00077 #define arg_flags(x) ((x).flags)
00078 #define arg_count(x) ((x).count)
00079 #define arg_result_type(x) ((x).result_type)
00080 #define arg_result_ptr(x) ((x).result_ptr)
00081 #define arg_table_size(x) ((x).table_size)
00082 
00083 #ifndef TRUE
00084 #define TRUE 1
00085 #endif
00086 #ifndef FALSE
00087 #define FALSE 0
00088 #endif
00089 typedef int boolean;
00090 
00091 
00092 static char *this_program = "";
00093 
00094 static int arg_parse Argdcl((char*, arg_info*));
00095 static char *lower_string Argdcl((char*, char*));
00096 static int match Argdcl((char*, char*, arg_info*, boolean));
00097 static int put_one_arg Argdcl((int, char*, char**, char*, char*));
00098 extern int badargs;
00099 
00100 
00101  boolean
00102 #ifdef KR_headers
00103 parse_args(argc, argv, table, entries, others, other_count)
00104         int argc;
00105         char **argv;
00106         arg_info *table;
00107         int entries;
00108         char **others;
00109         int other_count;
00110 #else
00111 parse_args(int argc, char **argv, arg_info *table, int entries, char **others, int other_count)
00112 #endif
00113 {
00114     boolean result;
00115 
00116     if (argv)
00117         this_program = argv[0];
00118 
00119 
00120 
00121     result = arg_verify (argv, table, entries);
00122 
00123 
00124 
00125     init_store (table, entries);
00126 
00127     if (result) {
00128         boolean use_prefix = TRUE;
00129         char *argv0;
00130 
00131         argc--;
00132         argv0 = *++argv;
00133         while (argc) {
00134             int index, length;
00135 
00136             index = match_table (*argv, table, entries, use_prefix, &length);
00137             if (index < 0) {
00138 
00139 
00140 
00141                 if (others) {
00142 
00143                     if (*argv > argv0)
00144                         *--*argv = '-'; 
00145 
00146                     if (other_count > 0) {
00147                         *others++ = *argv;
00148                         other_count--;
00149                     } else {
00150                         fprintf (stderr, "%s:  too many parameters: ",
00151                                 this_program);
00152                         fprintf (stderr, "'%s' ignored\n", *argv);
00153                         badargs++;
00154                     } 
00155                 } 
00156                 argv0 = *++argv;
00157                 argc--;
00158             } else {
00159 
00160 
00161 
00162                 if (length >= strlen (*argv)) {
00163                     argc--;
00164                     argv0 = *++argv;
00165                     use_prefix = TRUE;
00166                 } else {
00167                     (*argv) += length;
00168                     use_prefix = FALSE;
00169                 } 
00170 
00171 
00172 
00173                 if (arg_count (table[index]) != P_NO_ARGS) {
00174 
00175 
00176 
00177                     length = arg_parse(*argv, &table[index]);
00178                     if (*argv == NULL)
00179                         argc = 0;
00180                     else if (length >= strlen (*argv)) {
00181                         argc--;
00182                         argv0 = *++argv;
00183                         use_prefix = TRUE;
00184                     } else {
00185                         (*argv) += length;
00186                         use_prefix = FALSE;
00187                     } 
00188                 } 
00189                   else
00190                     *arg_result_ptr(table[index]) =
00191                             arg_table_size(table[index]);
00192             } 
00193         } 
00194     } 
00195 
00196     return result;
00197 } 
00198 
00199 
00200  boolean
00201 #ifdef KR_headers
00202 arg_verify(argv, table, entries)
00203         char **argv;
00204         arg_info *table;
00205         int entries;
00206 #else
00207 arg_verify(char **argv, arg_info *table, int entries)
00208 #endif
00209 {
00210     int i;
00211     char *this_program = "";
00212 
00213     if (argv)
00214         this_program = argv[0];
00215 
00216     for (i = 0; i < entries; i++) {
00217         arg_info *arg = &table[i];
00218 
00219 
00220 
00221         if (arg_flags (*arg) & ~(P_CASE_INSENSITIVE | P_REQUIRED_PREFIX)) {
00222             fprintf (stderr, "%s [arg_verify]:  too many ", this_program);
00223             fprintf (stderr, "flags in entry %d:  '%x' (hex)\n", i,
00224                     arg_flags (*arg));
00225             badargs++;
00226         } 
00227 
00228 
00229 
00230         { int count = arg_count (*arg);
00231 
00232             if (count != P_NO_ARGS && count != P_ONE_ARG && count !=
00233                     P_INFINITE_ARGS) {
00234                 fprintf (stderr, "%s [arg_verify]:  invalid ", this_program);
00235                 fprintf (stderr, "argument count in entry %d:  '%d'\n", i,
00236                         count);
00237                 badargs++;
00238             } 
00239 
00240 
00241 
00242               else
00243                 if (arg_result_ptr (*arg) == (int *) NULL) {
00244                     fprintf (stderr, "%s [arg_verify]:  ", this_program);
00245                     fprintf (stderr, "no argument storage given for ");
00246                     fprintf (stderr, "entry %d\n", i);
00247                     badargs++;
00248                 } 
00249         }
00250 
00251 
00252 
00253         { int type = arg_result_type (*arg);
00254 
00255             if (type < P_STRING || type > P_DOUBLE) {
00256                     fprintf(stderr,
00257                         "%s [arg_verify]:  bad arg type in entry %d:  '%d'\n",
00258                         this_program, i, type);
00259                     badargs++;
00260                     }
00261         }
00262 
00263 
00264 
00265         { int size = arg_table_size (*arg);
00266 
00267             if (arg_count (*arg) == P_INFINITE_ARGS && size < 1) {
00268                 fprintf (stderr, "%s [arg_verify]:  bad ", this_program);
00269                 fprintf (stderr, "table size in entry %d:  '%d'\n", i,
00270                         size);
00271                 badargs++;
00272             } 
00273         }
00274 
00275     } 
00276 
00277     return TRUE;
00278 } 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286  int
00287 #ifdef KR_headers
00288 match_table(norm_input, table, entries, use_prefix, length)
00289         register char *norm_input;
00290         arg_info *table;
00291         int entries;
00292         boolean use_prefix;
00293         int *length;
00294 #else
00295 match_table(register char *norm_input, arg_info *table, int entries, boolean use_prefix, int *length)
00296 #endif
00297 {
00298     char low_input[MAX_INPUT_SIZE];
00299     register int i;
00300     int best_index = -1, best_length = 0;
00301 
00302 
00303 
00304     (void) lower_string (low_input, norm_input);
00305 
00306     for (i = 0; i < entries; i++) {
00307         int this_length = match(norm_input, low_input, &table[i], use_prefix);
00308 
00309         if (this_length > best_length) {
00310             best_index = i;
00311             best_length = this_length;
00312         } 
00313     } 
00314 
00315     if (best_index > -1 && length != (int *) NULL)
00316         *length = best_length;
00317 
00318     return best_index;
00319 } 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338  static int
00339 #ifdef KR_headers
00340 match(norm_input, low_input, entry, use_prefix)
00341         char *norm_input;
00342         char *low_input;
00343         arg_info *entry;
00344         boolean use_prefix;
00345 #else
00346 match(char *norm_input, char *low_input, arg_info *entry, boolean use_prefix)
00347 #endif
00348 {
00349     char *norm_prefix = arg_prefix (*entry);
00350     char *norm_string = arg_string (*entry);
00351     boolean prefix_match = FALSE, string_match = FALSE;
00352     int result = 0;
00353 
00354 
00355 
00356 
00357     static char low_prefix[MAX_INPUT_SIZE];
00358     static char low_string[MAX_INPUT_SIZE];
00359     int prefix_length = strlen (norm_prefix);
00360     int string_length = strlen (norm_string);
00361 
00362 
00363 
00364     register char *input, *prefix, *string;
00365 
00366 
00367 
00368 
00369 
00370     if (arg_flags (*entry) & P_CASE_INSENSITIVE) {
00371         input = low_input;
00372         prefix = lower_string (low_prefix, norm_prefix);
00373         string = lower_string (low_string, norm_string);
00374     } else {
00375         input = norm_input;
00376         prefix = norm_prefix;
00377         string = norm_string;
00378     } 
00379 
00380 
00381 
00382 
00383     if (use_prefix && prefix != NULL && *prefix != '\0')
00384          prefix_match = (strncmp (input, prefix, prefix_length) == 0) &&
00385                 (strncmp (input + prefix_length, string, string_length) == 0);
00386 
00387 
00388 
00389     if (!use_prefix && (arg_flags (*entry) & P_REQUIRED_PREFIX) == 0)
00390         string_match = strncmp (input, string, string_length) == 0;
00391 
00392     if (prefix_match)
00393         result = prefix_length + string_length;
00394     else if (string_match)
00395         result = string_length;
00396 
00397     return result;
00398 } 
00399 
00400 
00401  static char *
00402 #ifdef KR_headers
00403 lower_string(dest, src)
00404         char *dest;
00405         char *src;
00406 #else
00407 lower_string(char *dest, char *src)
00408 #endif
00409 {
00410     char *result = dest;
00411     register int c;
00412 
00413     if (dest == NULL || src == NULL)
00414         result = NULL;
00415     else
00416         while (*dest++ = (c = *src++) >= 'A' && c <= 'Z' ? tolower(c) : c);
00417 
00418     return result;
00419 } 
00420 
00421 
00422 
00423 
00424  static int
00425 #ifdef KR_headers
00426 arg_parse(str, entry)
00427         char *str;
00428         arg_info *entry;
00429 #else
00430 arg_parse(char *str, arg_info *entry)
00431 #endif
00432 {
00433     int length = 0;
00434 
00435     if (arg_count (*entry) == P_ONE_ARG) {
00436         char **store = (char **) arg_result_ptr (*entry);
00437 
00438         length = put_one_arg (arg_result_type (*entry), str, store,
00439                 arg_prefix (*entry), arg_string (*entry));
00440 
00441     } 
00442       else { 
00443         char **store = (char **) arg_result_ptr (*entry);
00444 
00445         if (store) {
00446             while (*store)
00447                 store++;
00448 
00449             length = put_one_arg(arg_result_type (*entry), str, store++,
00450                     arg_prefix (*entry), arg_string (*entry));
00451 
00452             *store = (char *) NULL;
00453         } 
00454     } 
00455 
00456     return length;
00457 } 
00458 
00459 
00460  static int
00461 #ifdef KR_headers
00462 put_one_arg(type, str, store, prefix, string)
00463         int type;
00464         char *str;
00465         char **store;
00466         char *prefix;
00467         char *string;
00468 #else
00469 put_one_arg(int type, char *str, char **store, char *prefix, char *string)
00470 #endif
00471 {
00472     int length = 0;
00473     long L;
00474 
00475     if (store) {
00476         switch (type) {
00477             case P_STRING:
00478             case P_FILE:
00479             case P_OLD_FILE:
00480             case P_NEW_FILE:
00481                 if (str == NULL) {
00482                         fprintf(stderr, "%s: Missing argument after '%s%s'\n",
00483                                 this_program, prefix, string);
00484                         length = 0;
00485                         badargs++;
00486                         }
00487                 else
00488                         length = strlen(*store = str);
00489                 break;
00490             case P_CHAR:
00491                 *((char *) store) = *str;
00492                 length = 1;
00493                 break;
00494             case P_SHORT:
00495                 L = atol(str);
00496                 *(short *)store = (short) L;
00497                 if (L != *(short *)store) {
00498                     fprintf(stderr,
00499         "%s%s parameter '%ld' is not a SHORT INT (truncating to %d)\n",
00500                             prefix, string, L, *(short *)store);
00501                     badargs++;
00502                     }
00503                 length = strlen (str);
00504                 break;
00505             case P_INT:
00506                 L = atol(str);
00507                 *(int *)store = (int)L;
00508                 if (L != *(int *)store) {
00509                     fprintf(stderr,
00510         "%s%s parameter '%ld' is not an INT (truncating to %d)\n",
00511                             prefix, string, L, *(int *)store);
00512                     badargs++;
00513                     }
00514                 length = strlen (str);
00515                 break;
00516             case P_LONG:
00517                 *(long *)store = atol(str);
00518                 length = strlen (str);
00519                 break;
00520             case P_FLOAT:
00521                 *((float *) store) = (float) atof(str);
00522                 length = strlen (str);
00523                 break;
00524             case P_DOUBLE:
00525                 *((double *) store) = (double) atof(str);
00526                 length = strlen (str);
00527                 break;
00528             default:
00529                 fprintf (stderr, "put_one_arg:  bad type '%d'\n", type);
00530                 badargs++;
00531                 break;
00532         } 
00533     } 
00534 
00535     return length;
00536 } 
00537 
00538 
00539  void
00540 #ifdef KR_headers
00541 init_store(table, entries)
00542         arg_info *table;
00543         int entries;
00544 #else
00545 init_store(arg_info *table, int entries)
00546 #endif
00547 {
00548     int index;
00549 
00550     for (index = 0; index < entries; index++)
00551         if (arg_count (table[index]) == P_INFINITE_ARGS) {
00552             char **place = (char **) arg_result_ptr (table[index]);
00553 
00554             if (place)
00555                 *place = (char *) NULL;
00556         } 
00557 
00558 }