Rizin
unix-like reverse engineering framework and cli tools
getopt.c File Reference
#include <stdio.h>
#include "getopt.h"
#include <string.h>

Go to the source code of this file.

Macros

#define _NO_PROTO
 
#define const
 
#define GETOPT_INTERFACE_VERSION   2
 
#define _(msgid)   (msgid)
 
#define SWAP_FLAGS(ch1, ch2)
 
#define NONOPTION_P   (argv[optind][0] != '-' || argv[optind][1] == '\0')
 

Enumerations

enum  { REQUIRE_ORDER , PERMUTE , RETURN_IN_ORDER }
 

Functions

char * getenv ()
 
static char * my_index (char *str, int chr) const
 
static void exchange (char **argv)
 
static const char * _getopt_initialize (int argc, char *const *argv, const char *optstring)
 
int _getopt_internal (int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only)
 
int getopt (int argc, char *const *argv, const char *optstring)
 

Variables

char * optarg
 
int optind = 1
 
int __getopt_initialized
 
static char * nextchar
 
int opterr = 1
 
int optopt = '?'
 
static enum { ... }  ordering
 
static char * posixly_correct
 
static int first_nonopt
 
static int last_nonopt
 

Macro Definition Documentation

◆ _

#define _ (   msgid)    (msgid)

Definition at line 86 of file getopt.c.

◆ _NO_PROTO

#define _NO_PROTO

Definition at line 27 of file getopt.c.

◆ const

#define const

Definition at line 38 of file getopt.c.

◆ GETOPT_INTERFACE_VERSION

#define GETOPT_INTERFACE_VERSION   2

Definition at line 52 of file getopt.c.

◆ NONOPTION_P

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

◆ SWAP_FLAGS

#define SWAP_FLAGS (   ch1,
  ch2 
)

Definition at line 287 of file getopt.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
REQUIRE_ORDER 
PERMUTE 
RETURN_IN_ORDER 

Definition at line 184 of file getopt.c.

185 {
187 } ordering;
static enum @389 ordering
@ REQUIRE_ORDER
Definition: getopt.c:186
@ RETURN_IN_ORDER
Definition: getopt.c:186
@ PERMUTE
Definition: getopt.c:186

Function Documentation

◆ _getopt_initialize()

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

Definition at line 390 of file getopt.c.

394 {
395  /* Start processing options with ARGV-element 1 (since ARGV-element 0
396  is the program name); the sequence of previously skipped
397  non-option ARGV-elements is empty. */
398 
400 
401  nextchar = NULL;
402 
403  posixly_correct = getenv ("POSIXLY_CORRECT");
404 
405  /* Determine how to handle the ordering of options and nonoptions. */
406 
407  if (optstring[0] == '-')
408  {
410  ++optstring;
411  }
412  else if (optstring[0] == '+')
413  {
415  ++optstring;
416  }
417  else if (posixly_correct != NULL)
419  else
420  ordering = PERMUTE;
421 
422 #ifdef _LIBC
423  if (posixly_correct == NULL
424  && argc == original_argc && argv == original_argv)
425  {
426  if (nonoption_flags_max_len == 0)
427  {
428  if (__getopt_nonoption_flags == NULL
429  || __getopt_nonoption_flags[0] == '\0')
430  nonoption_flags_max_len = -1;
431  else
432  {
433  const char *orig_str = __getopt_nonoption_flags;
434  int len = nonoption_flags_max_len = strlen (orig_str);
435  if (nonoption_flags_max_len < argc)
436  nonoption_flags_max_len = argc;
437  __getopt_nonoption_flags =
438  (char *) malloc (nonoption_flags_max_len);
439  if (__getopt_nonoption_flags == NULL)
440  nonoption_flags_max_len = -1;
441  else {
442  memcpy (__getopt_nonoption_flags, orig_str, len);
443  memset (__getopt_nonoption_flags + len,
444  '\0', nonoption_flags_max_len - len);
445  }
446  }
447  }
448  nonoption_flags_len = nonoption_flags_max_len;
449  }
450  else
451  nonoption_flags_len = 0;
452 #endif
453 
454  return optstring;
455 }
size_t len
Definition: 6502dis.c:15
#define NULL
Definition: cris-opc.c:27
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
static char * nextchar
Definition: getopt.c:142
static int last_nonopt
Definition: getopt.c:248
static int first_nonopt
Definition: getopt.c:247
static char * posixly_correct
Definition: getopt.c:190
int optind
Definition: getopt.c:127
char * getenv()

References argv, first_nonopt, getenv(), last_nonopt, len, malloc(), memcpy(), memset(), nextchar, NULL, optind, ordering, PERMUTE, posixly_correct, REQUIRE_ORDER, and RETURN_IN_ORDER.

Referenced by _getopt_internal().

◆ _getopt_internal()

int _getopt_internal ( int  argc,
char *const argv,
const char *  optstring,
const struct option longopts,
int longind,
int  long_only 
)

Definition at line 514 of file getopt.c.

521 {
522  int print_errors = opterr;
523  if (optstring[0] == ':')
524  print_errors = 0;
525 
526  optarg = NULL;
527 
528  if (optind == 0 || !__getopt_initialized)
529  {
530  if (optind == 0)
531  optind = 1; /* Don't scan ARGV[0], the program name. */
532  optstring = _getopt_initialize (argc, argv, optstring);
534  }
535 
536  /* Test whether ARGV[optind] points to a non-option argument.
537  Either it does not have option syntax, or there is an environment flag
538  from the shell indicating it is not an option. The later information
539  is only used when the used in the GNU libc. */
540 #ifdef _LIBC
541 # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
542  || (optind < nonoption_flags_len \
543  && __getopt_nonoption_flags[optind] == '1'))
544 #else
545 # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
546 #endif
547 
548  if (nextchar == NULL || *nextchar == '\0')
549  {
550  /* Advance to the next ARGV-element. */
551 
552  /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
553  moved back by the user (who may also have changed the arguments). */
554  if (last_nonopt > optind)
556  if (first_nonopt > optind)
558 
559  if (ordering == PERMUTE)
560  {
561  /* If we have just processed some options following some non-options,
562  exchange them so that the options come first. */
563 
565  exchange ((char **) argv);
566  else if (last_nonopt != optind)
568 
569  /* Skip any additional non-options
570  and extend the range of non-options previously skipped. */
571 
572  while (optind < argc && NONOPTION_P)
573  optind++;
575  }
576 
577  /* The special ARGV-element `--' means premature end of options.
578  Skip it like a null option,
579  then exchange with previous non-options as if it were an option,
580  then skip everything else like a non-option. */
581 
582  if (optind != argc && !strcmp (argv[optind], "--"))
583  {
584  optind++;
585 
587  exchange ((char **) argv);
588  else if (first_nonopt == last_nonopt)
590  last_nonopt = argc;
591 
592  optind = argc;
593  }
594 
595  /* If we have done all the ARGV-elements, stop the scan
596  and back over any non-options that we skipped and permuted. */
597 
598  if (optind == argc)
599  {
600  /* Set the next-arg-index to point at the non-options
601  that we previously skipped, so the caller will digest them. */
602  if (first_nonopt != last_nonopt)
604  return -1;
605  }
606 
607  /* If we have come to a non-option and did not permute it,
608  either stop the scan or describe it to the caller and pass it by. */
609 
610  if (NONOPTION_P)
611  {
612  if (ordering == REQUIRE_ORDER)
613  return -1;
614  optarg = argv[optind++];
615  return 1;
616  }
617 
618  /* We have found another option-ARGV-element.
619  Skip the initial punctuation. */
620 
621  nextchar = (argv[optind] + 1
622  + (longopts != NULL && argv[optind][1] == '-'));
623  }
624 
625  /* Decode the current option-ARGV-element. */
626 
627  /* Check whether the ARGV-element is a long option.
628 
629  If long_only and the ARGV-element has the form "-f", where f is
630  a valid short option, don't consider it an abbreviated form of
631  a long option that starts with f. Otherwise there would be no
632  way to give the -f short option.
633 
634  On the other hand, if there's a long option "fubar" and
635  the ARGV-element is "-fu", do consider that an abbreviation of
636  the long option, just like "--fu", and not "-f" with arg "u".
637 
638  This distinction seems to be the most useful approach. */
639 
640  if (longopts != NULL
641  && (argv[optind][1] == '-'
642  || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
643  {
644  char *nameend;
645  const struct option *p;
646  const struct option *pfound = NULL;
647  int exact = 0;
648  int ambig = 0;
649  int indfound = -1;
650  int option_index;
651 
652  for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
653  /* Do nothing. */ ;
654 
655  /* Test all long options for either exact match
656  or abbreviated matches. */
657  for (p = longopts, option_index = 0; p->name; p++, option_index++)
658  if (!strncmp (p->name, nextchar, nameend - nextchar))
659  {
660  if ((unsigned int) (nameend - nextchar)
661  == (unsigned int) strlen (p->name))
662  {
663  /* Exact match found. */
664  pfound = p;
665  indfound = option_index;
666  exact = 1;
667  break;
668  }
669  else if (pfound == NULL)
670  {
671  /* First nonexact match found. */
672  pfound = p;
673  indfound = option_index;
674  }
675  else
676  /* Second or later nonexact match found. */
677  ambig = 1;
678  }
679 
680  if (ambig && !exact)
681  {
682  if (print_errors)
683  fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
684  argv[0], argv[optind]);
685  nextchar += strlen (nextchar);
686  optind++;
687  optopt = 0;
688  return '?';
689  }
690 
691  if (pfound != NULL)
692  {
693  option_index = indfound;
694  optind++;
695  if (*nameend)
696  {
697  /* Don't test has_arg with >, because some C compilers don't
698  allow it to be used on enums. */
699  if (pfound->has_arg)
700  optarg = nameend + 1;
701  else
702  {
703  if (print_errors)
704  {
705  if (argv[optind - 1][1] == '-')
706  /* --option */
707  fprintf (stderr,
708  _("%s: option `--%s' doesn't allow an argument\n"),
709  argv[0], pfound->name);
710  else
711  /* +option or -option */
712  fprintf (stderr,
713  _("%s: option `%c%s' doesn't allow an argument\n"),
714  argv[0], argv[optind - 1][0], pfound->name);
715  }
716 
717  nextchar += strlen (nextchar);
718 
719  optopt = pfound->val;
720  return '?';
721  }
722  }
723  else if (pfound->has_arg == 1)
724  {
725  if (optind < argc)
726  optarg = argv[optind++];
727  else
728  {
729  if (print_errors)
730  fprintf (stderr,
731  _("%s: option `%s' requires an argument\n"),
732  argv[0], argv[optind - 1]);
733  nextchar += strlen (nextchar);
734  optopt = pfound->val;
735  return optstring[0] == ':' ? ':' : '?';
736  }
737  }
738  nextchar += strlen (nextchar);
739  if (longind != NULL)
740  *longind = option_index;
741  if (pfound->flag)
742  {
743  *(pfound->flag) = pfound->val;
744  return 0;
745  }
746  return pfound->val;
747  }
748 
749  /* Can't find it as a long option. If this is not getopt_long_only,
750  or the option starts with '--' or is not a valid short
751  option, then it's an error.
752  Otherwise interpret it as a short option. */
753  if (!long_only || argv[optind][1] == '-'
754  || my_index (optstring, *nextchar) == NULL)
755  {
756  if (print_errors)
757  {
758  if (argv[optind][1] == '-')
759  /* --option */
760  fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
761  argv[0], nextchar);
762  else
763  /* +option or -option */
764  fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
765  argv[0], argv[optind][0], nextchar);
766  }
767  nextchar = (char *) "";
768  optind++;
769  optopt = 0;
770  return '?';
771  }
772  }
773 
774  /* Look at and handle the next short option-character. */
775 
776  {
777  char c = *nextchar++;
778  char *temp = my_index (optstring, c);
779 
780  /* Increment `optind' when we start to process its last character. */
781  if (*nextchar == '\0')
782  ++optind;
783 
784  if (temp == NULL || c == ':')
785  {
786  if (print_errors)
787  {
788  if (posixly_correct)
789  /* 1003.2 specifies the format of this message. */
790  fprintf (stderr, _("%s: illegal option -- %c\n"),
791  argv[0], c);
792  else
793  fprintf (stderr, _("%s: invalid option -- %c\n"),
794  argv[0], c);
795  }
796  optopt = c;
797  return '?';
798  }
799  /* Convenience. Treat POSIX -W foo same as long option --foo */
800  if (temp[0] == 'W' && temp[1] == ';')
801  {
802  char *nameend;
803  const struct option *p;
804  const struct option *pfound = NULL;
805  int exact = 0;
806  int ambig = 0;
807  int indfound = 0;
808  int option_index;
809 
810  /* This is an option that requires an argument. */
811  if (*nextchar != '\0')
812  {
813  optarg = nextchar;
814  /* If we end this ARGV-element by taking the rest as an arg,
815  we must advance to the next element now. */
816  optind++;
817  }
818  else if (optind == argc)
819  {
820  if (print_errors)
821  {
822  /* 1003.2 specifies the format of this message. */
823  fprintf (stderr, _("%s: option requires an argument -- %c\n"),
824  argv[0], c);
825  }
826  optopt = c;
827  if (optstring[0] == ':')
828  c = ':';
829  else
830  c = '?';
831  return c;
832  }
833  else
834  /* We already incremented `optind' once;
835  increment it again when taking next ARGV-elt as argument. */
836  optarg = argv[optind++];
837 
838  /* optarg is now the argument, see if it's in the
839  table of longopts. */
840 
841  for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
842  /* Do nothing. */ ;
843 
844  /* Test all long options for either exact match
845  or abbreviated matches. */
846  for (p = longopts, option_index = 0; p->name; p++, option_index++)
847  if (!strncmp (p->name, nextchar, nameend - nextchar))
848  {
849  if ((unsigned int) (nameend - nextchar) == strlen (p->name))
850  {
851  /* Exact match found. */
852  pfound = p;
853  indfound = option_index;
854  exact = 1;
855  break;
856  }
857  else if (pfound == NULL)
858  {
859  /* First nonexact match found. */
860  pfound = p;
861  indfound = option_index;
862  }
863  else
864  /* Second or later nonexact match found. */
865  ambig = 1;
866  }
867  if (ambig && !exact)
868  {
869  if (print_errors)
870  fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
871  argv[0], argv[optind]);
872  nextchar += strlen (nextchar);
873  optind++;
874  return '?';
875  }
876  if (pfound != NULL)
877  {
878  option_index = indfound;
879  if (*nameend)
880  {
881  /* Don't test has_arg with >, because some C compilers don't
882  allow it to be used on enums. */
883  if (pfound->has_arg)
884  optarg = nameend + 1;
885  else
886  {
887  if (print_errors)
888  fprintf (stderr, _("%s: option `-W %s' doesn't allow an argument\n"),
889  argv[0], pfound->name);
890 
891  nextchar += strlen (nextchar);
892  return '?';
893  }
894  }
895  else if (pfound->has_arg == 1)
896  {
897  if (optind < argc)
898  optarg = argv[optind++];
899  else
900  {
901  if (print_errors)
902  fprintf (stderr,
903  _("%s: option `%s' requires an argument\n"),
904  argv[0], argv[optind - 1]);
905  nextchar += strlen (nextchar);
906  return optstring[0] == ':' ? ':' : '?';
907  }
908  }
909  nextchar += strlen (nextchar);
910  if (longind != NULL)
911  *longind = option_index;
912  if (pfound->flag)
913  {
914  *(pfound->flag) = pfound->val;
915  return 0;
916  }
917  return pfound->val;
918  }
919  nextchar = NULL;
920  return 'W'; /* Let the application handle it. */
921  }
922  if (temp[1] == ':')
923  {
924  if (temp[2] == ':')
925  {
926  /* This is an option that accepts an argument optionally. */
927  if (*nextchar != '\0')
928  {
929  optarg = nextchar;
930  optind++;
931  }
932  else
933  optarg = NULL;
934  nextchar = NULL;
935  }
936  else
937  {
938  /* This is an option that requires an argument. */
939  if (*nextchar != '\0')
940  {
941  optarg = nextchar;
942  /* If we end this ARGV-element by taking the rest as an arg,
943  we must advance to the next element now. */
944  optind++;
945  }
946  else if (optind == argc)
947  {
948  if (print_errors)
949  {
950  /* 1003.2 specifies the format of this message. */
951  fprintf (stderr,
952  _("%s: option requires an argument -- %c\n"),
953  argv[0], c);
954  }
955  optopt = c;
956  if (optstring[0] == ':')
957  c = ':';
958  else
959  c = '?';
960  }
961  else
962  /* We already incremented `optind' once;
963  increment it again when taking next ARGV-elt as argument. */
964  optarg = argv[optind++];
965  nextchar = NULL;
966  }
967  }
968  return c;
969  }
970 }
void * p
Definition: libc.cpp:67
#define c(i)
Definition: sha256.c:43
Definition: getopt.h:84
int val
Definition: getopt.h:94
int * flag
Definition: getopt.h:93
int has_arg
Definition: getopt.h:92
char * name
Definition: getopt.h:88
static const char * _getopt_initialize(int argc, char *const *argv, const char *optstring)
Definition: getopt.c:390
int __getopt_initialized
Definition: getopt.c:133
static void exchange(char **argv)
Definition: getopt.c:304
int optopt
Definition: getopt.c:153
#define NONOPTION_P
#define _(msgid)
Definition: getopt.c:86
char * optarg
Definition: getopt.c:112
static char * my_index(char *str, int chr) const
Definition: getopt.c:214
int opterr
Definition: getopt.c:147

References _, __getopt_initialized, _getopt_initialize(), argv, c, exchange(), first_nonopt, option::flag, option::has_arg, last_nonopt, my_index(), option::name, nextchar, NONOPTION_P, NULL, optarg, opterr, optind, optopt, ordering, p, PERMUTE, posixly_correct, REQUIRE_ORDER, and option::val.

Referenced by getopt(), getopt_long(), and getopt_long_only().

◆ exchange()

static void exchange ( char **  argv)
static

Definition at line 304 of file getopt.c.

306 {
307  int bottom = first_nonopt;
308  int middle = last_nonopt;
309  int top = optind;
310  char *tem;
311 
312  /* Exchange the shorter segment with the far end of the longer segment.
313  That puts the shorter segment into the right place.
314  It leaves the longer segment in the right place overall,
315  but it consists of two parts that need to be swapped next. */
316 
317 #ifdef _LIBC
318  /* First make sure the handling of the `__getopt_nonoption_flags'
319  string can work normally. Our top argument must be in the range
320  of the string. */
321  if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
322  {
323  /* We must extend the array. The user plays games with us and
324  presents new arguments. */
325  char *new_str = malloc (top + 1);
326  if (new_str == NULL)
327  nonoption_flags_len = nonoption_flags_max_len = 0;
328  else
329  {
330  memcpy (new_str, __getopt_nonoption_flags,
331  nonoption_flags_max_len);
332  memset (new_str + nonoption_flags_max_len,
333  '\0', top + 1 - nonoption_flags_max_len);
334  nonoption_flags_max_len = top + 1;
335  __getopt_nonoption_flags = new_str;
336  }
337  }
338 #endif
339 
340  while (top > middle && middle > bottom)
341  {
342  if (top - middle > middle - bottom)
343  {
344  /* Bottom segment is the short one. */
345  int len = middle - bottom;
346  register int i;
347 
348  /* Swap it with the top part of the top segment. */
349  for (i = 0; i < len; i++)
350  {
351  tem = argv[bottom + i];
352  argv[bottom + i] = argv[top - (middle - bottom) + i];
353  argv[top - (middle - bottom) + i] = tem;
354  SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
355  }
356  /* Exclude the moved bottom segment from further swapping. */
357  top -= len;
358  }
359  else
360  {
361  /* Top segment is the short one. */
362  int len = top - middle;
363  register int i;
364 
365  /* Swap it with the bottom part of the bottom segment. */
366  for (i = 0; i < len; i++)
367  {
368  tem = argv[bottom + i];
369  argv[bottom + i] = argv[middle + i];
370  argv[middle + i] = tem;
371  SWAP_FLAGS (bottom + i, middle + i);
372  }
373  /* Exclude the moved top segment from further swapping. */
374  bottom += len;
375  }
376  }
377 
378  /* Update records for the slots the non-options now occupy. */
379 
382 }
lzma_index ** i
Definition: index.h:629
#define SWAP_FLAGS(ch1, ch2)
Definition: getopt.c:287

References argv, first_nonopt, i, last_nonopt, len, malloc(), memcpy(), memset(), NULL, optind, and SWAP_FLAGS.

Referenced by _getopt_internal().

◆ getenv()

◆ getopt()

int getopt ( int  argc,
char *const argv,
const char *  optstring 
)

Definition at line 973 of file getopt.c.

977 {
978  return _getopt_internal (argc, argv, optstring,
979  (const struct option *) 0,
980  (int *) 0,
981  0);
982 }
int _getopt_internal(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *longind, int long_only)
Definition: getopt.c:514

References _getopt_internal(), and argv.

◆ my_index()

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

Definition at line 214 of file getopt.c.

217 {
218  while (*str)
219  {
220  if (*str == chr)
221  return (char *) str;
222  str++;
223  }
224  return 0;
225 }

References cmd_descs_generate::str.

Referenced by _getopt_internal().

Variable Documentation

◆ __getopt_initialized

int __getopt_initialized

Definition at line 133 of file getopt.c.

Referenced by _getopt_internal().

◆ first_nonopt

int first_nonopt
static

Definition at line 247 of file getopt.c.

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

◆ last_nonopt

int last_nonopt
static

Definition at line 248 of file getopt.c.

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

◆ nextchar

char* nextchar
static

Definition at line 142 of file getopt.c.

Referenced by _getopt_initialize(), _getopt_internal(), and file_getbuffer().

◆ optarg

char* optarg

Definition at line 112 of file getopt.c.

Referenced by _getopt_internal(), and getopt().

◆ opterr

int opterr = 1

Definition at line 147 of file getopt.c.

Referenced by _getopt_internal(), and getopt().

◆ optind

int optind = 1

Definition at line 127 of file getopt.c.

Referenced by _getopt_initialize(), _getopt_internal(), exchange(), and getopt().

◆ optopt

int optopt = '?'

Definition at line 153 of file getopt.c.

Referenced by _getopt_internal(), and getopt().

◆ 

enum { ... } ordering

◆ posixly_correct

char* posixly_correct
static

Definition at line 190 of file getopt.c.

Referenced by _getopt_initialize(), _getopt_internal(), and _getopt_internal_r().