Remove win32 and cygwin support
[oweals/gnunet.git] / src / util / getopt.c
1 /* Getopt for GNU.
2    NOTE: getopt is now part of the C library, so if you don't know what
3    "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
4    before changing it!
5
6    Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
7      Free Software Foundation, Inc.
8
9    NOTE: The canonical source of this file is maintained with the GNU C Library.
10    Bugs can be reported to bug-glibc@prep.ai.mit.edu.
11
12    This program is free software; you can redistribute it and/or modify it
13    under the terms of the GNU General Public License as published by the
14    Free Software Foundation; either version 3, or (at your option) any
15    later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25    USA.
26
27
28    This code was heavily modified for GNUnet.
29    Copyright (C) 2006, 2017 Christian Grothoff
30  */
31
32 /**
33  * @file util/getopt.c
34  * @brief GNU style option parsing
35  *
36  * TODO: get rid of statics (make reentrant) and
37  * replace main GNU getopt parser with one that
38  * actually fits our API.
39  */
40 #include "platform.h"
41 #include "gnunet_util_lib.h"
42
43 #ifdef VMS
44 #include <unixlib.h>
45 #if HAVE_STRING_H - 0
46 #include <string.h>
47 #endif
48 #endif
49
50 #define LOG(kind, ...) GNUNET_log_from(kind, "util-getopt", __VA_ARGS__)
51
52 #define LOG_STRERROR(kind, syscall) \
53   GNUNET_log_from_strerror(kind, "util-getopt", syscall)
54
55 #ifndef _
56 /* This is for other GNU distributions with internationalized messages.
57    When compiling libc, the _ macro is predefined.  */
58 #ifdef HAVE_LIBINTL_H
59 #include <libintl.h>
60 #define _(msgid) gettext(msgid)
61 #else
62 #define _(msgid) (msgid)
63 #endif
64 #endif
65
66 /* Describe the long-named options requested by the application.
67    The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
68    of `struct GNoption' terminated by an element containing a name which is
69    zero.
70
71    The field `has_arg' is:
72    no_argument          (or 0) if the option does not take an argument,
73    required_argument  (or 1) if the option requires an argument,
74    optional_argument   (or 2) if the option takes an optional argument.
75
76    If the field `flag' is not NULL, it points to a variable that is set
77    to the value given in the field `val' when the option is found, but
78    left unchanged if the option is not found.
79
80    To have a long-named option do something other than set an `int' to
81    a compiled-in constant, such as set a value from `GNoptarg', set the
82    option's `flag' field to zero and its `val' field to a nonzero
83    value (the equivalent single-letter option character, if there is
84    one).  For long options that have a zero `flag' field, `getopt'
85    returns the contents of the `val' field.  */
86
87 struct GNoption {
88   const char *name;
89   /* has_arg can't be an enum because some compilers complain about
90    * type mismatches in all the code that assumes it is an int.  */
91   int has_arg;
92   int *flag;
93   int val;
94 };
95
96
97 /* This version of `getopt' appears to the caller like standard Unix `getopt'
98    but it behaves differently for the user, since it allows the user
99    to intersperse the options with the other arguments.
100
101    As `getopt' works, it permutes the elements of ARGV so that,
102    when it is done, all the options precede everything else.  Thus
103    all application programs are extended to handle flexible argument order.
104
105    Setting the environment variable POSIXLY_CORRECT disables permutation.
106    Then the behavior is completely standard.
107
108    GNU application programs can use a third alternative mode in which
109    they can distinguish the relative order of options and other arguments.  */
110
111 /* For communication from `getopt' to the caller.
112    When `getopt' finds an option that takes an argument,
113    the argument value is returned here.
114    Also, when `ordering' is RETURN_IN_ORDER,
115    each non-option ARGV-element is returned here.  */
116
117 static char *GNoptarg = NULL;
118
119 /* Index in ARGV of the next element to be scanned.
120    This is used for communication to and from the caller
121    and for communication between successive calls to `getopt'.
122
123    On entry to `getopt', zero means this is the first call; initialize.
124
125    When `getopt' returns -1, this is the index of the first of the
126    non-option elements that the caller should itself scan.
127
128    Otherwise, `GNoptind' communicates from one call to the next
129    how much of ARGV has been scanned so far.  */
130
131 /* 1003.2 says this must be 1 before any call.  */
132 static int GNoptind = 1;
133
134 /* The next char to be scanned in the option-element
135    in which the last option character we returned was found.
136    This allows us to pick up the scan where we left off.
137
138    If this is zero, or a null string, it means resume the scan
139    by advancing to the next ARGV-element.  */
140
141 static char *nextchar;
142
143
144 /* Describe how to deal with options that follow non-option ARGV-elements.
145
146    If the caller did not specify anything,
147    the default is REQUIRE_ORDER if the environment variable
148    POSIXLY_CORRECT is defined, PERMUTE otherwise.
149
150    REQUIRE_ORDER means don't recognize them as options;
151    stop option processing when the first non-option is seen.
152    This is what Unix does.
153    This mode of operation is selected by either setting the environment
154    variable POSIXLY_CORRECT, or using `+' as the first character
155    of the list of option characters.
156
157    PERMUTE is the default.  We GNUNET_CRYPTO_random_permute the contents of ARGV as we scan,
158    so that eventually all the non-options are at the end.  This allows options
159    to be given in any order, even with programs that were not written to
160    expect this.
161
162    RETURN_IN_ORDER is an option available to programs that were written
163    to expect GNoptions and other ARGV-elements in any order and that care about
164    the ordering of the two.  We describe each non-option ARGV-element
165    as if it were the argument of an option with character code 1.
166    Using `-' as the first character of the list of option characters
167    selects this mode of operation.
168
169    The special argument `--' forces an end of option-scanning regardless
170    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
171    `--' can cause `getopt' to return -1 with `GNoptind' != ARGC.  */
172
173 static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering;
174
175 /* Value of POSIXLY_CORRECT environment variable.  */
176 static char *posixly_correct;
177
178 #ifdef __GNU_LIBRARY__
179 /* We want to avoid inclusion of string.h with non-GNU libraries
180    because there are many ways it can cause trouble.
181    On some systems, it contains special magic macros that don't work
182    in GCC.  */
183 #include <string.h>
184 #define my_index strchr
185 #else
186
187 /* Avoid depending on library functions or files
188    whose names are inconsistent.  */
189
190 char *
191 getenv();
192
193 static char *
194 my_index(const char *str, int chr)
195 {
196   while (*str)
197     {
198       if (*str == chr)
199         return (char *)str;
200       str++;
201     }
202   return 0;
203 }
204
205 /* If using GCC, we can safely declare strlen this way.
206    If not using GCC, it is ok not to declare it.  */
207 #ifdef __GNUC__
208 /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
209    That was relevant to code that was here before.  */
210 #if !defined(__STDC__) || !__STDC__
211 /* gcc with -traditional declares the built-in strlen to return int,
212    and has done so at least since version 2.4.5. -- rms.  */
213 extern int
214 strlen(const char *);
215 #endif /* not __STDC__ */
216 #endif /* __GNUC__ */
217
218 #endif /* not __GNU_LIBRARY__ */
219
220 /* Handle permutation of arguments.  */
221
222 /* Describe the part of ARGV that contains non-options that have
223    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
224    `last_nonopt' is the index after the last of them.  */
225
226 static int first_nonopt;
227 static int last_nonopt;
228
229 #define SWAP_FLAGS(ch1, ch2)
230
231 /* Exchange two adjacent subsequences of ARGV.
232    One subsequence is elements [first_nonopt,last_nonopt)
233    which contains all the non-options that have been skipped so far.
234    The other is elements [last_nonopt,GNoptind), which contains all
235    the options processed since those non-options were skipped.
236
237    `first_nonopt' and `last_nonopt' are relocated so that they describe
238    the new indices of the non-options in ARGV after they are moved.  */
239
240 #if defined(__STDC__) && __STDC__
241 static void
242 exchange(char **);
243 #endif
244
245 static void
246 exchange(char **argv)
247 {
248   int bottom = first_nonopt;
249   int middle = last_nonopt;
250   int top = GNoptind;
251   char *tem;
252
253   /* Exchange the shorter segment with the far end of the longer segment.
254    * That puts the shorter segment into the right place.
255    * It leaves the longer segment in the right place overall,
256    * but it consists of two parts that need to be swapped next.  */
257
258   while (top > middle && middle > bottom)
259     {
260       if (top - middle > middle - bottom)
261         {
262           /* Bottom segment is the short one.  */
263           int len = middle - bottom;
264           register int i;
265
266           /* Swap it with the top part of the top segment.  */
267           for (i = 0; i < len; i++)
268             {
269               tem = argv[bottom + i];
270               argv[bottom + i] = argv[top - (middle - bottom) + i];
271               argv[top - (middle - bottom) + i] = tem;
272               SWAP_FLAGS(bottom + i, top - (middle - bottom) + i);
273             }
274           /* Exclude the moved bottom segment from further swapping.  */
275           top -= len;
276         }
277       else
278         {
279           /* Top segment is the short one.  */
280           int len = top - middle;
281           register int i;
282
283           /* Swap it with the bottom part of the bottom segment.  */
284           for (i = 0; i < len; i++)
285             {
286               tem = argv[bottom + i];
287               argv[bottom + i] = argv[middle + i];
288               argv[middle + i] = tem;
289               SWAP_FLAGS(bottom + i, middle + i);
290             }
291           /* Exclude the moved top segment from further swapping.  */
292           bottom += len;
293         }
294     }
295
296   /* Update records for the slots the non-options now occupy.  */
297
298   first_nonopt += (GNoptind - last_nonopt);
299   last_nonopt = GNoptind;
300 }
301
302 /* Initialize the internal data when the first call is made.  */
303
304 #if defined(__STDC__) && __STDC__
305 static const char *
306 _getopt_initialize(int, char *const *, const char *);
307 #endif
308 static const char *
309 _getopt_initialize(int argc, char *const *argv, const char *optstring)
310 {
311   /* Start processing options with ARGV-element 1 (since ARGV-element 0
312    * is the program name); the sequence of previously skipped
313    * non-option ARGV-elements is empty.  */
314
315   first_nonopt = last_nonopt = GNoptind;
316
317   nextchar = NULL;
318
319   posixly_correct = getenv("POSIXLY_CORRECT");
320
321   /* Determine how to handle the ordering of options and nonoptions.  */
322
323   if (optstring[0] == '-')
324     {
325       ordering = RETURN_IN_ORDER;
326       ++optstring;
327     }
328   else if (optstring[0] == '+')
329     {
330       ordering = REQUIRE_ORDER;
331       ++optstring;
332     }
333   else if (posixly_correct != NULL)
334     ordering = REQUIRE_ORDER;
335   else
336     ordering = PERMUTE;
337
338   return optstring;
339 }
340
341 /* Scan elements of ARGV (whose length is ARGC) for option characters
342    given in OPTSTRING.
343
344    If an element of ARGV starts with '-', and is not exactly "-" or "--",
345    then it is an option element.  The characters of this element
346    (aside from the initial '-') are option characters.  If `getopt'
347    is called repeatedly, it returns successively each of the option characters
348    from each of the option elements.
349
350    If `getopt' finds another option character, it returns that character,
351    updating `GNoptind' and `nextchar' so that the next call to `getopt' can
352    resume the scan with the following option character or ARGV-element.
353
354    If there are no more option characters, `getopt' returns -1.
355    Then `GNoptind' is the index in ARGV of the first ARGV-element
356    that is not an option.  (The ARGV-elements have been permuted
357    so that those that are not options now come last.)
358
359    OPTSTRING is a string containing the legitimate option characters.
360    If an option character is seen that is not listed in OPTSTRING,
361    return '?' after printing an error message.  If you set `GNopterr' to
362    zero, the error message is suppressed but we still return '?'.
363
364    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
365    so the following text in the same ARGV-element, or the text of the following
366    ARGV-element, is returned in `GNoptarg'.  Two colons mean an option that
367    wants an optional arg; if there is text in the current ARGV-element,
368    it is returned in `GNoptarg', otherwise `GNoptarg' is set to zero.
369
370    If OPTSTRING starts with `-' or `+', it requests different methods of
371    handling the non-option ARGV-elements.
372    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
373
374    Long-named options begin with `--' instead of `-'.
375    Their names may be abbreviated as long as the abbreviation is unique
376    or is an exact match for some defined option.  If they have an
377    argument, it follows the option name in the same ARGV-element, separated
378    from the option name by a `=', or else the in next ARGV-element.
379    When `getopt' finds a long-named option, it returns 0 if that option's
380    `flag' field is nonzero, the value of the option's `val' field
381    if the `flag' field is zero.
382
383    The elements of ARGV aren't really const, because we GNUNET_CRYPTO_random_permute them.
384    But we pretend they're const in the prototype to be compatible
385    with other systems.
386
387    LONGOPTS is a vector of `struct GNoption' terminated by an
388    element containing a name which is zero.
389
390    LONGIND returns the index in LONGOPT of the long-named option found.
391    It is only valid when a long-named option has been found by the most
392    recent call.
393
394    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
395    long-named options.  */
396
397 static int
398 GN_getopt_internal(int argc,
399                    char *const *argv,
400                    const char *optstring,
401                    const struct GNoption *longopts,
402                    int *longind,
403                    int long_only)
404 {
405   static int __getopt_initialized = 0;
406   static int GNopterr = 1;
407
408   GNoptarg = NULL;
409
410   if (GNoptind == 0 || !__getopt_initialized)
411     {
412       if (GNoptind == 0)
413         GNoptind = 1; /* Don't scan ARGV[0], the program name.  */
414       optstring = _getopt_initialize(argc, argv, optstring);
415       __getopt_initialized = 1;
416     }
417
418   /* Test whether ARGV[GNoptind] points to a non-option argument.
419    * Either it does not have option syntax, or there is an environment flag
420    * from the shell indicating it is not an option.  The later information
421    * is only used when the used in the GNU libc.  */
422 #define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')
423
424   if (nextchar == NULL || *nextchar == '\0')
425     {
426       /* Advance to the next ARGV-element.  */
427
428       /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been
429       * moved back by the user (who may also have changed the arguments).  */
430       if (last_nonopt > GNoptind)
431         last_nonopt = GNoptind;
432       if (first_nonopt > GNoptind)
433         first_nonopt = GNoptind;
434
435       if (ordering == PERMUTE)
436         {
437           /* If we have just processed some options following some non-options,
438            * exchange them so that the options come first.  */
439
440           if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
441             exchange((char **)argv);
442           else if (last_nonopt != GNoptind)
443             first_nonopt = GNoptind;
444
445           /* Skip any additional non-options
446            * and extend the range of non-options previously skipped.  */
447
448           while (GNoptind < argc && NONOPTION_P)
449             GNoptind++;
450           last_nonopt = GNoptind;
451         }
452
453       /* The special ARGV-element `--' means premature end of options.
454        * Skip it like a null option,
455        * then exchange with previous non-options as if it were an option,
456        * then skip everything else like a non-option.  */
457       if (GNoptind != argc && !strcmp(argv[GNoptind], "--"))
458         {
459           GNoptind++;
460
461           if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
462             exchange((char **)argv);
463           else if (first_nonopt == last_nonopt)
464             first_nonopt = GNoptind;
465           last_nonopt = argc;
466
467           GNoptind = argc;
468         }
469
470       /* If we have done all the ARGV-elements, stop the scan
471        * and back over any non-options that we skipped and permuted.  */
472
473       if (GNoptind == argc)
474         {
475           /* Set the next-arg-index to point at the non-options
476            * that we previously skipped, so the caller will digest them.  */
477           if (first_nonopt != last_nonopt)
478             GNoptind = first_nonopt;
479           return -1;
480         }
481
482       /* If we have come to a non-option and did not permute it,
483        * either stop the scan or describe it to the caller and pass it by.  */
484
485       if (NONOPTION_P)
486         {
487           if (ordering == REQUIRE_ORDER)
488             return -1;
489           GNoptarg = argv[GNoptind++];
490           return 1;
491         }
492
493       /* We have found another option-ARGV-element.
494        * Skip the initial punctuation.  */
495
496       nextchar =
497         (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-'));
498     }
499
500   /* Decode the current option-ARGV-element.  */
501
502   /* Check whether the ARGV-element is a long option.
503    *
504    * If long_only and the ARGV-element has the form "-f", where f is
505    * a valid short option, don't consider it an abbreviated form of
506    * a long option that starts with f.  Otherwise there would be no
507    * way to give the -f short option.
508    *
509    * On the other hand, if there's a long option "fubar" and
510    * the ARGV-element is "-fu", do consider that an abbreviation of
511    * the long option, just like "--fu", and not "-f" with arg "u".
512    *
513    * This distinction seems to be the most useful approach.  */
514
515   if (longopts != NULL &&
516       (argv[GNoptind][1] == '-' ||
517        (long_only &&
518         (argv[GNoptind][2] || !my_index(optstring, argv[GNoptind][1])))))
519     {
520       char *nameend;
521       const struct GNoption *p;
522       const struct GNoption *pfound = NULL;
523       int exact = 0;
524       int ambig = 0;
525       int indfound = -1;
526       int option_index;
527
528       for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
529         /* Do nothing.  */;
530
531       /* Test all long options for either exact match
532        * or abbreviated matches.  */
533       for (p = longopts, option_index = 0; p->name; p++, option_index++)
534         if (!strncmp(p->name, nextchar, nameend - nextchar))
535           {
536             if ((unsigned int)(nameend - nextchar) ==
537                 (unsigned int)strlen(p->name))
538               {
539                 /* Exact match found.  */
540                 pfound = p;
541                 indfound = option_index;
542                 exact = 1;
543                 break;
544               }
545             else if (pfound == NULL)
546               {
547                 /* First nonexact match found.  */
548                 pfound = p;
549                 indfound = option_index;
550               }
551             else
552               /* Second or later nonexact match found.  */
553               ambig = 1;
554           }
555
556       if (ambig && !exact)
557         {
558           if (GNopterr)
559             fprintf(stderr,
560                     _("%s: option `%s' is ambiguous\n"),
561                     argv[0],
562                     argv[GNoptind]);
563           nextchar += strlen(nextchar);
564           GNoptind++;
565           return '?';
566         }
567
568       if (pfound != NULL)
569         {
570           option_index = indfound;
571           GNoptind++;
572           if (*nameend)
573             {
574               /* Don't test has_arg with >, because some C compilers don't
575                * allow it to be used on enums.  */
576               if (pfound->has_arg)
577                 GNoptarg = nameend + 1;
578               else
579                 {
580                   if (GNopterr)
581                     {
582                       if (argv[GNoptind - 1][1] == '-')
583                         /* --option */
584                         fprintf(stderr,
585                                 _("%s: option `--%s' does not allow an argument\n"),
586                                 argv[0],
587                                 pfound->name);
588                       else
589                         /* +option or -option */
590                         fprintf(stderr,
591                                 _("%s: option `%c%s' does not allow an argument\n"),
592                                 argv[0],
593                                 argv[GNoptind - 1][0],
594                                 pfound->name);
595                     }
596                   nextchar += strlen(nextchar);
597                   return '?';
598                 }
599             }
600           else if (pfound->has_arg == 1)
601             {
602               if (GNoptind < argc)
603                 {
604                   GNoptarg = argv[GNoptind++];
605                 }
606               else
607                 {
608                   if (GNopterr)
609                     {
610                       fprintf(stderr,
611                               _("%s: option `%s' requires an argument\n"),
612                               argv[0],
613                               argv[GNoptind - 1]);
614                     }
615                   nextchar += strlen(nextchar);
616                   return (optstring[0] == ':') ? ':' : '?';
617                 }
618             }
619           nextchar += strlen(nextchar);
620           if (longind != NULL)
621             *longind = option_index;
622           if (pfound->flag)
623             {
624               *(pfound->flag) = pfound->val;
625               return 0;
626             }
627           return pfound->val;
628         }
629
630       /* Can't find it as a long option.  If this is not getopt_long_only,
631        * or the option starts with '--' or is not a valid short
632        * option, then it's an error.
633        * Otherwise interpret it as a short option.  */
634       if (!long_only || argv[GNoptind][1] == '-' ||
635           my_index(optstring, *nextchar) == NULL)
636         {
637           if (GNopterr)
638             {
639               if (argv[GNoptind][1] == '-')
640                 /* --option */
641                 fprintf(stderr,
642                         _("%s: unrecognized option `--%s'\n"),
643                         argv[0],
644                         nextchar);
645               else
646                 /* +option or -option */
647                 fprintf(stderr,
648                         _("%s: unrecognized option `%c%s'\n"),
649                         argv[0],
650                         argv[GNoptind][0],
651                         nextchar);
652             }
653           nextchar = (char *)"";
654           GNoptind++;
655           return '?';
656         }
657     }
658
659   /* Look at and handle the next short option-character.  */
660
661   {
662     char c = *nextchar++;
663     char *temp = my_index(optstring, c);
664
665     /* Increment `GNoptind' when we start to process its last character.  */
666     if (*nextchar == '\0')
667       ++GNoptind;
668
669     if (temp == NULL || c == ':')
670       {
671         if (GNopterr)
672           {
673             if (posixly_correct)
674               /* 1003.2 specifies the format of this message.  */
675               fprintf(stderr, _("%s: illegal option -- %c\n"), argv[0], c);
676             else
677               fprintf(stderr, _("%s: invalid option -- %c\n"), argv[0], c);
678           }
679         return '?';
680       }
681     /* Convenience. Treat POSIX -W foo same as long option --foo */
682     if (temp[0] == 'W' && temp[1] == ';')
683       {
684         char *nameend;
685         const struct GNoption *p;
686         const struct GNoption *pfound = NULL;
687         int exact = 0;
688         int ambig = 0;
689         int indfound = 0;
690         int option_index;
691
692         /* This is an option that requires an argument.  */
693         if (*nextchar != '\0')
694           {
695             GNoptarg = nextchar;
696             /* If we end this ARGV-element by taking the rest as an arg,
697              * we must advance to the next element now.  */
698             GNoptind++;
699           }
700         else if (GNoptind == argc)
701           {
702             if (GNopterr)
703               {
704                 /* 1003.2 specifies the format of this message.  */
705                 fprintf(stderr,
706                         _("%s: option requires an argument -- %c\n"),
707                         argv[0],
708                         c);
709               }
710             if (optstring[0] == ':')
711               c = ':';
712             else
713               c = '?';
714             return c;
715           }
716         else
717           /* We already incremented `GNoptind' once;
718            * increment it again when taking next ARGV-elt as argument.  */
719           GNoptarg = argv[GNoptind++];
720
721         /* GNoptarg is now the argument, see if it's in the
722          * table of longopts.  */
723
724         for (nextchar = nameend = GNoptarg; *nameend && *nameend != '=';
725              nameend++)
726           /* Do nothing.  */;
727
728         /* Test all long options for either exact match
729          * or abbreviated matches.  */
730         if (longopts != NULL)
731           for (p = longopts, option_index = 0; p->name; p++, option_index++)
732             if (!strncmp(p->name, nextchar, nameend - nextchar))
733               {
734                 if ((unsigned int)(nameend - nextchar) == strlen(p->name))
735                   {
736                     /* Exact match found.  */
737                     pfound = p;
738                     indfound = option_index;
739                     exact = 1;
740                     break;
741                   }
742                 else if (pfound == NULL)
743                   {
744                     /* First nonexact match found.  */
745                     pfound = p;
746                     indfound = option_index;
747                   }
748                 else
749                   /* Second or later nonexact match found.  */
750                   ambig = 1;
751               }
752         if (ambig && !exact)
753           {
754             if (GNopterr)
755               fprintf(stderr,
756                       _("%s: option `-W %s' is ambiguous\n"),
757                       argv[0],
758                       argv[GNoptind]);
759             nextchar += strlen(nextchar);
760             GNoptind++;
761             return '?';
762           }
763         if (pfound != NULL)
764           {
765             option_index = indfound;
766             if (*nameend)
767               {
768                 /* Don't test has_arg with >, because some C compilers don't
769                  * allow it to be used on enums.  */
770                 if (pfound->has_arg)
771                   GNoptarg = nameend + 1;
772                 else
773                   {
774                     if (GNopterr)
775                       fprintf(stderr,
776                               _("%s: option `-W %s' does not allow an argument\n"),
777                               argv[0],
778                               pfound->name);
779
780                     nextchar += strlen(nextchar);
781                     return '?';
782                   }
783               }
784             else if (pfound->has_arg == 1)
785               {
786                 if (GNoptind < argc)
787                   GNoptarg = argv[GNoptind++];
788                 else
789                   {
790                     if (GNopterr)
791                       fprintf(stderr,
792                               _("%s: option `%s' requires an argument\n"),
793                               argv[0],
794                               argv[GNoptind - 1]);
795                     nextchar += strlen(nextchar);
796                     return optstring[0] == ':' ? ':' : '?';
797                   }
798               }
799             nextchar += strlen(nextchar);
800             if (longind != NULL)
801               *longind = option_index;
802             if (pfound->flag)
803               {
804                 *(pfound->flag) = pfound->val;
805                 return 0;
806               }
807             return pfound->val;
808           }
809         nextchar = NULL;
810         return 'W'; /* Let the application handle it.   */
811       }
812     if (temp[1] == ':')
813       {
814         if (temp[2] == ':')
815           {
816             /* This is an option that accepts an argument optionally.  */
817             if (*nextchar != '\0')
818               {
819                 GNoptarg = nextchar;
820                 GNoptind++;
821               }
822             else
823               GNoptarg = NULL;
824             nextchar = NULL;
825           }
826         else
827           {
828             /* This is an option that requires an argument.  */
829             if (*nextchar != '\0')
830               {
831                 GNoptarg = nextchar;
832                 /* If we end this ARGV-element by taking the rest as an arg,
833                  * we must advance to the next element now.  */
834                 GNoptind++;
835               }
836             else if (GNoptind == argc)
837               {
838                 if (GNopterr)
839                   {
840                     /* 1003.2 specifies the format of this message.  */
841                     fprintf(stderr,
842                             _("%s: option requires an argument -- %c\n"),
843                             argv[0],
844                             c);
845                   }
846                 if (optstring[0] == ':')
847                   c = ':';
848                 else
849                   c = '?';
850               }
851             else
852               /* We already incremented `GNoptind' once;
853                * increment it again when taking next ARGV-elt as argument.  */
854               GNoptarg = argv[GNoptind++];
855             nextchar = NULL;
856           }
857       }
858     return c;
859   }
860 }
861
862
863 static int
864 GNgetopt_long(int argc,
865               char *const *argv,
866               const char *options,
867               const struct GNoption *long_options,
868               int *opt_index)
869 {
870   return GN_getopt_internal(argc, argv, options, long_options, opt_index, 0);
871 }
872
873 /* ******************** now the GNUnet specific modifications... ********************* */
874
875 /**
876  * Parse the command line.
877  *
878  * @param binaryOptions Name of application with option summary
879  * @param allOptions defined options and handlers
880  * @param argc number of arguments
881  * @param argv actual arguments
882  * @return index into argv with first non-option
883  *   argument, or #GNUNET_SYSERR on error
884  */
885 int
886 GNUNET_GETOPT_run(const char *binaryOptions,
887                   const struct GNUNET_GETOPT_CommandLineOption *allOptions,
888                   unsigned int argc,
889                   char *const *argv)
890 {
891   struct GNoption *long_options;
892   struct GNUNET_GETOPT_CommandLineProcessorContext clpc;
893   int count;
894   char *shorts;
895   int spos;
896   int cont;
897   uint8_t *seen;
898   unsigned int optmatch = 0;
899   const char *have_exclusive = NULL;
900
901   GNUNET_assert(argc > 0);
902   GNoptind = 0;
903   clpc.binaryName = argv[0];
904   clpc.binaryOptions = binaryOptions;
905   clpc.allOptions = allOptions;
906   clpc.argv = argv;
907   clpc.argc = argc;
908   for (count = 0; NULL != allOptions[count].name; count++)
909     ;
910
911   /* transform our option representation into the format
912      used by the GNU getopt copylib */
913   long_options = GNUNET_new_array(count + 1, struct GNoption);
914   seen = GNUNET_new_array(count, uint8_t);
915   shorts = GNUNET_malloc(count * 2 + 1);
916   spos = 0;
917   for (unsigned i = 0; i < count; i++)
918     {
919       long_options[i].name = allOptions[i].name;
920       long_options[i].has_arg = allOptions[i].require_argument;
921       long_options[i].flag = NULL;
922       long_options[i].val = allOptions[i].shortName;
923       shorts[spos++] = allOptions[i].shortName;
924       if (allOptions[i].require_argument != 0)
925         shorts[spos++] = ':';
926     }
927   long_options[count].name = NULL;
928   long_options[count].has_arg = 0;
929   long_options[count].flag = NULL;
930   long_options[count].val = '\0';
931   shorts[spos] = '\0';
932   cont = GNUNET_OK;
933
934   /* main getopt loop */
935   while (1)
936     {
937       int option_index = 0;
938       unsigned int i;
939       int c;
940
941       c = GNgetopt_long(argc, argv, shorts, long_options, &option_index);
942       if (c == GNUNET_SYSERR)
943         break; /* No more flags to process */
944
945       /* Check which of our program's options was given by the user */
946       for (i = 0; i < count; i++)
947         {
948           clpc.currentArgument = GNoptind - 1;
949           if ((char)c == allOptions[i].shortName)
950             {
951               optmatch++;
952               if (allOptions[i].option_exclusive)
953                 have_exclusive = allOptions[i].name;
954               if (GNUNET_OK == cont)
955                 {
956                   /* parse the option using the option-specific processor */
957                   cont = allOptions[i].processor(&clpc,
958                                                  allOptions[i].scls,
959                                                  allOptions[i].name,
960                                                  GNoptarg);
961                 }
962               seen[i] = 1;
963               break;
964             }
965         }
966       if (i == count)
967         {
968           fprintf(stderr, _("Use %s to get a list of options.\n"), "--help");
969           cont = GNUNET_SYSERR;
970         }
971     }
972   GNUNET_free(shorts);
973   GNUNET_free(long_options);
974
975   /* check that if any option that was marked as exclusive
976      is the only option that was provided */
977   if ((NULL != have_exclusive) && (optmatch > 1))
978     {
979       fprintf(stderr,
980               _("Option `%s' can't be used with other options.\n"),
981               have_exclusive);
982       cont = GNUNET_SYSERR;
983     }
984   if (GNUNET_YES == cont)
985     {
986       /* check that all mandatory options are present */
987       for (count = 0; NULL != allOptions[count].name; count++)
988         {
989           if ((0 == seen[count]) && (allOptions[count].option_mandatory))
990             {
991               fprintf(stderr,
992                       _("Missing mandatory option `%s'.\n"),
993                       allOptions[count].name);
994               cont = GNUNET_SYSERR;
995             }
996         }
997     }
998   GNUNET_free(seen);
999
1000   /* call cleaners, if available */
1001   for (unsigned int i = 0; NULL != allOptions[i].name; i++)
1002     if (NULL != allOptions[i].cleaner)
1003       allOptions[i].cleaner(allOptions[i].scls);
1004
1005   if (GNUNET_OK != cont)
1006     return cont;
1007   return GNoptind;
1008 }
1009
1010 /* end of getopt.c */