GNUnet 0.21.1
getopt.c File Reference

GNU style option parsing. More...

#include "platform.h"
#include "gnunet_util_lib.h"
Include dependency graph for getopt.c:

Go to the source code of this file.

Data Structures

struct  GNoption
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util-getopt", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)    GNUNET_log_from_strerror (kind, "util-getopt", syscall)
 
#define _(msgid)   (msgid)
 
#define SWAP_FLAGS(ch1, ch2)
 
#define NONOPTION_P   (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')
 

Enumerations

enum  { REQUIRE_ORDER , PERMUTE , RETURN_IN_ORDER }
 

Functions

char * getenv ()
 
static char * my_index (const char *str, int chr)
 
static void exchange (char **argv)
 
static const char * _getopt_initialize (int argc, char *const *argv, const char *optstring)
 
static int GN_getopt_internal (int argc, char *const *argv, const char *optstring, const struct GNoption *longopts, int *longind, int long_only)
 
static int GNgetopt_long (int argc, char *const *argv, const char *options, const struct GNoption *long_options, int *opt_index)
 
int GNUNET_GETOPT_run (const char *binaryOptions, const struct GNUNET_GETOPT_CommandLineOption *allOptions, unsigned int argc, char *const *argv)
 Parse the command line. More...
 

Variables

static char * GNoptarg = NULL
 
static int GNoptind = 1
 
static char * nextchar
 
static enum { ... }  ordering
 
static char * posixly_correct
 
static int first_nonopt
 
static int last_nonopt
 

Detailed Description

GNU style option parsing.

TODO: get rid of statics (make reentrant) and replace main GNU getopt parser with one that actually fits our API.

Definition in file getopt.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-getopt", __VA_ARGS__)

Definition at line 51 of file getopt.c.

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)     GNUNET_log_from_strerror (kind, "util-getopt", syscall)

Definition at line 53 of file getopt.c.

◆ _

#define _ (   msgid)    (msgid)

Definition at line 63 of file getopt.c.

◆ SWAP_FLAGS

#define SWAP_FLAGS (   ch1,
  ch2 
)

Definition at line 233 of file getopt.c.

◆ NONOPTION_P

#define NONOPTION_P   (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
REQUIRE_ORDER 
PERMUTE 
RETURN_IN_ORDER 

Definition at line 175 of file getopt.c.

@ REQUIRE_ORDER
Definition: getopt.c:175
@ RETURN_IN_ORDER
Definition: getopt.c:175
@ PERMUTE
Definition: getopt.c:175
static enum @36 ordering

Function Documentation

◆ getenv()

◆ my_index()

static char * my_index ( const char *  str,
int  chr 
)
static

Definition at line 196 of file getopt.c.

197{
198 while (*str)
199 {
200 if (*str == chr)
201 return (char *) str;
202 str++;
203 }
204 return 0;
205}

Referenced by GN_getopt_internal().

Here is the caller graph for this function:

◆ exchange()

static void exchange ( char **  argv)
static

Definition at line 251 of file getopt.c.

252{
253 int bottom = first_nonopt;
254 int middle = last_nonopt;
255 int top = GNoptind;
256 char *tem;
257
258 /* Exchange the shorter segment with the far end of the longer segment.
259 * That puts the shorter segment into the right place.
260 * It leaves the longer segment in the right place overall,
261 * but it consists of two parts that need to be swapped next. */
262
263 while (top > middle && middle > bottom)
264 {
265 if (top - middle > middle - bottom)
266 {
267 /* Bottom segment is the short one. */
268 int len = middle - bottom;
269 register int i;
270
271 /* Swap it with the top part of the top segment. */
272 for (i = 0; i < len; i++)
273 {
274 tem = argv[bottom + i];
275 argv[bottom + i] = argv[top - (middle - bottom) + i];
276 argv[top - (middle - bottom) + i] = tem;
277 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
278 }
279 /* Exclude the moved bottom segment from further swapping. */
280 top -= len;
281 }
282 else
283 {
284 /* Top segment is the short one. */
285 int len = top - middle;
286 register int i;
287
288 /* Swap it with the bottom part of the bottom segment. */
289 for (i = 0; i < len; i++)
290 {
291 tem = argv[bottom + i];
292 argv[bottom + i] = argv[middle + i];
293 argv[middle + i] = tem;
294 SWAP_FLAGS (bottom + i, middle + i);
295 }
296 /* Exclude the moved top segment from further swapping. */
297 bottom += len;
298 }
299 }
300
301 /* Update records for the slots the non-options now occupy. */
302
305}
static int GNoptind
Definition: getopt.c:134
static int last_nonopt
Definition: getopt.c:231
#define SWAP_FLAGS(ch1, ch2)
Definition: getopt.c:233
static int first_nonopt
Definition: getopt.c:230

References first_nonopt, GNoptind, last_nonopt, and SWAP_FLAGS.

Referenced by GN_getopt_internal().

Here is the caller graph for this function:

◆ _getopt_initialize()

static const char * _getopt_initialize ( int  argc,
char *const *  argv,
const char *  optstring 
)
static

Definition at line 316 of file getopt.c.

317{
318 /* Start processing options with ARGV-element 1 (since ARGV-element 0
319 * is the program name); the sequence of previously skipped
320 * non-option ARGV-elements is empty. */
321
323
324 nextchar = NULL;
325
326 posixly_correct = getenv ("POSIXLY_CORRECT");
327
328 /* Determine how to handle the ordering of options and nonoptions. */
329
330 if (optstring[0] == '-')
331 {
333 ++optstring;
334 }
335 else if (optstring[0] == '+')
336 {
338 ++optstring;
339 }
340 else if (posixly_correct != NULL)
342 else
344
345 return optstring;
346}
static char * nextchar
Definition: getopt.c:143
char * getenv()
static char * posixly_correct
Definition: getopt.c:178

References first_nonopt, getenv(), GNoptind, last_nonopt, nextchar, ordering, PERMUTE, posixly_correct, REQUIRE_ORDER, and RETURN_IN_ORDER.

Referenced by GN_getopt_internal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GN_getopt_internal()

static int GN_getopt_internal ( int  argc,
char *const *  argv,
const char *  optstring,
const struct GNoption longopts,
int *  longind,
int  long_only 
)
static

Definition at line 406 of file getopt.c.

412{
413 static int __getopt_initialized = 0;
414 static int GNopterr = 1;
415
416 GNoptarg = NULL;
417
418 if ((GNoptind == 0) || ! __getopt_initialized)
419 {
420 if (GNoptind == 0)
421 GNoptind = 1; /* Don't scan ARGV[0], the program name. */
422 optstring = _getopt_initialize (argc, argv, optstring);
423 __getopt_initialized = 1;
424 }
425
426 /* Test whether ARGV[GNoptind] points to a non-option argument.
427 * Either it does not have option syntax, or there is an environment flag
428 * from the shell indicating it is not an option. The later information
429 * is only used when the used in the GNU libc. */
430#define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0')
431
432 if ((nextchar == NULL) || (*nextchar == '\0'))
433 {
434 /* Advance to the next ARGV-element. */
435
436 /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been
437 * moved back by the user (who may also have changed the arguments). */
438 if (last_nonopt > GNoptind)
442
443 if (ordering == PERMUTE)
444 {
445 /* If we have just processed some options following some non-options,
446 * exchange them so that the options come first. */
447
449 exchange ((char **) argv);
450 else if (last_nonopt != GNoptind)
452
453 /* Skip any additional non-options
454 * and extend the range of non-options previously skipped. */
455
456 while (GNoptind < argc && NONOPTION_P)
457 GNoptind++;
459 }
460
461 /* The special ARGV-element `--' means premature end of options.
462 * Skip it like a null option,
463 * then exchange with previous non-options as if it were an option,
464 * then skip everything else like a non-option. */
465 if ((GNoptind != argc) && ! strcmp (argv[GNoptind], "--"))
466 {
467 GNoptind++;
468
470 exchange ((char **) argv);
471 else if (first_nonopt == last_nonopt)
473 last_nonopt = argc;
474
475 GNoptind = argc;
476 }
477
478 /* If we have done all the ARGV-elements, stop the scan
479 * and back over any non-options that we skipped and permuted. */
480
481 if (GNoptind == argc)
482 {
483 /* Set the next-arg-index to point at the non-options
484 * that we previously skipped, so the caller will digest them. */
487 return -1;
488 }
489
490 /* If we have come to a non-option and did not permute it,
491 * either stop the scan or describe it to the caller and pass it by. */
492
493 if (NONOPTION_P)
494 {
495 if (ordering == REQUIRE_ORDER)
496 return -1;
497 GNoptarg = argv[GNoptind++];
498 return 1;
499 }
500
501 /* We have found another option-ARGV-element.
502 * Skip the initial punctuation. */
503
504 nextchar =
505 (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-'));
506 }
507
508 /* Decode the current option-ARGV-element. */
509
510 /* Check whether the ARGV-element is a long option.
511 *
512 * If long_only and the ARGV-element has the form "-f", where f is
513 * a valid short option, don't consider it an abbreviated form of
514 * a long option that starts with f. Otherwise there would be no
515 * way to give the -f short option.
516 *
517 * On the other hand, if there's a long option "fubar" and
518 * the ARGV-element is "-fu", do consider that an abbreviation of
519 * the long option, just like "--fu", and not "-f" with arg "u".
520 *
521 * This distinction seems to be the most useful approach. */if ((longopts != NULL) &&
522 ((argv[GNoptind][1] == '-') ||
523 (long_only &&
524 (argv[GNoptind][2] || ! my_index (optstring, argv[GNoptind][1])))))
525 {
526 char *nameend;
527 const struct GNoption *p;
528 const struct GNoption *pfound = NULL;
529 int exact = 0;
530 int ambig = 0;
531 int indfound = -1;
532 int option_index;
533
534 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
535 /* Do nothing. */;
536
537 /* Test all long options for either exact match
538 * or abbreviated matches. */
539 for (p = longopts, option_index = 0; p->name; p++, option_index++)
540 if (! strncmp (p->name, nextchar, nameend - nextchar))
541 {
542 if ((unsigned int) (nameend - nextchar) ==
543 (unsigned int) strlen (p->name))
544 {
545 /* Exact match found. */
546 pfound = p;
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 }
557 else
558 /* Second or later nonexact match found. */
559 ambig = 1;
560 }
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++;
571 return '?';
572 }
573
574 if (pfound != NULL)
575 {
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;
634 }
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) )
642 {
643 if (GNopterr)
644 {
645 if (argv[GNoptind][1] == '-')
646 /* --option */
647 fprintf (stderr,
648 _ ("%s: unrecognized option `--%s'\n"),
649 argv[0],
650 nextchar);
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 '?';
662 }
663 }
664
665 /* Look at and handle the next short option-character. */
666
667 {
668 char c = *nextchar++;
669 char *temp = my_index (optstring, c);
670
671 /* Increment `GNoptind' when we start to process its last character. */
672 if (*nextchar == '\0')
673 ++GNoptind;
674
675 if ((temp == NULL) || (c == ':'))
676 {
677 if (GNopterr)
678 {
679 if (posixly_correct)
680 /* 1003.2 specifies the format of this message. */
681 fprintf (stderr, _ ("%s: illegal option -- %c\n"), argv[0], c);
682 else
683 fprintf (stderr, _ ("%s: invalid option -- %c\n"), argv[0], c);
684 }
685 return '?';
686 }
687 /* Convenience. Treat POSIX -W foo same as long option --foo */
688 if ((temp[0] == 'W') && (temp[1] == ';'))
689 {
690 char *nameend;
691 const struct GNoption *p;
692 const struct GNoption *pfound = NULL;
693 int exact = 0;
694 int ambig = 0;
695 int indfound = 0;
696 int option_index;
697
698 /* This is an option that requires an argument. */
699 if (*nextchar != '\0')
700 {
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)
707 {
708 if (GNopterr)
709 {
710 /* 1003.2 specifies the format of this message. */
711 fprintf (stderr,
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++];
726
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++;
767 return '?';
768 }
769 if (pfound != NULL)
770 {
771 option_index = indfound;
772 if (*nameend)
773 {
774 /* Don't test has_arg with >, because some C compilers don't
775 * allow it to be used on enums. */
776 if (pfound->has_arg)
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;
814 }
815 nextchar = NULL;
816 return 'W'; /* Let the application handle it. */
817 }
818 if (temp[1] == ':')
819 {
820 if (temp[2] == ':')
821 {
822 /* This is an option that accepts an argument optionally. */
823 if (*nextchar != '\0')
824 {
826 GNoptind++;
827 }
828 else
829 GNoptarg = NULL;
830 nextchar = NULL;
831 }
832 else
833 {
834 /* This is an option that requires an argument. */
835 if (*nextchar != '\0')
836 {
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 }
864 return c;
865 }
866}
static char * GNoptarg
Definition: getopt.c:119
static void exchange(char **argv)
Definition: getopt.c:251
static const char * _getopt_initialize(int argc, char *const *argv, const char *optstring)
Definition: getopt.c:316
static char * my_index(const char *str, int chr)
Definition: getopt.c:196
#define NONOPTION_P
#define _(msgid)
Definition: getopt.c:63
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
int has_arg
Definition: getopt.c:93
int val
Definition: getopt.c:95
const char * name
Definition: getopt.c:90
int * flag
Definition: getopt.c:94

References _, _getopt_initialize(), exchange(), first_nonopt, GNoption::flag, GNoptarg, GNoptind, GNoption::has_arg, last_nonopt, my_index(), GNoption::name, nextchar, NONOPTION_P, ordering, p, PERMUTE, posixly_correct, REQUIRE_ORDER, and GNoption::val.

Referenced by GNgetopt_long().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNgetopt_long()

static int GNgetopt_long ( int  argc,
char *const *  argv,
const char *  options,
const struct GNoption long_options,
int *  opt_index 
)
static

Definition at line 870 of file getopt.c.

875{
876 return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
877}
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
static int GN_getopt_internal(int argc, char *const *argv, const char *optstring, const struct GNoption *longopts, int *longind, int long_only)
Definition: getopt.c:406

References GN_getopt_internal(), and options.

Referenced by GNUNET_GETOPT_run().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ GNoptarg

char* GNoptarg = NULL
static

Definition at line 119 of file getopt.c.

Referenced by GN_getopt_internal(), and GNUNET_GETOPT_run().

◆ GNoptind

int GNoptind = 1
static

Definition at line 134 of file getopt.c.

Referenced by _getopt_initialize(), exchange(), GN_getopt_internal(), and GNUNET_GETOPT_run().

◆ nextchar

char* nextchar
static

Definition at line 143 of file getopt.c.

Referenced by _getopt_initialize(), and GN_getopt_internal().

◆ 

enum { ... } ordering

◆ posixly_correct

char* posixly_correct
static

Definition at line 178 of file getopt.c.

Referenced by _getopt_initialize(), and GN_getopt_internal().

◆ first_nonopt

int first_nonopt
static

Definition at line 230 of file getopt.c.

Referenced by _getopt_initialize(), exchange(), and GN_getopt_internal().

◆ last_nonopt

int last_nonopt
static

Definition at line 231 of file getopt.c.

Referenced by _getopt_initialize(), exchange(), and GN_getopt_internal().