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