diff options
Diffstat (limited to 'src/util/getopt.c')
-rw-r--r-- | src/util/getopt.c | 200 |
1 files changed, 114 insertions, 86 deletions
diff --git a/src/util/getopt.c b/src/util/getopt.c index 44f6dcda2..048f52ee0 100644 --- a/src/util/getopt.c +++ b/src/util/getopt.c | |||
@@ -47,14 +47,15 @@ Copyright (C) 2006, 2017 Christian Grothoff | |||
47 | #endif | 47 | #endif |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | #define LOG(kind,...) GNUNET_log_from (kind, "util-getopt", __VA_ARGS__) | 50 | #define LOG(kind, ...) GNUNET_log_from (kind, "util-getopt", __VA_ARGS__) |
51 | 51 | ||
52 | #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-getopt", syscall) | 52 | #define LOG_STRERROR(kind, syscall) \ |
53 | GNUNET_log_from_strerror (kind, "util-getopt", syscall) | ||
53 | 54 | ||
54 | #if defined (WIN32) && !defined (__CYGWIN32__) | 55 | #if defined(WIN32) && ! defined(__CYGWIN32__) |
55 | /* It's not Unix, really. See? Capital letters. */ | 56 | /* It's not Unix, really. See? Capital letters. */ |
56 | #include <windows.h> | 57 | #include <windows.h> |
57 | #define getpid() GetCurrentProcessId() | 58 | #define getpid() GetCurrentProcessId () |
58 | #endif | 59 | #endif |
59 | 60 | ||
60 | #ifndef _ | 61 | #ifndef _ |
@@ -62,9 +63,9 @@ Copyright (C) 2006, 2017 Christian Grothoff | |||
62 | When compiling libc, the _ macro is predefined. */ | 63 | When compiling libc, the _ macro is predefined. */ |
63 | #ifdef HAVE_LIBINTL_H | 64 | #ifdef HAVE_LIBINTL_H |
64 | #include <libintl.h> | 65 | #include <libintl.h> |
65 | #define _(msgid) gettext (msgid) | 66 | #define _(msgid) gettext (msgid) |
66 | #else | 67 | #else |
67 | #define _(msgid) (msgid) | 68 | #define _(msgid) (msgid) |
68 | #endif | 69 | #endif |
69 | #endif | 70 | #endif |
70 | 71 | ||
@@ -176,21 +177,18 @@ static char *nextchar; | |||
176 | of the value of `ordering'. In the case of RETURN_IN_ORDER, only | 177 | of the value of `ordering'. In the case of RETURN_IN_ORDER, only |
177 | `--' can cause `getopt' to return -1 with `GNoptind' != ARGC. */ | 178 | `--' can cause `getopt' to return -1 with `GNoptind' != ARGC. */ |
178 | 179 | ||
179 | static enum | 180 | static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; |
180 | { | ||
181 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER | ||
182 | } ordering; | ||
183 | 181 | ||
184 | /* Value of POSIXLY_CORRECT environment variable. */ | 182 | /* Value of POSIXLY_CORRECT environment variable. */ |
185 | static char *posixly_correct; | 183 | static char *posixly_correct; |
186 | 184 | ||
187 | #ifdef __GNU_LIBRARY__ | 185 | #ifdef __GNU_LIBRARY__ |
188 | /* We want to avoid inclusion of string.h with non-GNU libraries | 186 | /* We want to avoid inclusion of string.h with non-GNU libraries |
189 | because there are many ways it can cause trouble. | 187 | because there are many ways it can cause trouble. |
190 | On some systems, it contains special magic macros that don't work | 188 | On some systems, it contains special magic macros that don't work |
191 | in GCC. */ | 189 | in GCC. */ |
192 | #include <string.h> | 190 | #include <string.h> |
193 | #define my_index strchr | 191 | #define my_index strchr |
194 | #else | 192 | #else |
195 | 193 | ||
196 | /* Avoid depending on library functions or files | 194 | /* Avoid depending on library functions or files |
@@ -200,8 +198,7 @@ char * | |||
200 | getenv (); | 198 | getenv (); |
201 | 199 | ||
202 | static char * | 200 | static char * |
203 | my_index (const char *str, | 201 | my_index (const char *str, int chr) |
204 | int chr) | ||
205 | { | 202 | { |
206 | while (*str) | 203 | while (*str) |
207 | { | 204 | { |
@@ -217,7 +214,7 @@ my_index (const char *str, | |||
217 | #ifdef __GNUC__ | 214 | #ifdef __GNUC__ |
218 | /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. | 215 | /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. |
219 | That was relevant to code that was here before. */ | 216 | That was relevant to code that was here before. */ |
220 | #if !defined (__STDC__) || !__STDC__ | 217 | #if ! defined(__STDC__) || ! __STDC__ |
221 | /* gcc with -traditional declares the built-in strlen to return int, | 218 | /* gcc with -traditional declares the built-in strlen to return int, |
222 | and has done so at least since version 2.4.5. -- rms. */ | 219 | and has done so at least since version 2.4.5. -- rms. */ |
223 | extern int | 220 | extern int |
@@ -247,7 +244,7 @@ static int last_nonopt; | |||
247 | `first_nonopt' and `last_nonopt' are relocated so that they describe | 244 | `first_nonopt' and `last_nonopt' are relocated so that they describe |
248 | the new indices of the non-options in ARGV after they are moved. */ | 245 | the new indices of the non-options in ARGV after they are moved. */ |
249 | 246 | ||
250 | #if defined (__STDC__) && __STDC__ | 247 | #if defined(__STDC__) && __STDC__ |
251 | static void | 248 | static void |
252 | exchange (char **); | 249 | exchange (char **); |
253 | #endif | 250 | #endif |
@@ -311,14 +308,12 @@ exchange (char **argv) | |||
311 | 308 | ||
312 | /* Initialize the internal data when the first call is made. */ | 309 | /* Initialize the internal data when the first call is made. */ |
313 | 310 | ||
314 | #if defined (__STDC__) && __STDC__ | 311 | #if defined(__STDC__) && __STDC__ |
315 | static const char * | 312 | static const char * |
316 | _getopt_initialize (int, char *const *, const char *); | 313 | _getopt_initialize (int, char *const *, const char *); |
317 | #endif | 314 | #endif |
318 | static const char * | 315 | static const char * |
319 | _getopt_initialize (int argc, | 316 | _getopt_initialize (int argc, char *const *argv, const char *optstring) |
320 | char *const *argv, | ||
321 | const char *optstring) | ||
322 | { | 317 | { |
323 | /* Start processing options with ARGV-element 1 (since ARGV-element 0 | 318 | /* Start processing options with ARGV-element 1 (since ARGV-element 0 |
324 | * is the program name); the sequence of previously skipped | 319 | * is the program name); the sequence of previously skipped |
@@ -407,8 +402,11 @@ _getopt_initialize (int argc, | |||
407 | long-named options. */ | 402 | long-named options. */ |
408 | 403 | ||
409 | static int | 404 | static int |
410 | GN_getopt_internal (int argc, char *const *argv, const char *optstring, | 405 | GN_getopt_internal (int argc, |
411 | const struct GNoption *longopts, int *longind, | 406 | char *const *argv, |
407 | const char *optstring, | ||
408 | const struct GNoption *longopts, | ||
409 | int *longind, | ||
412 | int long_only) | 410 | int long_only) |
413 | { | 411 | { |
414 | static int __getopt_initialized = 0; | 412 | static int __getopt_initialized = 0; |
@@ -416,10 +414,10 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
416 | 414 | ||
417 | GNoptarg = NULL; | 415 | GNoptarg = NULL; |
418 | 416 | ||
419 | if (GNoptind == 0 || !__getopt_initialized) | 417 | if (GNoptind == 0 || ! __getopt_initialized) |
420 | { | 418 | { |
421 | if (GNoptind == 0) | 419 | if (GNoptind == 0) |
422 | GNoptind = 1; /* Don't scan ARGV[0], the program name. */ | 420 | GNoptind = 1; /* Don't scan ARGV[0], the program name. */ |
423 | optstring = _getopt_initialize (argc, argv, optstring); | 421 | optstring = _getopt_initialize (argc, argv, optstring); |
424 | __getopt_initialized = 1; | 422 | __getopt_initialized = 1; |
425 | } | 423 | } |
@@ -463,7 +461,7 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
463 | * Skip it like a null option, | 461 | * Skip it like a null option, |
464 | * then exchange with previous non-options as if it were an option, | 462 | * then exchange with previous non-options as if it were an option, |
465 | * then skip everything else like a non-option. */ | 463 | * then skip everything else like a non-option. */ |
466 | if (GNoptind != argc && !strcmp (argv[GNoptind], "--")) | 464 | if (GNoptind != argc && ! strcmp (argv[GNoptind], "--")) |
467 | { | 465 | { |
468 | GNoptind++; | 466 | GNoptind++; |
469 | 467 | ||
@@ -503,7 +501,7 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
503 | * Skip the initial punctuation. */ | 501 | * Skip the initial punctuation. */ |
504 | 502 | ||
505 | nextchar = | 503 | nextchar = |
506 | (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-')); | 504 | (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-')); |
507 | } | 505 | } |
508 | 506 | ||
509 | /* Decode the current option-ARGV-element. */ | 507 | /* Decode the current option-ARGV-element. */ |
@@ -524,7 +522,7 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
524 | if (longopts != NULL && | 522 | if (longopts != NULL && |
525 | (argv[GNoptind][1] == '-' || | 523 | (argv[GNoptind][1] == '-' || |
526 | (long_only && | 524 | (long_only && |
527 | (argv[GNoptind][2] || !my_index (optstring, argv[GNoptind][1]))))) | 525 | (argv[GNoptind][2] || ! my_index (optstring, argv[GNoptind][1]))))) |
528 | { | 526 | { |
529 | char *nameend; | 527 | char *nameend; |
530 | const struct GNoption *p; | 528 | const struct GNoption *p; |
@@ -535,12 +533,12 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
535 | int option_index; | 533 | int option_index; |
536 | 534 | ||
537 | for (nameend = nextchar; *nameend && *nameend != '='; nameend++) | 535 | for (nameend = nextchar; *nameend && *nameend != '='; nameend++) |
538 | /* Do nothing. */ ; | 536 | /* Do nothing. */; |
539 | 537 | ||
540 | /* Test all long options for either exact match | 538 | /* Test all long options for either exact match |
541 | * or abbreviated matches. */ | 539 | * or abbreviated matches. */ |
542 | for (p = longopts, option_index = 0; p->name; p++, option_index++) | 540 | for (p = longopts, option_index = 0; p->name; p++, option_index++) |
543 | if (!strncmp (p->name, nextchar, nameend - nextchar)) | 541 | if (! strncmp (p->name, nextchar, nameend - nextchar)) |
544 | { | 542 | { |
545 | if ((unsigned int) (nameend - nextchar) == | 543 | if ((unsigned int) (nameend - nextchar) == |
546 | (unsigned int) strlen (p->name)) | 544 | (unsigned int) strlen (p->name)) |
@@ -562,10 +560,12 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
562 | ambig = 1; | 560 | ambig = 1; |
563 | } | 561 | } |
564 | 562 | ||
565 | if (ambig && !exact) | 563 | if (ambig && ! exact) |
566 | { | 564 | { |
567 | if (GNopterr) | 565 | if (GNopterr) |
568 | FPRINTF (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], | 566 | FPRINTF (stderr, |
567 | _ ("%s: option `%s' is ambiguous\n"), | ||
568 | argv[0], | ||
569 | argv[GNoptind]); | 569 | argv[GNoptind]); |
570 | nextchar += strlen (nextchar); | 570 | nextchar += strlen (nextchar); |
571 | GNoptind++; | 571 | GNoptind++; |
@@ -589,13 +589,16 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
589 | if (argv[GNoptind - 1][1] == '-') | 589 | if (argv[GNoptind - 1][1] == '-') |
590 | /* --option */ | 590 | /* --option */ |
591 | FPRINTF (stderr, | 591 | FPRINTF (stderr, |
592 | _("%s: option `--%s' does not allow an argument\n"), | 592 | _ ("%s: option `--%s' does not allow an argument\n"), |
593 | argv[0], pfound->name); | 593 | argv[0], |
594 | pfound->name); | ||
594 | else | 595 | else |
595 | /* +option or -option */ | 596 | /* +option or -option */ |
596 | FPRINTF (stderr, | 597 | FPRINTF (stderr, |
597 | _("%s: option `%c%s' does not allow an argument\n"), | 598 | _ ("%s: option `%c%s' does not allow an argument\n"), |
598 | argv[0], argv[GNoptind - 1][0], pfound->name); | 599 | argv[0], |
600 | argv[GNoptind - 1][0], | ||
601 | pfound->name); | ||
599 | } | 602 | } |
600 | nextchar += strlen (nextchar); | 603 | nextchar += strlen (nextchar); |
601 | return '?'; | 604 | return '?'; |
@@ -611,8 +614,10 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
611 | { | 614 | { |
612 | if (GNopterr) | 615 | if (GNopterr) |
613 | { | 616 | { |
614 | FPRINTF (stderr, _("%s: option `%s' requires an argument\n"), | 617 | FPRINTF (stderr, |
615 | argv[0], argv[GNoptind - 1]); | 618 | _ ("%s: option `%s' requires an argument\n"), |
619 | argv[0], | ||
620 | argv[GNoptind - 1]); | ||
616 | } | 621 | } |
617 | nextchar += strlen (nextchar); | 622 | nextchar += strlen (nextchar); |
618 | return (optstring[0] == ':') ? ':' : '?'; | 623 | return (optstring[0] == ':') ? ':' : '?'; |
@@ -633,19 +638,24 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
633 | * or the option starts with '--' or is not a valid short | 638 | * or the option starts with '--' or is not a valid short |
634 | * option, then it's an error. | 639 | * option, then it's an error. |
635 | * Otherwise interpret it as a short option. */ | 640 | * Otherwise interpret it as a short option. */ |
636 | if (!long_only || argv[GNoptind][1] == '-' || | 641 | if (! long_only || argv[GNoptind][1] == '-' || |
637 | my_index (optstring, *nextchar) == NULL) | 642 | my_index (optstring, *nextchar) == NULL) |
638 | { | 643 | { |
639 | if (GNopterr) | 644 | if (GNopterr) |
640 | { | 645 | { |
641 | if (argv[GNoptind][1] == '-') | 646 | if (argv[GNoptind][1] == '-') |
642 | /* --option */ | 647 | /* --option */ |
643 | FPRINTF (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], | 648 | FPRINTF (stderr, |
649 | _ ("%s: unrecognized option `--%s'\n"), | ||
650 | argv[0], | ||
644 | nextchar); | 651 | nextchar); |
645 | else | 652 | else |
646 | /* +option or -option */ | 653 | /* +option or -option */ |
647 | FPRINTF (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], | 654 | FPRINTF (stderr, |
648 | argv[GNoptind][0], nextchar); | 655 | _ ("%s: unrecognized option `%c%s'\n"), |
656 | argv[0], | ||
657 | argv[GNoptind][0], | ||
658 | nextchar); | ||
649 | } | 659 | } |
650 | nextchar = (char *) ""; | 660 | nextchar = (char *) ""; |
651 | GNoptind++; | 661 | GNoptind++; |
@@ -669,9 +679,9 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
669 | { | 679 | { |
670 | if (posixly_correct) | 680 | if (posixly_correct) |
671 | /* 1003.2 specifies the format of this message. */ | 681 | /* 1003.2 specifies the format of this message. */ |
672 | FPRINTF (stderr, _("%s: illegal option -- %c\n"), argv[0], c); | 682 | FPRINTF (stderr, _ ("%s: illegal option -- %c\n"), argv[0], c); |
673 | else | 683 | else |
674 | FPRINTF (stderr, _("%s: invalid option -- %c\n"), argv[0], c); | 684 | FPRINTF (stderr, _ ("%s: invalid option -- %c\n"), argv[0], c); |
675 | } | 685 | } |
676 | return '?'; | 686 | return '?'; |
677 | } | 687 | } |
@@ -699,8 +709,10 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
699 | if (GNopterr) | 709 | if (GNopterr) |
700 | { | 710 | { |
701 | /* 1003.2 specifies the format of this message. */ | 711 | /* 1003.2 specifies the format of this message. */ |
702 | FPRINTF (stderr, _("%s: option requires an argument -- %c\n"), | 712 | FPRINTF (stderr, |
703 | argv[0], c); | 713 | _ ("%s: option requires an argument -- %c\n"), |
714 | argv[0], | ||
715 | c); | ||
704 | } | 716 | } |
705 | if (optstring[0] == ':') | 717 | if (optstring[0] == ':') |
706 | c = ':'; | 718 | c = ':'; |
@@ -718,13 +730,13 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
718 | 730 | ||
719 | for (nextchar = nameend = GNoptarg; *nameend && *nameend != '='; | 731 | for (nextchar = nameend = GNoptarg; *nameend && *nameend != '='; |
720 | nameend++) | 732 | nameend++) |
721 | /* Do nothing. */ ; | 733 | /* Do nothing. */; |
722 | 734 | ||
723 | /* Test all long options for either exact match | 735 | /* Test all long options for either exact match |
724 | * or abbreviated matches. */ | 736 | * or abbreviated matches. */ |
725 | if (longopts != NULL) | 737 | if (longopts != NULL) |
726 | for (p = longopts, option_index = 0; p->name; p++, option_index++) | 738 | for (p = longopts, option_index = 0; p->name; p++, option_index++) |
727 | if (!strncmp (p->name, nextchar, nameend - nextchar)) | 739 | if (! strncmp (p->name, nextchar, nameend - nextchar)) |
728 | { | 740 | { |
729 | if ((unsigned int) (nameend - nextchar) == strlen (p->name)) | 741 | if ((unsigned int) (nameend - nextchar) == strlen (p->name)) |
730 | { | 742 | { |
@@ -744,10 +756,12 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
744 | /* Second or later nonexact match found. */ | 756 | /* Second or later nonexact match found. */ |
745 | ambig = 1; | 757 | ambig = 1; |
746 | } | 758 | } |
747 | if (ambig && !exact) | 759 | if (ambig && ! exact) |
748 | { | 760 | { |
749 | if (GNopterr) | 761 | if (GNopterr) |
750 | FPRINTF (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], | 762 | FPRINTF (stderr, |
763 | _ ("%s: option `-W %s' is ambiguous\n"), | ||
764 | argv[0], | ||
751 | argv[GNoptind]); | 765 | argv[GNoptind]); |
752 | nextchar += strlen (nextchar); | 766 | nextchar += strlen (nextchar); |
753 | GNoptind++; | 767 | GNoptind++; |
@@ -765,7 +779,10 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
765 | else | 779 | else |
766 | { | 780 | { |
767 | if (GNopterr) | 781 | if (GNopterr) |
768 | FPRINTF (stderr, _("%s: option `-W %s' does not allow an argument\n"), argv[0], pfound->name); | 782 | FPRINTF (stderr, |
783 | _ ("%s: option `-W %s' does not allow an argument\n"), | ||
784 | argv[0], | ||
785 | pfound->name); | ||
769 | 786 | ||
770 | nextchar += strlen (nextchar); | 787 | nextchar += strlen (nextchar); |
771 | return '?'; | 788 | return '?'; |
@@ -778,8 +795,10 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
778 | else | 795 | else |
779 | { | 796 | { |
780 | if (GNopterr) | 797 | if (GNopterr) |
781 | FPRINTF (stderr, _("%s: option `%s' requires an argument\n"), | 798 | FPRINTF (stderr, |
782 | argv[0], argv[GNoptind - 1]); | 799 | _ ("%s: option `%s' requires an argument\n"), |
800 | argv[0], | ||
801 | argv[GNoptind - 1]); | ||
783 | nextchar += strlen (nextchar); | 802 | nextchar += strlen (nextchar); |
784 | return optstring[0] == ':' ? ':' : '?'; | 803 | return optstring[0] == ':' ? ':' : '?'; |
785 | } | 804 | } |
@@ -795,7 +814,7 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
795 | return pfound->val; | 814 | return pfound->val; |
796 | } | 815 | } |
797 | nextchar = NULL; | 816 | nextchar = NULL; |
798 | return 'W'; /* Let the application handle it. */ | 817 | return 'W'; /* Let the application handle it. */ |
799 | } | 818 | } |
800 | if (temp[1] == ':') | 819 | if (temp[1] == ':') |
801 | { | 820 | { |
@@ -826,8 +845,10 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, | |||
826 | if (GNopterr) | 845 | if (GNopterr) |
827 | { | 846 | { |
828 | /* 1003.2 specifies the format of this message. */ | 847 | /* 1003.2 specifies the format of this message. */ |
829 | FPRINTF (stderr, _("%s: option requires an argument -- %c\n"), | 848 | FPRINTF (stderr, |
830 | argv[0], c); | 849 | _ ("%s: option requires an argument -- %c\n"), |
850 | argv[0], | ||
851 | c); | ||
831 | } | 852 | } |
832 | if (optstring[0] == ':') | 853 | if (optstring[0] == ':') |
833 | c = ':'; | 854 | c = ':'; |
@@ -880,8 +901,9 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
880 | char *shorts; | 901 | char *shorts; |
881 | int spos; | 902 | int spos; |
882 | int cont; | 903 | int cont; |
883 | int c; | ||
884 | uint8_t *seen; | 904 | uint8_t *seen; |
905 | unsigned int optmatch = 0; | ||
906 | const char *have_exclusive = NULL; | ||
885 | 907 | ||
886 | GNUNET_assert (argc > 0); | 908 | GNUNET_assert (argc > 0); |
887 | GNoptind = 0; | 909 | GNoptind = 0; |
@@ -890,12 +912,13 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
890 | clpc.allOptions = allOptions; | 912 | clpc.allOptions = allOptions; |
891 | clpc.argv = argv; | 913 | clpc.argv = argv; |
892 | clpc.argc = argc; | 914 | clpc.argc = argc; |
893 | for (count = 0; NULL != allOptions[count].name; count++) ; | 915 | for (count = 0; NULL != allOptions[count].name; count++) |
916 | ; | ||
894 | 917 | ||
895 | long_options = GNUNET_new_array (count + 1, | 918 | /* transform our option representation into the format |
896 | struct GNoption); | 919 | used by the GNU getopt copylib */ |
897 | seen = GNUNET_new_array (count, | 920 | long_options = GNUNET_new_array (count + 1, struct GNoption); |
898 | uint8_t); | 921 | seen = GNUNET_new_array (count, uint8_t); |
899 | shorts = GNUNET_malloc (count * 2 + 1); | 922 | shorts = GNUNET_malloc (count * 2 + 1); |
900 | spos = 0; | 923 | spos = 0; |
901 | for (unsigned i = 0; i < count; i++) | 924 | for (unsigned i = 0; i < count; i++) |
@@ -916,59 +939,64 @@ GNUNET_GETOPT_run (const char *binaryOptions, | |||
916 | cont = GNUNET_OK; | 939 | cont = GNUNET_OK; |
917 | 940 | ||
918 | /* main getopt loop */ | 941 | /* main getopt loop */ |
919 | while (GNUNET_OK == cont) | 942 | while (1) |
920 | { | 943 | { |
921 | int option_index = 0; | 944 | int option_index = 0; |
922 | unsigned int i; | 945 | unsigned int i; |
946 | int c; | ||
923 | 947 | ||
924 | c = GNgetopt_long (argc, argv, | 948 | c = GNgetopt_long (argc, argv, shorts, long_options, &option_index); |
925 | shorts, | ||
926 | long_options, | ||
927 | &option_index); | ||
928 | if (c == GNUNET_SYSERR) | 949 | if (c == GNUNET_SYSERR) |
929 | break; /* No more flags to process */ | 950 | break; /* No more flags to process */ |
930 | 951 | ||
952 | /* Check which of our program's options was given by the user */ | ||
931 | for (i = 0; i < count; i++) | 953 | for (i = 0; i < count; i++) |
932 | { | 954 | { |
933 | clpc.currentArgument = GNoptind - 1; | 955 | clpc.currentArgument = GNoptind - 1; |
934 | if ((char) c == allOptions[i].shortName) | 956 | if ((char) c == allOptions[i].shortName) |
935 | { | 957 | { |
936 | cont = allOptions[i].processor (&clpc, | 958 | optmatch++; |
937 | allOptions[i].scls, | 959 | if (allOptions[i].option_exclusive) |
938 | allOptions[i].name, | 960 | have_exclusive = allOptions[i].name; |
939 | GNoptarg); | 961 | if (GNUNET_OK == cont) |
962 | { | ||
963 | /* parse the option using the option-specific processor */ | ||
964 | cont = allOptions[i].processor (&clpc, | ||
965 | allOptions[i].scls, | ||
966 | allOptions[i].name, | ||
967 | GNoptarg); | ||
968 | } | ||
940 | seen[i] = 1; | 969 | seen[i] = 1; |
941 | break; | 970 | break; |
942 | } | 971 | } |
943 | } | 972 | } |
944 | if (i == count) | 973 | if (i == count) |
945 | { | 974 | { |
946 | FPRINTF (stderr, | 975 | FPRINTF (stderr, _ ("Use %s to get a list of options.\n"), "--help"); |
947 | _("Use %s to get a list of options.\n"), | ||
948 | "--help"); | ||
949 | cont = GNUNET_SYSERR; | 976 | cont = GNUNET_SYSERR; |
950 | } | 977 | } |
951 | } | 978 | } |
952 | GNUNET_free (shorts); | 979 | GNUNET_free (shorts); |
953 | GNUNET_free (long_options); | 980 | GNUNET_free (long_options); |
954 | 981 | ||
982 | /* check that if any option that was marked as exclusive | ||
983 | is the only option that was provided */ | ||
984 | if ((NULL != have_exclusive) && (optmatch > 1)) | ||
985 | { | ||
986 | FPRINTF (stderr, | ||
987 | _ ("Option `%s' can't be used with other options.\n"), | ||
988 | have_exclusive); | ||
989 | cont = GNUNET_SYSERR; | ||
990 | } | ||
955 | if (GNUNET_YES == cont) | 991 | if (GNUNET_YES == cont) |
956 | { | 992 | { |
957 | for (count = 0; NULL != allOptions[count].name; count++) | 993 | /* check that all mandatory options are present */ |
994 | for (count = 0; NULL != allOptions[count].name; count++) | ||
958 | { | 995 | { |
959 | if (allOptions[count].option_exclusive) | 996 | if ((0 == seen[count]) && (allOptions[count].option_mandatory)) |
960 | { | ||
961 | FPRINTF (stderr, | ||
962 | _("Option `%s' can't be used with other options.\n"), | ||
963 | allOptions[count].name); | ||
964 | cont = GNUNET_SYSERR; | ||
965 | } | ||
966 | |||
967 | if ( (0 == seen[count]) && | ||
968 | (allOptions[count].option_mandatory) ) | ||
969 | { | 997 | { |
970 | FPRINTF (stderr, | 998 | FPRINTF (stderr, |
971 | _("Missing mandatory option `%s'.\n"), | 999 | _ ("Missing mandatory option `%s'.\n"), |
972 | allOptions[count].name); | 1000 | allOptions[count].name); |
973 | cont = GNUNET_SYSERR; | 1001 | cont = GNUNET_SYSERR; |
974 | } | 1002 | } |