aboutsummaryrefslogtreecommitdiff
path: root/src/util/getopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/getopt.c')
-rw-r--r--src/util/getopt.c1041
1 files changed, 520 insertions, 521 deletions
diff --git a/src/util/getopt.c b/src/util/getopt.c
index 678e2a61f..19b160cc9 100644
--- a/src/util/getopt.c
+++ b/src/util/getopt.c
@@ -6,28 +6,28 @@
6 Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 6 Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
7 Free Software Foundation, Inc. 7 Free Software Foundation, Inc.
8 8
9NOTE: The canonical source of this file is maintained with the GNU C Library. 9 NOTE: The canonical source of this file is maintained with the GNU C Library.
10Bugs can be reported to bug-glibc@prep.ai.mit.edu. 10 Bugs can be reported to bug-glibc@prep.ai.mit.edu.
11 11
12This program is free software; you can redistribute it and/or modify it 12 This 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 13 under the terms of the GNU General Public License as published by the
14Free Software Foundation; either version 3, or (at your option) any 14 Free Software Foundation; either version 3, or (at your option) any
15later version. 15 later version.
16 16
17This program is distributed in the hope that it will be useful, 17 This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of 18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU General Public License for more details. 20 GNU General Public License for more details.
21 21
22You should have received a copy of the GNU General Public License 22 You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software 23 along with this program; if not, write to the Free Software
24Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25USA. 25 USA.
26 26
27 27
28This code was heavily modified for GNUnet. 28 This code was heavily modified for GNUnet.
29Copyright (C) 2006, 2017 Christian Grothoff 29 Copyright (C) 2006, 2017 Christian Grothoff
30*/ 30 */
31 31
32/** 32/**
33 * @file util/getopt.c 33 * @file util/getopt.c
@@ -47,15 +47,15 @@ Copyright (C) 2006, 2017 Christian Grothoff
47#endif 47#endif
48#endif 48#endif
49 49
50#define LOG(kind, ...) GNUNET_log_from (kind, "util-getopt", __VA_ARGS__) 50#define LOG(kind, ...) GNUNET_log_from(kind, "util-getopt", __VA_ARGS__)
51 51
52#define LOG_STRERROR(kind, syscall) \ 52#define LOG_STRERROR(kind, syscall) \
53 GNUNET_log_from_strerror (kind, "util-getopt", syscall) 53 GNUNET_log_from_strerror(kind, "util-getopt", syscall)
54 54
55#if defined(WIN32) && ! defined(__CYGWIN32__) 55#if defined(WIN32) && !defined(__CYGWIN32__)
56/* It's not Unix, really. See? Capital letters. */ 56/* It's not Unix, really. See? Capital letters. */
57#include <windows.h> 57#include <windows.h>
58#define getpid() GetCurrentProcessId () 58#define getpid() GetCurrentProcessId()
59#endif 59#endif
60 60
61#ifndef _ 61#ifndef _
@@ -63,7 +63,7 @@ Copyright (C) 2006, 2017 Christian Grothoff
63 When compiling libc, the _ macro is predefined. */ 63 When compiling libc, the _ macro is predefined. */
64#ifdef HAVE_LIBINTL_H 64#ifdef HAVE_LIBINTL_H
65#include <libintl.h> 65#include <libintl.h>
66#define _(msgid) gettext (msgid) 66#define _(msgid) gettext(msgid)
67#else 67#else
68#define _(msgid) (msgid) 68#define _(msgid) (msgid)
69#endif 69#endif
@@ -75,7 +75,7 @@ Copyright (C) 2006, 2017 Christian Grothoff
75 zero. 75 zero.
76 76
77 The field `has_arg' is: 77 The field `has_arg' is:
78 no_argument (or 0) if the option does not take an argument, 78 no_argument (or 0) if the option does not take an argument,
79 required_argument (or 1) if the option requires an argument, 79 required_argument (or 1) if the option requires an argument,
80 optional_argument (or 2) if the option takes an optional argument. 80 optional_argument (or 2) if the option takes an optional argument.
81 81
@@ -90,8 +90,7 @@ Copyright (C) 2006, 2017 Christian Grothoff
90 one). For long options that have a zero `flag' field, `getopt' 90 one). For long options that have a zero `flag' field, `getopt'
91 returns the contents of the `val' field. */ 91 returns the contents of the `val' field. */
92 92
93struct GNoption 93struct GNoption {
94{
95 const char *name; 94 const char *name;
96 /* has_arg can't be an enum because some compilers complain about 95 /* has_arg can't be an enum because some compilers complain about
97 * type mismatches in all the code that assumes it is an int. */ 96 * type mismatches in all the code that assumes it is an int. */
@@ -195,17 +194,17 @@ static char *posixly_correct;
195 whose names are inconsistent. */ 194 whose names are inconsistent. */
196 195
197char * 196char *
198getenv (); 197getenv();
199 198
200static char * 199static char *
201my_index (const char *str, int chr) 200my_index(const char *str, int chr)
202{ 201{
203 while (*str) 202 while (*str)
204 { 203 {
205 if (*str == chr) 204 if (*str == chr)
206 return (char *) str; 205 return (char *)str;
207 str++; 206 str++;
208 } 207 }
209 return 0; 208 return 0;
210} 209}
211 210
@@ -214,11 +213,11 @@ my_index (const char *str, int chr)
214#ifdef __GNUC__ 213#ifdef __GNUC__
215/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. 214/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
216 That was relevant to code that was here before. */ 215 That was relevant to code that was here before. */
217#if ! defined(__STDC__) || ! __STDC__ 216#if !defined(__STDC__) || !__STDC__
218/* gcc with -traditional declares the built-in strlen to return int, 217/* gcc with -traditional declares the built-in strlen to return int,
219 and has done so at least since version 2.4.5. -- rms. */ 218 and has done so at least since version 2.4.5. -- rms. */
220extern int 219extern int
221strlen (const char *); 220strlen(const char *);
222#endif /* not __STDC__ */ 221#endif /* not __STDC__ */
223#endif /* __GNUC__ */ 222#endif /* __GNUC__ */
224 223
@@ -246,11 +245,11 @@ static int last_nonopt;
246 245
247#if defined(__STDC__) && __STDC__ 246#if defined(__STDC__) && __STDC__
248static void 247static void
249exchange (char **); 248exchange(char **);
250#endif 249#endif
251 250
252static void 251static void
253exchange (char **argv) 252exchange(char **argv)
254{ 253{
255 int bottom = first_nonopt; 254 int bottom = first_nonopt;
256 int middle = last_nonopt; 255 int middle = last_nonopt;
@@ -263,42 +262,42 @@ exchange (char **argv)
263 * but it consists of two parts that need to be swapped next. */ 262 * but it consists of two parts that need to be swapped next. */
264 263
265 while (top > middle && middle > bottom) 264 while (top > middle && middle > bottom)
266 {
267 if (top - middle > middle - bottom)
268 { 265 {
269 /* Bottom segment is the short one. */ 266 if (top - middle > middle - bottom)
270 int len = middle - bottom; 267 {
271 register int i; 268 /* Bottom segment is the short one. */
269 int len = middle - bottom;
270 register int i;
272 271
273 /* Swap it with the top part of the top segment. */ 272 /* Swap it with the top part of the top segment. */
274 for (i = 0; i < len; i++) 273 for (i = 0; i < len; i++)
275 { 274 {
276 tem = argv[bottom + i]; 275 tem = argv[bottom + i];
277 argv[bottom + i] = argv[top - (middle - bottom) + i]; 276 argv[bottom + i] = argv[top - (middle - bottom) + i];
278 argv[top - (middle - bottom) + i] = tem; 277 argv[top - (middle - bottom) + i] = tem;
279 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); 278 SWAP_FLAGS(bottom + i, top - (middle - bottom) + i);
280 } 279 }
281 /* Exclude the moved bottom segment from further swapping. */ 280 /* Exclude the moved bottom segment from further swapping. */
282 top -= len; 281 top -= len;
283 } 282 }
284 else 283 else
285 { 284 {
286 /* Top segment is the short one. */ 285 /* Top segment is the short one. */
287 int len = top - middle; 286 int len = top - middle;
288 register int i; 287 register int i;
289 288
290 /* Swap it with the bottom part of the bottom segment. */ 289 /* Swap it with the bottom part of the bottom segment. */
291 for (i = 0; i < len; i++) 290 for (i = 0; i < len; i++)
292 { 291 {
293 tem = argv[bottom + i]; 292 tem = argv[bottom + i];
294 argv[bottom + i] = argv[middle + i]; 293 argv[bottom + i] = argv[middle + i];
295 argv[middle + i] = tem; 294 argv[middle + i] = tem;
296 SWAP_FLAGS (bottom + i, middle + i); 295 SWAP_FLAGS(bottom + i, middle + i);
297 } 296 }
298 /* Exclude the moved top segment from further swapping. */ 297 /* Exclude the moved top segment from further swapping. */
299 bottom += len; 298 bottom += len;
299 }
300 } 300 }
301 }
302 301
303 /* Update records for the slots the non-options now occupy. */ 302 /* Update records for the slots the non-options now occupy. */
304 303
@@ -310,10 +309,10 @@ exchange (char **argv)
310 309
311#if defined(__STDC__) && __STDC__ 310#if defined(__STDC__) && __STDC__
312static const char * 311static const char *
313_getopt_initialize (int, char *const *, const char *); 312_getopt_initialize(int, char *const *, const char *);
314#endif 313#endif
315static const char * 314static const char *
316_getopt_initialize (int argc, char *const *argv, const char *optstring) 315_getopt_initialize(int argc, char *const *argv, const char *optstring)
317{ 316{
318 /* Start processing options with ARGV-element 1 (since ARGV-element 0 317 /* Start processing options with ARGV-element 1 (since ARGV-element 0
319 * is the program name); the sequence of previously skipped 318 * is the program name); the sequence of previously skipped
@@ -323,20 +322,20 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring)
323 322
324 nextchar = NULL; 323 nextchar = NULL;
325 324
326 posixly_correct = getenv ("POSIXLY_CORRECT"); 325 posixly_correct = getenv("POSIXLY_CORRECT");
327 326
328 /* Determine how to handle the ordering of options and nonoptions. */ 327 /* Determine how to handle the ordering of options and nonoptions. */
329 328
330 if (optstring[0] == '-') 329 if (optstring[0] == '-')
331 { 330 {
332 ordering = RETURN_IN_ORDER; 331 ordering = RETURN_IN_ORDER;
333 ++optstring; 332 ++optstring;
334 } 333 }
335 else if (optstring[0] == '+') 334 else if (optstring[0] == '+')
336 { 335 {
337 ordering = REQUIRE_ORDER; 336 ordering = REQUIRE_ORDER;
338 ++optstring; 337 ++optstring;
339 } 338 }
340 else if (posixly_correct != NULL) 339 else if (posixly_correct != NULL)
341 ordering = REQUIRE_ORDER; 340 ordering = REQUIRE_ORDER;
342 else 341 else
@@ -402,25 +401,25 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring)
402 long-named options. */ 401 long-named options. */
403 402
404static int 403static int
405GN_getopt_internal (int argc, 404GN_getopt_internal(int argc,
406 char *const *argv, 405 char *const *argv,
407 const char *optstring, 406 const char *optstring,
408 const struct GNoption *longopts, 407 const struct GNoption *longopts,
409 int *longind, 408 int *longind,
410 int long_only) 409 int long_only)
411{ 410{
412 static int __getopt_initialized = 0; 411 static int __getopt_initialized = 0;
413 static int GNopterr = 1; 412 static int GNopterr = 1;
414 413
415 GNoptarg = NULL; 414 GNoptarg = NULL;
416 415
417 if (GNoptind == 0 || ! __getopt_initialized) 416 if (GNoptind == 0 || !__getopt_initialized)
418 { 417 {
419 if (GNoptind == 0) 418 if (GNoptind == 0)
420 GNoptind = 1; /* Don't scan ARGV[0], the program name. */ 419 GNoptind = 1; /* Don't scan ARGV[0], the program name. */
421 optstring = _getopt_initialize (argc, argv, optstring); 420 optstring = _getopt_initialize(argc, argv, optstring);
422 __getopt_initialized = 1; 421 __getopt_initialized = 1;
423 } 422 }
424 423
425 /* Test whether ARGV[GNoptind] points to a non-option argument. 424 /* Test whether ARGV[GNoptind] points to a non-option argument.
426 * Either it does not have option syntax, or there is an environment flag 425 * Either it does not have option syntax, or there is an environment flag
@@ -429,80 +428,80 @@ GN_getopt_internal (int argc,
429#define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0') 428#define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')
430 429
431 if (nextchar == NULL || *nextchar == '\0') 430 if (nextchar == NULL || *nextchar == '\0')
432 {
433 /* Advance to the next ARGV-element. */
434
435 /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been
436 * moved back by the user (who may also have changed the arguments). */
437 if (last_nonopt > GNoptind)
438 last_nonopt = GNoptind;
439 if (first_nonopt > GNoptind)
440 first_nonopt = GNoptind;
441
442 if (ordering == PERMUTE)
443 { 431 {
444 /* If we have just processed some options following some non-options, 432 /* Advance to the next ARGV-element. */
445 * exchange them so that the options come first. */
446 433
447 if (first_nonopt != last_nonopt && last_nonopt != GNoptind) 434 /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been
448 exchange ((char **) argv); 435 * moved back by the user (who may also have changed the arguments). */
449 else if (last_nonopt != GNoptind) 436 if (last_nonopt > GNoptind)
437 last_nonopt = GNoptind;
438 if (first_nonopt > GNoptind)
450 first_nonopt = GNoptind; 439 first_nonopt = GNoptind;
451 440
452 /* Skip any additional non-options 441 if (ordering == PERMUTE)
453 * and extend the range of non-options previously skipped. */ 442 {
443 /* If we have just processed some options following some non-options,
444 * exchange them so that the options come first. */
454 445
455 while (GNoptind < argc && NONOPTION_P) 446 if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
456 GNoptind++; 447 exchange((char **)argv);
457 last_nonopt = GNoptind; 448 else if (last_nonopt != GNoptind)
458 } 449 first_nonopt = GNoptind;
459 450
460 /* The special ARGV-element `--' means premature end of options. 451 /* Skip any additional non-options
461 * Skip it like a null option, 452 * and extend the range of non-options previously skipped. */
462 * then exchange with previous non-options as if it were an option,
463 * then skip everything else like a non-option. */
464 if (GNoptind != argc && ! strcmp (argv[GNoptind], "--"))
465 {
466 GNoptind++;
467 453
468 if (first_nonopt != last_nonopt && last_nonopt != GNoptind) 454 while (GNoptind < argc && NONOPTION_P)
469 exchange ((char **) argv); 455 GNoptind++;
470 else if (first_nonopt == last_nonopt) 456 last_nonopt = GNoptind;
471 first_nonopt = GNoptind; 457 }
472 last_nonopt = argc;
473 458
474 GNoptind = argc; 459 /* The special ARGV-element `--' means premature end of options.
475 } 460 * Skip it like a null option,
461 * then exchange with previous non-options as if it were an option,
462 * then skip everything else like a non-option. */
463 if (GNoptind != argc && !strcmp(argv[GNoptind], "--"))
464 {
465 GNoptind++;
476 466
477 /* If we have done all the ARGV-elements, stop the scan 467 if (first_nonopt != last_nonopt && last_nonopt != GNoptind)
478 * and back over any non-options that we skipped and permuted. */ 468 exchange((char **)argv);
469 else if (first_nonopt == last_nonopt)
470 first_nonopt = GNoptind;
471 last_nonopt = argc;
479 472
480 if (GNoptind == argc) 473 GNoptind = argc;
481 { 474 }
482 /* Set the next-arg-index to point at the non-options
483 * that we previously skipped, so the caller will digest them. */
484 if (first_nonopt != last_nonopt)
485 GNoptind = first_nonopt;
486 return -1;
487 }
488 475
489 /* If we have come to a non-option and did not permute it, 476 /* If we have done all the ARGV-elements, stop the scan
490 * either stop the scan or describe it to the caller and pass it by. */ 477 * and back over any non-options that we skipped and permuted. */
491 478
492 if (NONOPTION_P) 479 if (GNoptind == argc)
493 { 480 {
494 if (ordering == REQUIRE_ORDER) 481 /* Set the next-arg-index to point at the non-options
495 return -1; 482 * that we previously skipped, so the caller will digest them. */
496 GNoptarg = argv[GNoptind++]; 483 if (first_nonopt != last_nonopt)
497 return 1; 484 GNoptind = first_nonopt;
498 } 485 return -1;
486 }
499 487
500 /* We have found another option-ARGV-element. 488 /* If we have come to a non-option and did not permute it,
501 * Skip the initial punctuation. */ 489 * either stop the scan or describe it to the caller and pass it by. */
502 490
503 nextchar = 491 if (NONOPTION_P)
504 (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-')); 492 {
505 } 493 if (ordering == REQUIRE_ORDER)
494 return -1;
495 GNoptarg = argv[GNoptind++];
496 return 1;
497 }
498
499 /* We have found another option-ARGV-element.
500 * Skip the initial punctuation. */
501
502 nextchar =
503 (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-'));
504 }
506 505
507 /* Decode the current option-ARGV-element. */ 506 /* Decode the current option-ARGV-element. */
508 507
@@ -522,359 +521,359 @@ GN_getopt_internal (int argc,
522 if (longopts != NULL && 521 if (longopts != NULL &&
523 (argv[GNoptind][1] == '-' || 522 (argv[GNoptind][1] == '-' ||
524 (long_only && 523 (long_only &&
525 (argv[GNoptind][2] || ! my_index (optstring, argv[GNoptind][1]))))) 524 (argv[GNoptind][2] || !my_index(optstring, argv[GNoptind][1])))))
526 {
527 char *nameend;
528 const struct GNoption *p;
529 const struct GNoption *pfound = NULL;
530 int exact = 0;
531 int ambig = 0;
532 int indfound = -1;
533 int option_index;
534
535 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
536 /* Do nothing. */;
537
538 /* Test all long options for either exact match
539 * or abbreviated matches. */
540 for (p = longopts, option_index = 0; p->name; p++, option_index++)
541 if (! strncmp (p->name, nextchar, nameend - nextchar))
542 {
543 if ((unsigned int) (nameend - nextchar) ==
544 (unsigned int) strlen (p->name))
545 {
546 /* Exact match found. */
547 pfound = p;
548 indfound = option_index;
549 exact = 1;
550 break;
551 }
552 else if (pfound == NULL)
553 {
554 /* First nonexact match found. */
555 pfound = p;
556 indfound = option_index;
557 }
558 else
559 /* Second or later nonexact match found. */
560 ambig = 1;
561 }
562
563 if (ambig && ! exact)
564 { 525 {
565 if (GNopterr) 526 char *nameend;
566 fprintf (stderr, 527 const struct GNoption *p;
567 _ ("%s: option `%s' is ambiguous\n"), 528 const struct GNoption *pfound = NULL;
568 argv[0], 529 int exact = 0;
569 argv[GNoptind]); 530 int ambig = 0;
570 nextchar += strlen (nextchar); 531 int indfound = -1;
571 GNoptind++; 532 int option_index;
572 return '?';
573 }
574 533
575 if (pfound != NULL) 534 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
576 { 535 /* Do nothing. */;
577 option_index = indfound; 536
578 GNoptind++; 537 /* Test all long options for either exact match
579 if (*nameend) 538 * or abbreviated matches. */
580 { 539 for (p = longopts, option_index = 0; p->name; p++, option_index++)
581 /* Don't test has_arg with >, because some C compilers don't 540 if (!strncmp(p->name, nextchar, nameend - nextchar))
582 * allow it to be used on enums. */
583 if (pfound->has_arg)
584 GNoptarg = nameend + 1;
585 else
586 {
587 if (GNopterr)
588 { 541 {
589 if (argv[GNoptind - 1][1] == '-') 542 if ((unsigned int)(nameend - nextchar) ==
590 /* --option */ 543 (unsigned int)strlen(p->name))
591 fprintf (stderr, 544 {
592 _ ("%s: option `--%s' does not allow an argument\n"), 545 /* Exact match found. */
593 argv[0], 546 pfound = p;
594 pfound->name); 547 indfound = option_index;
548 exact = 1;
549 break;
550 }
551 else if (pfound == NULL)
552 {
553 /* First nonexact match found. */
554 pfound = p;
555 indfound = option_index;
556 }
595 else 557 else
596 /* +option or -option */ 558 /* Second or later nonexact match found. */
597 fprintf (stderr, 559 ambig = 1;
598 _ ("%s: option `%c%s' does not allow an argument\n"),
599 argv[0],
600 argv[GNoptind - 1][0],
601 pfound->name);
602 } 560 }
603 nextchar += strlen (nextchar); 561
562 if (ambig && !exact)
563 {
564 if (GNopterr)
565 fprintf(stderr,
566 _("%s: option `%s' is ambiguous\n"),
567 argv[0],
568 argv[GNoptind]);
569 nextchar += strlen(nextchar);
570 GNoptind++;
604 return '?'; 571 return '?';
605 } 572 }
606 } 573
607 else if (pfound->has_arg == 1) 574 if (pfound != NULL)
608 {
609 if (GNoptind < argc)
610 { 575 {
611 GNoptarg = argv[GNoptind++]; 576 option_index = indfound;
577 GNoptind++;
578 if (*nameend)
579 {
580 /* Don't test has_arg with >, because some C compilers don't
581 * allow it to be used on enums. */
582 if (pfound->has_arg)
583 GNoptarg = nameend + 1;
584 else
585 {
586 if (GNopterr)
587 {
588 if (argv[GNoptind - 1][1] == '-')
589 /* --option */
590 fprintf(stderr,
591 _("%s: option `--%s' does not allow an argument\n"),
592 argv[0],
593 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],
599 argv[GNoptind - 1][0],
600 pfound->name);
601 }
602 nextchar += strlen(nextchar);
603 return '?';
604 }
605 }
606 else if (pfound->has_arg == 1)
607 {
608 if (GNoptind < argc)
609 {
610 GNoptarg = argv[GNoptind++];
611 }
612 else
613 {
614 if (GNopterr)
615 {
616 fprintf(stderr,
617 _("%s: option `%s' requires an argument\n"),
618 argv[0],
619 argv[GNoptind - 1]);
620 }
621 nextchar += strlen(nextchar);
622 return (optstring[0] == ':') ? ':' : '?';
623 }
624 }
625 nextchar += strlen(nextchar);
626 if (longind != NULL)
627 *longind = option_index;
628 if (pfound->flag)
629 {
630 *(pfound->flag) = pfound->val;
631 return 0;
632 }
633 return pfound->val;
612 } 634 }
613 else 635
636 /* Can't find it as a long option. If this is not getopt_long_only,
637 * or the option starts with '--' or is not a valid short
638 * option, then it's an error.
639 * Otherwise interpret it as a short option. */
640 if (!long_only || argv[GNoptind][1] == '-' ||
641 my_index(optstring, *nextchar) == NULL)
614 { 642 {
615 if (GNopterr) 643 if (GNopterr)
616 { 644 {
617 fprintf (stderr, 645 if (argv[GNoptind][1] == '-')
618 _ ("%s: option `%s' requires an argument\n"), 646 /* --option */
619 argv[0], 647 fprintf(stderr,
620 argv[GNoptind - 1]); 648 _("%s: unrecognized option `--%s'\n"),
621 } 649 argv[0],
622 nextchar += strlen (nextchar); 650 nextchar);
623 return (optstring[0] == ':') ? ':' : '?'; 651 else
652 /* +option or -option */
653 fprintf(stderr,
654 _("%s: unrecognized option `%c%s'\n"),
655 argv[0],
656 argv[GNoptind][0],
657 nextchar);
658 }
659 nextchar = (char *)"";
660 GNoptind++;
661 return '?';
624 } 662 }
625 }
626 nextchar += strlen (nextchar);
627 if (longind != NULL)
628 *longind = option_index;
629 if (pfound->flag)
630 {
631 *(pfound->flag) = pfound->val;
632 return 0;
633 }
634 return pfound->val;
635 } 663 }
636 664
637 /* Can't find it as a long option. If this is not getopt_long_only,
638 * or the option starts with '--' or is not a valid short
639 * option, then it's an error.
640 * Otherwise interpret it as a short option. */
641 if (! long_only || argv[GNoptind][1] == '-' ||
642 my_index (optstring, *nextchar) == NULL)
643 {
644 if (GNopterr)
645 {
646 if (argv[GNoptind][1] == '-')
647 /* --option */
648 fprintf (stderr,
649 _ ("%s: unrecognized option `--%s'\n"),
650 argv[0],
651 nextchar);
652 else
653 /* +option or -option */
654 fprintf (stderr,
655 _ ("%s: unrecognized option `%c%s'\n"),
656 argv[0],
657 argv[GNoptind][0],
658 nextchar);
659 }
660 nextchar = (char *) "";
661 GNoptind++;
662 return '?';
663 }
664 }
665
666 /* Look at and handle the next short option-character. */ 665 /* Look at and handle the next short option-character. */
667 666
668 { 667 {
669 char c = *nextchar++; 668 char c = *nextchar++;
670 char *temp = my_index (optstring, c); 669 char *temp = my_index(optstring, c);
671 670
672 /* Increment `GNoptind' when we start to process its last character. */ 671 /* Increment `GNoptind' when we start to process its last character. */
673 if (*nextchar == '\0') 672 if (*nextchar == '\0')
674 ++GNoptind; 673 ++GNoptind;
675 674
676 if (temp == NULL || c == ':') 675 if (temp == NULL || c == ':')
677 {
678 if (GNopterr)
679 {
680 if (posixly_correct)
681 /* 1003.2 specifies the format of this message. */
682 fprintf (stderr, _ ("%s: illegal option -- %c\n"), argv[0], c);
683 else
684 fprintf (stderr, _ ("%s: invalid option -- %c\n"), argv[0], c);
685 }
686 return '?';
687 }
688 /* Convenience. Treat POSIX -W foo same as long option --foo */
689 if (temp[0] == 'W' && temp[1] == ';')
690 {
691 char *nameend;
692 const struct GNoption *p;
693 const struct GNoption *pfound = NULL;
694 int exact = 0;
695 int ambig = 0;
696 int indfound = 0;
697 int option_index;
698
699 /* This is an option that requires an argument. */
700 if (*nextchar != '\0')
701 {
702 GNoptarg = nextchar;
703 /* If we end this ARGV-element by taking the rest as an arg,
704 * we must advance to the next element now. */
705 GNoptind++;
706 }
707 else if (GNoptind == argc)
708 { 676 {
709 if (GNopterr) 677 if (GNopterr)
710 {
711 /* 1003.2 specifies the format of this message. */
712 fprintf (stderr,
713 _ ("%s: option requires an argument -- %c\n"),
714 argv[0],
715 c);
716 }
717 if (optstring[0] == ':')
718 c = ':';
719 else
720 c = '?';
721 return c;
722 }
723 else
724 /* We already incremented `GNoptind' once;
725 * increment it again when taking next ARGV-elt as argument. */
726 GNoptarg = argv[GNoptind++];
727
728 /* GNoptarg is now the argument, see if it's in the
729 * table of longopts. */
730
731 for (nextchar = nameend = GNoptarg; *nameend && *nameend != '=';
732 nameend++)
733 /* Do nothing. */;
734
735 /* Test all long options for either exact match
736 * or abbreviated matches. */
737 if (longopts != NULL)
738 for (p = longopts, option_index = 0; p->name; p++, option_index++)
739 if (! strncmp (p->name, nextchar, nameend - nextchar))
740 { 678 {
741 if ((unsigned int) (nameend - nextchar) == strlen (p->name)) 679 if (posixly_correct)
742 { 680 /* 1003.2 specifies the format of this message. */
743 /* Exact match found. */ 681 fprintf(stderr, _("%s: illegal option -- %c\n"), argv[0], c);
744 pfound = p;
745 indfound = option_index;
746 exact = 1;
747 break;
748 }
749 else if (pfound == NULL)
750 {
751 /* First nonexact match found. */
752 pfound = p;
753 indfound = option_index;
754 }
755 else 682 else
756 /* Second or later nonexact match found. */ 683 fprintf(stderr, _("%s: invalid option -- %c\n"), argv[0], c);
757 ambig = 1;
758 } 684 }
759 if (ambig && ! exact)
760 {
761 if (GNopterr)
762 fprintf (stderr,
763 _ ("%s: option `-W %s' is ambiguous\n"),
764 argv[0],
765 argv[GNoptind]);
766 nextchar += strlen (nextchar);
767 GNoptind++;
768 return '?'; 685 return '?';
769 } 686 }
770 if (pfound != NULL) 687 /* Convenience. Treat POSIX -W foo same as long option --foo */
688 if (temp[0] == 'W' && temp[1] == ';')
771 { 689 {
772 option_index = indfound; 690 char *nameend;
773 if (*nameend) 691 const struct GNoption *p;
774 { 692 const struct GNoption *pfound = NULL;
775 /* Don't test has_arg with >, because some C compilers don't 693 int exact = 0;
776 * allow it to be used on enums. */ 694 int ambig = 0;
777 if (pfound->has_arg) 695 int indfound = 0;
778 GNoptarg = nameend + 1; 696 int option_index;
779 else 697
698 /* This is an option that requires an argument. */
699 if (*nextchar != '\0')
700 {
701 GNoptarg = nextchar;
702 /* If we end this ARGV-element by taking the rest as an arg,
703 * we must advance to the next element now. */
704 GNoptind++;
705 }
706 else if (GNoptind == argc)
780 { 707 {
781 if (GNopterr) 708 if (GNopterr)
782 fprintf (stderr, 709 {
783 _ ("%s: option `-W %s' does not allow an argument\n"), 710 /* 1003.2 specifies the format of this message. */
784 argv[0], 711 fprintf(stderr,
785 pfound->name); 712 _("%s: option requires an argument -- %c\n"),
713 argv[0],
714 c);
715 }
716 if (optstring[0] == ':')
717 c = ':';
718 else
719 c = '?';
720 return c;
721 }
722 else
723 /* We already incremented `GNoptind' once;
724 * increment it again when taking next ARGV-elt as argument. */
725 GNoptarg = argv[GNoptind++];
786 726
787 nextchar += strlen (nextchar); 727 /* GNoptarg is now the argument, see if it's in the
728 * table of longopts. */
729
730 for (nextchar = nameend = GNoptarg; *nameend && *nameend != '=';
731 nameend++)
732 /* Do nothing. */;
733
734 /* Test all long options for either exact match
735 * or abbreviated matches. */
736 if (longopts != NULL)
737 for (p = longopts, option_index = 0; p->name; p++, option_index++)
738 if (!strncmp(p->name, nextchar, nameend - nextchar))
739 {
740 if ((unsigned int)(nameend - nextchar) == strlen(p->name))
741 {
742 /* Exact match found. */
743 pfound = p;
744 indfound = option_index;
745 exact = 1;
746 break;
747 }
748 else if (pfound == NULL)
749 {
750 /* First nonexact match found. */
751 pfound = p;
752 indfound = option_index;
753 }
754 else
755 /* Second or later nonexact match found. */
756 ambig = 1;
757 }
758 if (ambig && !exact)
759 {
760 if (GNopterr)
761 fprintf(stderr,
762 _("%s: option `-W %s' is ambiguous\n"),
763 argv[0],
764 argv[GNoptind]);
765 nextchar += strlen(nextchar);
766 GNoptind++;
788 return '?'; 767 return '?';
789 } 768 }
790 } 769 if (pfound != NULL)
791 else if (pfound->has_arg == 1)
792 {
793 if (GNoptind < argc)
794 GNoptarg = argv[GNoptind++];
795 else
796 { 770 {
797 if (GNopterr) 771 option_index = indfound;
798 fprintf (stderr, 772 if (*nameend)
799 _ ("%s: option `%s' requires an argument\n"), 773 {
800 argv[0], 774 /* Don't test has_arg with >, because some C compilers don't
801 argv[GNoptind - 1]); 775 * allow it to be used on enums. */
802 nextchar += strlen (nextchar); 776 if (pfound->has_arg)
803 return optstring[0] == ':' ? ':' : '?'; 777 GNoptarg = nameend + 1;
778 else
779 {
780 if (GNopterr)
781 fprintf(stderr,
782 _("%s: option `-W %s' does not allow an argument\n"),
783 argv[0],
784 pfound->name);
785
786 nextchar += strlen(nextchar);
787 return '?';
788 }
789 }
790 else if (pfound->has_arg == 1)
791 {
792 if (GNoptind < argc)
793 GNoptarg = argv[GNoptind++];
794 else
795 {
796 if (GNopterr)
797 fprintf(stderr,
798 _("%s: option `%s' requires an argument\n"),
799 argv[0],
800 argv[GNoptind - 1]);
801 nextchar += strlen(nextchar);
802 return optstring[0] == ':' ? ':' : '?';
803 }
804 }
805 nextchar += strlen(nextchar);
806 if (longind != NULL)
807 *longind = option_index;
808 if (pfound->flag)
809 {
810 *(pfound->flag) = pfound->val;
811 return 0;
812 }
813 return pfound->val;
804 } 814 }
805 }
806 nextchar += strlen (nextchar);
807 if (longind != NULL)
808 *longind = option_index;
809 if (pfound->flag)
810 {
811 *(pfound->flag) = pfound->val;
812 return 0;
813 }
814 return pfound->val;
815 }
816 nextchar = NULL;
817 return 'W'; /* Let the application handle it. */
818 }
819 if (temp[1] == ':')
820 {
821 if (temp[2] == ':')
822 {
823 /* This is an option that accepts an argument optionally. */
824 if (*nextchar != '\0')
825 {
826 GNoptarg = nextchar;
827 GNoptind++;
828 }
829 else
830 GNoptarg = NULL;
831 nextchar = NULL; 815 nextchar = NULL;
816 return 'W'; /* Let the application handle it. */
832 } 817 }
833 else 818 if (temp[1] == ':')
834 { 819 {
835 /* This is an option that requires an argument. */ 820 if (temp[2] == ':')
836 if (*nextchar != '\0')
837 {
838 GNoptarg = nextchar;
839 /* If we end this ARGV-element by taking the rest as an arg,
840 * we must advance to the next element now. */
841 GNoptind++;
842 }
843 else if (GNoptind == argc)
844 {
845 if (GNopterr)
846 { 821 {
847 /* 1003.2 specifies the format of this message. */ 822 /* This is an option that accepts an argument optionally. */
848 fprintf (stderr, 823 if (*nextchar != '\0')
849 _ ("%s: option requires an argument -- %c\n"), 824 {
850 argv[0], 825 GNoptarg = nextchar;
851 c); 826 GNoptind++;
827 }
828 else
829 GNoptarg = NULL;
830 nextchar = NULL;
852 } 831 }
853 if (optstring[0] == ':')
854 c = ':';
855 else
856 c = '?';
857 }
858 else 832 else
859 /* We already incremented `GNoptind' once; 833 {
860 * increment it again when taking next ARGV-elt as argument. */ 834 /* This is an option that requires an argument. */
861 GNoptarg = argv[GNoptind++]; 835 if (*nextchar != '\0')
862 nextchar = NULL; 836 {
837 GNoptarg = nextchar;
838 /* If we end this ARGV-element by taking the rest as an arg,
839 * we must advance to the next element now. */
840 GNoptind++;
841 }
842 else if (GNoptind == argc)
843 {
844 if (GNopterr)
845 {
846 /* 1003.2 specifies the format of this message. */
847 fprintf(stderr,
848 _("%s: option requires an argument -- %c\n"),
849 argv[0],
850 c);
851 }
852 if (optstring[0] == ':')
853 c = ':';
854 else
855 c = '?';
856 }
857 else
858 /* We already incremented `GNoptind' once;
859 * increment it again when taking next ARGV-elt as argument. */
860 GNoptarg = argv[GNoptind++];
861 nextchar = NULL;
862 }
863 } 863 }
864 }
865 return c; 864 return c;
866 } 865 }
867} 866}
868 867
869 868
870static int 869static int
871GNgetopt_long (int argc, 870GNgetopt_long(int argc,
872 char *const *argv, 871 char *const *argv,
873 const char *options, 872 const char *options,
874 const struct GNoption *long_options, 873 const struct GNoption *long_options,
875 int *opt_index) 874 int *opt_index)
876{ 875{
877 return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0); 876 return GN_getopt_internal(argc, argv, options, long_options, opt_index, 0);
878} 877}
879 878
880/* ******************** now the GNUnet specific modifications... ********************* */ 879/* ******************** now the GNUnet specific modifications... ********************* */
@@ -890,10 +889,10 @@ GNgetopt_long (int argc,
890 * argument, or #GNUNET_SYSERR on error 889 * argument, or #GNUNET_SYSERR on error
891 */ 890 */
892int 891int
893GNUNET_GETOPT_run (const char *binaryOptions, 892GNUNET_GETOPT_run(const char *binaryOptions,
894 const struct GNUNET_GETOPT_CommandLineOption *allOptions, 893 const struct GNUNET_GETOPT_CommandLineOption *allOptions,
895 unsigned int argc, 894 unsigned int argc,
896 char *const *argv) 895 char *const *argv)
897{ 896{
898 struct GNoption *long_options; 897 struct GNoption *long_options;
899 struct GNUNET_GETOPT_CommandLineProcessorContext clpc; 898 struct GNUNET_GETOPT_CommandLineProcessorContext clpc;
@@ -905,7 +904,7 @@ GNUNET_GETOPT_run (const char *binaryOptions,
905 unsigned int optmatch = 0; 904 unsigned int optmatch = 0;
906 const char *have_exclusive = NULL; 905 const char *have_exclusive = NULL;
907 906
908 GNUNET_assert (argc > 0); 907 GNUNET_assert(argc > 0);
909 GNoptind = 0; 908 GNoptind = 0;
910 clpc.binaryName = argv[0]; 909 clpc.binaryName = argv[0];
911 clpc.binaryOptions = binaryOptions; 910 clpc.binaryOptions = binaryOptions;
@@ -917,20 +916,20 @@ GNUNET_GETOPT_run (const char *binaryOptions,
917 916
918 /* transform our option representation into the format 917 /* transform our option representation into the format
919 used by the GNU getopt copylib */ 918 used by the GNU getopt copylib */
920 long_options = GNUNET_new_array (count + 1, struct GNoption); 919 long_options = GNUNET_new_array(count + 1, struct GNoption);
921 seen = GNUNET_new_array (count, uint8_t); 920 seen = GNUNET_new_array(count, uint8_t);
922 shorts = GNUNET_malloc (count * 2 + 1); 921 shorts = GNUNET_malloc(count * 2 + 1);
923 spos = 0; 922 spos = 0;
924 for (unsigned i = 0; i < count; i++) 923 for (unsigned i = 0; i < count; i++)
925 { 924 {
926 long_options[i].name = allOptions[i].name; 925 long_options[i].name = allOptions[i].name;
927 long_options[i].has_arg = allOptions[i].require_argument; 926 long_options[i].has_arg = allOptions[i].require_argument;
928 long_options[i].flag = NULL; 927 long_options[i].flag = NULL;
929 long_options[i].val = allOptions[i].shortName; 928 long_options[i].val = allOptions[i].shortName;
930 shorts[spos++] = allOptions[i].shortName; 929 shorts[spos++] = allOptions[i].shortName;
931 if (allOptions[i].require_argument != 0) 930 if (allOptions[i].require_argument != 0)
932 shorts[spos++] = ':'; 931 shorts[spos++] = ':';
933 } 932 }
934 long_options[count].name = NULL; 933 long_options[count].name = NULL;
935 long_options[count].has_arg = 0; 934 long_options[count].has_arg = 0;
936 long_options[count].flag = NULL; 935 long_options[count].flag = NULL;
@@ -940,74 +939,74 @@ GNUNET_GETOPT_run (const char *binaryOptions,
940 939
941 /* main getopt loop */ 940 /* main getopt loop */
942 while (1) 941 while (1)
943 { 942 {
944 int option_index = 0; 943 int option_index = 0;
945 unsigned int i; 944 unsigned int i;
946 int c; 945 int c;
947 946
948 c = GNgetopt_long (argc, argv, shorts, long_options, &option_index); 947 c = GNgetopt_long(argc, argv, shorts, long_options, &option_index);
949 if (c == GNUNET_SYSERR) 948 if (c == GNUNET_SYSERR)
950 break; /* No more flags to process */ 949 break; /* No more flags to process */
951 950
952 /* Check which of our program's options was given by the user */ 951 /* Check which of our program's options was given by the user */
953 for (i = 0; i < count; i++) 952 for (i = 0; i < count; i++)
954 {
955 clpc.currentArgument = GNoptind - 1;
956 if ((char) c == allOptions[i].shortName)
957 {
958 optmatch++;
959 if (allOptions[i].option_exclusive)
960 have_exclusive = allOptions[i].name;
961 if (GNUNET_OK == cont)
962 { 953 {
963 /* parse the option using the option-specific processor */ 954 clpc.currentArgument = GNoptind - 1;
964 cont = allOptions[i].processor (&clpc, 955 if ((char)c == allOptions[i].shortName)
965 allOptions[i].scls, 956 {
966 allOptions[i].name, 957 optmatch++;
967 GNoptarg); 958 if (allOptions[i].option_exclusive)
959 have_exclusive = allOptions[i].name;
960 if (GNUNET_OK == cont)
961 {
962 /* parse the option using the option-specific processor */
963 cont = allOptions[i].processor(&clpc,
964 allOptions[i].scls,
965 allOptions[i].name,
966 GNoptarg);
967 }
968 seen[i] = 1;
969 break;
970 }
971 }
972 if (i == count)
973 {
974 fprintf(stderr, _("Use %s to get a list of options.\n"), "--help");
975 cont = GNUNET_SYSERR;
968 } 976 }
969 seen[i] = 1;
970 break;
971 }
972 }
973 if (i == count)
974 {
975 fprintf (stderr, _ ("Use %s to get a list of options.\n"), "--help");
976 cont = GNUNET_SYSERR;
977 } 977 }
978 } 978 GNUNET_free(shorts);
979 GNUNET_free (shorts); 979 GNUNET_free(long_options);
980 GNUNET_free (long_options);
981 980
982 /* check that if any option that was marked as exclusive 981 /* check that if any option that was marked as exclusive
983 is the only option that was provided */ 982 is the only option that was provided */
984 if ((NULL != have_exclusive) && (optmatch > 1)) 983 if ((NULL != have_exclusive) && (optmatch > 1))
985 { 984 {
986 fprintf (stderr, 985 fprintf(stderr,
987 _ ("Option `%s' can't be used with other options.\n"), 986 _("Option `%s' can't be used with other options.\n"),
988 have_exclusive); 987 have_exclusive);
989 cont = GNUNET_SYSERR; 988 cont = GNUNET_SYSERR;
990 } 989 }
991 if (GNUNET_YES == cont) 990 if (GNUNET_YES == cont)
992 {
993 /* check that all mandatory options are present */
994 for (count = 0; NULL != allOptions[count].name; count++)
995 { 991 {
996 if ((0 == seen[count]) && (allOptions[count].option_mandatory)) 992 /* check that all mandatory options are present */
997 { 993 for (count = 0; NULL != allOptions[count].name; count++)
998 fprintf (stderr, 994 {
999 _ ("Missing mandatory option `%s'.\n"), 995 if ((0 == seen[count]) && (allOptions[count].option_mandatory))
1000 allOptions[count].name); 996 {
1001 cont = GNUNET_SYSERR; 997 fprintf(stderr,
1002 } 998 _("Missing mandatory option `%s'.\n"),
999 allOptions[count].name);
1000 cont = GNUNET_SYSERR;
1001 }
1002 }
1003 } 1003 }
1004 } 1004 GNUNET_free(seen);
1005 GNUNET_free (seen);
1006 1005
1007 /* call cleaners, if available */ 1006 /* call cleaners, if available */
1008 for (unsigned int i = 0; NULL != allOptions[i].name; i++) 1007 for (unsigned int i = 0; NULL != allOptions[i].name; i++)
1009 if (NULL != allOptions[i].cleaner) 1008 if (NULL != allOptions[i].cleaner)
1010 allOptions[i].cleaner (allOptions[i].scls); 1009 allOptions[i].cleaner(allOptions[i].scls);
1011 1010
1012 if (GNUNET_OK != cont) 1011 if (GNUNET_OK != cont)
1013 return cont; 1012 return cont;