root/src/udns/getopt.c

Revision 5a9b91bc0a14543e0995eba973fbeacc05aaee8b, 3.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

svn merge -r 327:330 https://labs.omniti.com/reconnoiter/branches/dev/udns .

closes #38

  • Property mode set to 100644
Line 
1 /* $Id: getopt.c,v 1.2 2007/01/07 23:19:19 mjt Exp $
2  * Simple getopt() implementation.
3  *
4  * Standard interface:
5  *  extern int getopt(int argc, char *const *argv, const char *opts);
6  *  extern int optind;    current index in argv[]
7  *  extern char *optarg;  argument for the current option
8  *  extern int optopt;    the current option
9  *  extern int opterr;    to control error printing
10  *
11  * Some minor extensions:
12  *  ignores leading `+' sign in opts[] (unemplemented GNU extension)
13  *  handles optional arguments, in form "x::" in opts[]
14  *  if opts[] starts with `:', will return `:' in case of missing required
15  *    argument, instead of '?'.
16  *
17  * Compile with -DGETOPT_NO_OPTERR to never print errors internally.
18  * Compile with -DGETOPT_NO_STDIO to use write() calls instead of fprintf() for
19  *  error reporting (ignored with -DGETOPT_NO_OPTERR).
20  * Compile with -DGETOPT_CLASS=static to get static linkage.
21  * Compile with -DGETOPT_MY to redefine all visible symbols to be prefixed
22  *  with "my_", like my_getopt instead of getopt.
23  * Compile with -DTEST to get a test executable.
24  *
25  * Written by Michael Tokarev.  Public domain.
26  */
27
28 #include <string.h>
29
30 #ifndef GETOPT_CLASS
31 # define GETOPT_CLASS
32 #endif
33 #ifdef GETOPT_MY
34 # define optarg my_optarg
35 # define optind my_optind
36 # define opterr my_opterr
37 # define optopt my_optopt
38 # define getopt my_getopt
39 #endif
40
41 GETOPT_CLASS char *optarg /* = NULL */;
42 GETOPT_CLASS int optind = 1;
43 GETOPT_CLASS int opterr = 1;
44 GETOPT_CLASS int optopt;
45
46 static char *nextc /* = NULL */;
47
48 #if defined(GETOPT_NO_OPTERR)
49
50 #define printerr(argv, msg)
51
52 #elif defined(GETOPT_NO_STDIO)
53
54 extern int write(int, void *, int);
55
56 static void printerr(char *const *argv, const char *msg) {
57   if (opterr) {
58     char buf[64];
59     unsigned pl = strlen(argv[0]);
60     unsigned ml = strlen(msg);
61     char *p;
62     if (pl + /*": "*/2 + ml + /*" -- c\n"*/6 > sizeof(buf)) {
63       write(2, argv[0], pl);
64       p = buf;
65     }
66     else {
67       memcpy(buf, argv[0], ml);
68       p = buf + pl;
69     }
70     *p++ = ':'; *p++ = ' ';
71     memcpy(p, msg, ml); p += ml;
72     *p++ = ' '; *p++ = '-'; *p++ = '-'; *p++ = ' ';
73     *p++ = optopt;
74     *p++ = '\n';
75     write(2, buf, p - buf);
76   }
77 }
78
79 #else
80
81 #include <stdio.h>
82 static void printerr(char *const *argv, const char *msg) {
83   if (opterr)
84      fprintf(stderr, "%s: %s -- %c\n", argv[0], msg, optopt);
85 }
86
87 #endif
88
89 GETOPT_CLASS int getopt(int argc, char *const *argv, const char *opts) {
90   char *p;
91
92   optarg = 0;
93   if (*opts == '+') /* GNU extension (permutation) - isn't supported */
94     ++opts;
95
96   if (!optind) {  /* a way to reset things */
97     nextc = 0;
98     optind = 1;
99   }
100
101   if (!nextc || !*nextc) {   /* advance to the next argv element */
102     /* done scanning? */
103     if (optind >= argc)
104       return -1;
105     /* not an optional argument */
106     if (argv[optind][0] != '-')
107       return -1;
108     /* bare `-' */
109     if (argv[optind][1] == '\0')
110       return -1;
111     /* special case `--' argument */
112     if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
113       ++optind;
114       return -1;
115     }
116     nextc = argv[optind] + 1;
117   }
118
119   optopt = *nextc++;
120   if (!*nextc)
121     ++optind;
122   p = strchr(opts, optopt);
123   if (!p || optopt == ':') {
124     printerr(argv, "illegal option");
125     return '?';
126   }
127   if (p[1] == ':') {
128     if (*nextc) {
129       optarg = nextc;
130       nextc = NULL;
131       ++optind;
132     }
133     else if (p[2] != ':') {     /* required argument */
134       if (optind >= argc) {
135         printerr(argv, "option requires an argument");
136         return *opts == ':' ? ':' : '?';
137       }
138       else
139         optarg = argv[optind++];
140     }
141   }
142   return optopt;
143 }
144
145 #ifdef TEST
146
147 #include <stdio.h>
148
149 int main(int argc, char **argv) {
150   int c;
151   while((c = getopt(argc, argv, "ab:c::")) != -1) switch(c) {
152   case 'a':
153   case 'b':
154   case 'c':
155     printf("option %c %s\n", c, optarg ? optarg : "(none)");
156     break;
157   default:
158     return -1;
159   }
160   for(c = optind; c < argc; ++c)
161     printf("non-opt: %s\n", argv[c]);
162   return 0;
163 }
164
165 #endif
Note: See TracBrowser for help on using the browser.