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