getopt.c raw

   1  #define _BSD_SOURCE
   2  #include <unistd.h>
   3  #include <wchar.h>
   4  #include <string.h>
   5  #include <limits.h>
   6  #include <stdlib.h>
   7  #include "locale_impl.h"
   8  #include "stdio_impl.h"
   9  
  10  char *optarg;
  11  int optind=1, opterr=1, optopt, __optpos, __optreset=0;
  12  
  13  #define optpos __optpos
  14  weak_alias(__optreset, optreset);
  15  
  16  void __getopt_msg(const char *a, const char *b, const char *c, size_t l)
  17  {
  18  	FILE *f = stderr;
  19  	b = __lctrans_cur(b);
  20  	FLOCK(f);
  21  	fputs(a, f)>=0
  22  	&& fwrite(b, strlen(b), 1, f)
  23  	&& fwrite(c, 1, l, f)==l
  24  	&& putc('\n', f);
  25  	FUNLOCK(f);
  26  }
  27  
  28  int getopt(int argc, char * const argv[], const char *optstring)
  29  {
  30  	int i;
  31  	wchar_t c, d;
  32  	int k, l;
  33  	char *optchar;
  34  
  35  	if (!optind || __optreset) {
  36  		__optreset = 0;
  37  		__optpos = 0;
  38  		optind = 1;
  39  	}
  40  
  41  	if (optind >= argc || !argv[optind])
  42  		return -1;
  43  
  44  	if (argv[optind][0] != '-') {
  45  		if (optstring[0] == '-') {
  46  			optarg = argv[optind++];
  47  			return 1;
  48  		}
  49  		return -1;
  50  	}
  51  
  52  	if (!argv[optind][1])
  53  		return -1;
  54  
  55  	if (argv[optind][1] == '-' && !argv[optind][2])
  56  		return optind++, -1;
  57  
  58  	if (!optpos) optpos++;
  59  	if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
  60  		k = 1;
  61  		c = 0xfffd; /* replacement char */
  62  	}
  63  	optchar = argv[optind]+optpos;
  64  	optpos += k;
  65  
  66  	if (!argv[optind][optpos]) {
  67  		optind++;
  68  		optpos = 0;
  69  	}
  70  
  71  	if (optstring[0] == '-' || optstring[0] == '+')
  72  		optstring++;
  73  
  74  	i = 0;
  75  	d = 0;
  76  	do {
  77  		l = mbtowc(&d, optstring+i, MB_LEN_MAX);
  78  		if (l>0) i+=l; else i++;
  79  	} while (l && d != c);
  80  
  81  	if (d != c || c == ':') {
  82  		optopt = c;
  83  		if (optstring[0] != ':' && opterr)
  84  			__getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
  85  		return '?';
  86  	}
  87  	if (optstring[i] == ':') {
  88  		optarg = 0;
  89  		if (optstring[i+1] != ':' || optpos) {
  90  			optarg = argv[optind++] + optpos;
  91  			optpos = 0;
  92  		}
  93  		if (optind > argc) {
  94  			optopt = c;
  95  			if (optstring[0] == ':') return ':';
  96  			if (opterr) __getopt_msg(argv[0],
  97  				": option requires an argument: ",
  98  				optchar, k);
  99  			return '?';
 100  		}
 101  	}
 102  	return c;
 103  }
 104  
 105  weak_alias(getopt, __posix_getopt);
 106