source: trunk/sys/dietlibc/getopt_long_only.c @ 333

Last change on this file since 333 was 1, checked in by alain, 7 years ago

First import

File size: 2.8 KB
Line 
1#include <string.h>
2#include <getopt.h>
3
4static void getopterror(int which) {
5  static char error1[]="Unknown option `-x'.\n";
6  static char error2[]="Missing argument for `-x'.\n";
7  if (opterr) {
8    if (which) {
9      error2[23]=optopt;
10      write(2,error2,28);
11    } else {
12      error1[17]=optopt;
13      write(2,error1,22);
14    }
15  }
16}
17
18int getopt_long_only(int argc, char * const argv[], const char *optstring,
19                const struct option *longopts, int *longindex) {
20  static int lastidx,lastofs;
21  char *tmp,*arg;
22  if (optind==0) { optind=1; lastidx=0; }       /* whoever started setting optind to 0 should be shot */
23again:
24  if (optind>argc || !argv[optind] || *argv[optind]!='-' || argv[optind][1]==0)
25    return -1;
26  if (argv[optind][1]=='-' && argv[optind][2]==0) {
27    ++optind;
28    return -1;
29  }
30  if (argv[optind][1]=='-')
31    arg=argv[optind]+2;
32  else
33    arg=argv[optind]+1;
34  {
35    char* max=strchr(arg,'=');
36    const struct option* o;
37    const struct option* match=0;
38    if (!max) max=arg+strlen(arg);
39    for (o=longopts; o->name; ++o) {
40      size_t tlen=max-arg;
41      if (!strncmp(o->name,arg,tlen)) { /* match */
42        if (strlen(o->name)==tlen) {
43          match=o;      /* perfect match, not just prefix */
44          break;
45        }
46        if (!match)
47          match=o;
48        else
49          /* Another imperfect match. */
50          match=(struct option*)-1;
51      }
52    }
53    if (match!=(struct option*)-1 && (o=match)) {
54      if (longindex) *longindex=o-longopts;
55      if (o->has_arg>0) {
56        if (*max=='=')
57          optarg=max+1;
58        else {
59          optarg=argv[optind+1];
60          if (!optarg && o->has_arg==1) {       /* no argument there */
61            if (*optstring==':') return ':';
62            write(2,"argument required: `",20);
63            write(2,arg,(size_t)(max-arg));
64            write(2,"'.\n",3);
65            ++optind;
66            return '?';
67          }
68          ++optind;
69        }
70      }
71      ++optind;
72      if (o->flag)
73        *(o->flag)=o->val;
74      else
75        return o->val;
76      return 0;
77    }
78    if (argv[optind][1]!='-') goto shortopt;
79    if (*optstring==':') return ':';
80    write(2,"invalid option `",16);
81    write(2,arg,(size_t)(max-arg));
82    write(2,"'.\n",3);
83    ++optind;
84    return '?';
85  }
86shortopt:
87  if (lastidx!=optind) {
88    lastidx=optind; lastofs=0;
89  }
90  optopt=argv[optind][lastofs+1];
91  if ((tmp=strchr(optstring,optopt))) {
92    if (*tmp==0) {      /* apparently, we looked for \0, i.e. end of argument */
93      ++optind;
94      goto again;
95    }
96    if (tmp[1]==':') {  /* argument expected */
97      if (tmp[2]==':' || argv[optind][lastofs+2]) {     /* "-foo", return "oo" as optarg */
98        if (!*(optarg=argv[optind]+lastofs+2)) optarg=0;
99        goto found;
100      }
101      optarg=argv[optind+1];
102      if (!optarg) {    /* missing argument */
103        ++optind;
104        if (*optstring==':') return ':';
105        getopterror(1);
106        return ':';
107      }
108      ++optind;
109    } else {
110      ++lastofs;
111      return optopt;
112    }
113found:
114    ++optind;
115    return optopt;
116  } else {      /* not found */
117    getopterror(0);
118    ++optind;
119    return '?';
120  }
121}
Note: See TracBrowser for help on using the repository browser.