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 }