00001
00036
00037
00038
00039 #include <GKlib.h>
00040
00041
00042
00043
00044 static void exchange (char **);
00045 static char *gk_getopt_initialize (int, char **, char *);
00046 static int gk_getopt_internal(int argc, char **argv, char *optstring,
00047 struct gk_option *longopts, int *longind, int long_only);
00048
00049
00050
00051
00057
00058 CMK_THREADLOCAL char *gk_optarg;
00059
00060
00061
00069
00070 CMK_THREADLOCAL int gk_optind = 1;
00071
00072
00073
00082
00083 CMK_THREADLOCAL int gk_opterr = 1;
00084
00085
00086
00093
00094 CMK_THREADLOCAL int gk_optopt = '?';
00095
00096
00097
00098
00099
00100
00101
00102 CMK_THREADLOCAL int gk_getopt_initialized;
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 static CMK_THREADLOCAL char *nextchar;
00116
00117
00118
00119
00120
00121
00122
00123 static CMK_THREADLOCAL char *posixly_correct;
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 static enum
00157 {
00158 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
00159 } ordering;
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 static CMK_THREADLOCAL int first_nonopt;
00171 static CMK_THREADLOCAL int last_nonopt;
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 static void exchange (char **argv)
00192 {
00193 int bottom = first_nonopt;
00194 int middle = last_nonopt;
00195 int top = gk_optind;
00196 char *tem;
00197
00198
00199
00200
00201
00202
00203 while (top > middle && middle > bottom) {
00204 if (top - middle > middle - bottom) {
00205
00206 int len = middle - bottom;
00207 register int i;
00208
00209
00210 for (i = 0; i < len; i++) {
00211 tem = argv[bottom + i];
00212 argv[bottom + i] = argv[top - (middle - bottom) + i];
00213 argv[top - (middle - bottom) + i] = tem;
00214 }
00215
00216 top -= len;
00217 }
00218 else {
00219
00220 int len = top - middle;
00221 register int i;
00222
00223
00224 for (i = 0; i < len; i++) {
00225 tem = argv[bottom + i];
00226 argv[bottom + i] = argv[middle + i];
00227 argv[middle + i] = tem;
00228 }
00229
00230 bottom += len;
00231 }
00232 }
00233
00234
00235
00236 first_nonopt += (gk_optind - last_nonopt);
00237 last_nonopt = gk_optind;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247 static char *gk_getopt_initialize (int argc, char **argv, char *optstring)
00248 {
00249
00250
00251
00252
00253 first_nonopt = last_nonopt = gk_optind;
00254
00255 nextchar = NULL;
00256
00257 posixly_correct = getenv("POSIXLY_CORRECT");
00258
00259
00260 if (optstring[0] == '-') {
00261 ordering = RETURN_IN_ORDER;
00262 ++optstring;
00263 }
00264 else if (optstring[0] == '+') {
00265 ordering = REQUIRE_ORDER;
00266 ++optstring;
00267 }
00268 else if (posixly_correct != NULL)
00269 ordering = REQUIRE_ORDER;
00270 else
00271 ordering = PERMUTE;
00272
00273 return optstring;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 static int gk_getopt_internal(int argc, char **argv, char *optstring,
00333 struct gk_option *longopts, int *longind, int long_only)
00334 {
00335 int print_errors = gk_opterr;
00336 if (optstring[0] == ':')
00337 print_errors = 0;
00338
00339 if (argc < 1)
00340 return -1;
00341
00342 gk_optarg = NULL;
00343
00344 if (gk_optind == 0 || !gk_getopt_initialized) {
00345 if (gk_optind == 0)
00346 gk_optind = 1;
00347 optstring = gk_getopt_initialize (argc, argv, optstring);
00348 gk_getopt_initialized = 1;
00349 }
00350
00351
00352
00353
00354
00355 # define NONOPTION_P (argv[gk_optind][0] != '-' || argv[gk_optind][1] == '\0')
00356
00357 if (nextchar == NULL || *nextchar == '\0') {
00358
00359
00360
00361
00362 if (last_nonopt > gk_optind)
00363 last_nonopt = gk_optind;
00364 if (first_nonopt > gk_optind)
00365 first_nonopt = gk_optind;
00366
00367 if (ordering == PERMUTE) {
00368
00369
00370
00371 if (first_nonopt != last_nonopt && last_nonopt != gk_optind)
00372 exchange ((char **) argv);
00373 else if (last_nonopt != gk_optind)
00374 first_nonopt = gk_optind;
00375
00376
00377
00378
00379 while (gk_optind < argc && NONOPTION_P)
00380 gk_optind++;
00381
00382 last_nonopt = gk_optind;
00383 }
00384
00385
00386
00387
00388
00389
00390 if (gk_optind != argc && !strcmp (argv[gk_optind], "--")) {
00391 gk_optind++;
00392
00393 if (first_nonopt != last_nonopt && last_nonopt != gk_optind)
00394 exchange ((char **) argv);
00395 else if (first_nonopt == last_nonopt)
00396 first_nonopt = gk_optind;
00397 last_nonopt = argc;
00398
00399 gk_optind = argc;
00400 }
00401
00402
00403
00404
00405 if (gk_optind == argc) {
00406
00407
00408 if (first_nonopt != last_nonopt)
00409 gk_optind = first_nonopt;
00410 return -1;
00411 }
00412
00413
00414
00415
00416 if (NONOPTION_P) {
00417 if (ordering == REQUIRE_ORDER)
00418 return -1;
00419 gk_optarg = argv[gk_optind++];
00420 return 1;
00421 }
00422
00423
00424
00425
00426 nextchar = (argv[gk_optind] + 1 + (longopts != NULL && argv[gk_optind][1] == '-'));
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 if (longopts != NULL && (argv[gk_optind][1] == '-' || (long_only && (argv[gk_optind][2] || !strchr(optstring, argv[gk_optind][1]))))) {
00445 char *nameend;
00446 struct gk_option *p;
00447 struct gk_option *pfound = NULL;
00448 int exact = 0;
00449 int ambig = 0;
00450 int indfound = -1;
00451 int option_index;
00452
00453 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
00454 ;
00455
00456
00457 for (p = longopts, option_index = 0; p->name; p++, option_index++) {
00458 if (!strncmp (p->name, nextchar, nameend - nextchar)) {
00459 if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) {
00460
00461 pfound = p;
00462 indfound = option_index;
00463 exact = 1;
00464 break;
00465 }
00466 else if (pfound == NULL) {
00467
00468 pfound = p;
00469 indfound = option_index;
00470 }
00471 else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val)
00472
00473 ambig = 1;
00474 }
00475 }
00476
00477 if (ambig && !exact) {
00478 if (print_errors)
00479 fprintf(stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[gk_optind]);
00480
00481 nextchar += strlen (nextchar);
00482 gk_optind++;
00483 gk_optopt = 0;
00484 return '?';
00485 }
00486
00487 if (pfound != NULL) {
00488 option_index = indfound;
00489 gk_optind++;
00490 if (*nameend) {
00491
00492 if (pfound->has_arg)
00493 gk_optarg = nameend + 1;
00494 else {
00495 if (print_errors) {
00496 if (argv[gk_optind - 1][1] == '-')
00497
00498 fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name);
00499 else
00500
00501 fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[gk_optind - 1][0], pfound->name);
00502 }
00503
00504 nextchar += strlen (nextchar);
00505
00506 gk_optopt = pfound->val;
00507 return '?';
00508 }
00509 }
00510 else if (pfound->has_arg == 1) {
00511 if (gk_optind < argc)
00512 gk_optarg = argv[gk_optind++];
00513 else {
00514 if (print_errors)
00515 fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[gk_optind - 1]);
00516 nextchar += strlen (nextchar);
00517 gk_optopt = pfound->val;
00518 return optstring[0] == ':' ? ':' : '?';
00519 }
00520 }
00521 nextchar += strlen (nextchar);
00522 if (longind != NULL)
00523 *longind = option_index;
00524 if (pfound->flag) {
00525 *(pfound->flag) = pfound->val;
00526 return 0;
00527 }
00528 return pfound->val;
00529 }
00530
00531
00532
00533
00534 if (!long_only || argv[gk_optind][1] == '-' || strchr(optstring, *nextchar) == NULL) {
00535 if (print_errors) {
00536 if (argv[gk_optind][1] == '-')
00537
00538 fprintf(stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar);
00539 else
00540
00541 fprintf(stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[gk_optind][0], nextchar);
00542 }
00543 nextchar = (char *) "";
00544 gk_optind++;
00545 gk_optopt = 0;
00546 return '?';
00547 }
00548 }
00549
00550
00551 {
00552 char c = *nextchar++;
00553 char *temp = strchr(optstring, c);
00554
00555
00556 if (*nextchar == '\0')
00557 ++gk_optind;
00558
00559 if (temp == NULL || c == ':') {
00560 if (print_errors) {
00561 if (posixly_correct)
00562
00563 fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c);
00564 else
00565 fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
00566 }
00567 gk_optopt = c;
00568 return '?';
00569 }
00570
00571
00572 if (temp[0] == 'W' && temp[1] == ';') {
00573 char *nameend;
00574 struct gk_option *p;
00575 struct gk_option *pfound = NULL;
00576 int exact = 0;
00577 int ambig = 0;
00578 int indfound = 0;
00579 int option_index;
00580
00581
00582 if (*nextchar != '\0') {
00583 gk_optarg = nextchar;
00584
00585
00586 gk_optind++;
00587 }
00588 else if (gk_optind == argc) {
00589 if (print_errors) {
00590
00591 fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c);
00592 }
00593 gk_optopt = c;
00594 if (optstring[0] == ':')
00595 c = ':';
00596 else
00597 c = '?';
00598 return c;
00599 }
00600 else
00601
00602 gk_optarg = argv[gk_optind++];
00603
00604
00605
00606 for (nextchar = nameend = gk_optarg; *nameend && *nameend != '='; nameend++)
00607 ;
00608
00609
00610 for (p = longopts, option_index = 0; p->name; p++, option_index++) {
00611 if (!strncmp (p->name, nextchar, nameend - nextchar)) {
00612 if ((unsigned int) (nameend - nextchar) == strlen (p->name)) {
00613
00614 pfound = p;
00615 indfound = option_index;
00616 exact = 1;
00617 break;
00618 }
00619 else if (pfound == NULL) {
00620
00621 pfound = p;
00622 indfound = option_index;
00623 }
00624 else
00625
00626 ambig = 1;
00627 }
00628 }
00629 if (ambig && !exact) {
00630 if (print_errors)
00631 fprintf(stderr, "%s: option `-W %s' is ambiguous\n", argv[0], argv[gk_optind]);
00632 nextchar += strlen (nextchar);
00633 gk_optind++;
00634 return '?';
00635 }
00636 if (pfound != NULL) {
00637 option_index = indfound;
00638 if (*nameend) {
00639
00640 if (pfound->has_arg)
00641 gk_optarg = nameend + 1;
00642 else {
00643 if (print_errors)
00644 fprintf(stderr, "%s: option `-W %s' doesn't allow an argument\n", argv[0], pfound->name);
00645
00646 nextchar += strlen (nextchar);
00647 return '?';
00648 }
00649 }
00650 else if (pfound->has_arg == 1) {
00651 if (gk_optind < argc)
00652 gk_optarg = argv[gk_optind++];
00653 else {
00654 if (print_errors)
00655 fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[gk_optind - 1]);
00656 nextchar += strlen (nextchar);
00657 return optstring[0] == ':' ? ':' : '?';
00658 }
00659 }
00660 nextchar += strlen (nextchar);
00661 if (longind != NULL)
00662 *longind = option_index;
00663 if (pfound->flag) {
00664 *(pfound->flag) = pfound->val;
00665 return 0;
00666 }
00667 return pfound->val;
00668 }
00669 nextchar = NULL;
00670 return 'W';
00671 }
00672
00673 if (temp[1] == ':') {
00674 if (temp[2] == ':') {
00675
00676 if (*nextchar != '\0') {
00677 gk_optarg = nextchar;
00678 gk_optind++;
00679 }
00680 else
00681 gk_optarg = NULL;
00682 nextchar = NULL;
00683 }
00684 else {
00685
00686 if (*nextchar != '\0') {
00687 gk_optarg = nextchar;
00688
00689 gk_optind++;
00690 }
00691 else if (gk_optind == argc) {
00692 if (print_errors) {
00693
00694 fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c);
00695 }
00696 gk_optopt = c;
00697 if (optstring[0] == ':')
00698 c = ':';
00699 else
00700 c = '?';
00701 }
00702 else
00703
00704 gk_optarg = argv[gk_optind++];
00705 nextchar = NULL;
00706 }
00707 }
00708 return c;
00709 }
00710 }
00711
00712
00713
00714
00770
00771 int gk_getopt(int argc, char **argv, char *options)
00772 {
00773 return gk_getopt_internal(argc, argv, options, NULL, NULL, 0);
00774 }
00775
00776
00777
00834
00835 int gk_getopt_long( int argc, char **argv, char *options,
00836 struct gk_option *long_options, int *opt_index)
00837 {
00838 return gk_getopt_internal (argc, argv, options, long_options, opt_index, 0);
00839 }
00840
00841
00842
00843
00850
00851 int gk_getopt_long_only(int argc, char **argv, char *options,
00852 struct gk_option *long_options, int *opt_index)
00853 {
00854 return gk_getopt_internal(argc, argv, options, long_options, opt_index, 1);
00855 }
00856