HuntnGather – Blame information for rev

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /****************************************************************************
31 office 2 * getopt(): Return the next user option on each iteration.
1 office 3 * This is a clone of the usual UNIX getopt() function.
4 * If you have never used a getopt() before, you'll have to
5 * read about it on any UNIX machine or other C system that
6 * documents it.
7 *
8 * Author: Daniel J. Barrett, barrett@cs.umass.edu.
9 *
10 * License: This code is placed in the Public Domain.
11 * Give it away to anybody for free!
12 * Use it for any purpose you like!
13 *
14 * If you use this code in a program, please give me credit
15 * for my work. Thanks!
16 *
17 * Why I wrote it:
18 *
19 * Because every other getopt() function I have ever seen
20 * had source code that was difficult to understand.
21 * I wrote this code to be very modular and readable.
22 * I hope you find it instructive and/or helpful.
23 *
24 * BUGS
25 * "--JUNK" is treated as "--", the "end of options" flag.
26 *
27 * REVISION HISTORY:
28 *
29 * Version: 1.3
30 * Date: January 21, 1993
31 * Comments: Bugfix. Option "-:" was accepted as OK. Not anymore.
32 *
33 * Version: 1.2a
34 * Date: January 21, 1993
35 * Comments: Improved the TESTME main program. More useful output.
36 * Rewrote Error() to eliminate redundancy.
37 *
38 * Version: 1.2
39 * Date: January 21, 1993
40 * Comments: If a legal option is not followed by a required
41 * argument, getopt() previously returned the option's
42 * character. It should have returned UNKNOWN_OPT.
43 * This has been fixed. Note that HandleArgument()
44 * now returns an int value rather than void.
45 *
46 * Version: 1.1b
47 * Date: December 17, 1991.
48 * Comments: Minor change of NULL to '\0' in 1 spot.
49 *
50 * Version: 1.1
51 * Date: February 20, 1991.
52 * Comments: Bug fix in Pass(). Forgot to check that the
53 * current argument is non-empty and starts with
54 * a DASH.
55 *
56 * Got rid of the unnecessary "g_" at the beginning
57 * of each function name. Since they're static, we
58 * don't have to worry about duplication of names
59 * by the calling program.
60 *
61 * Version: 1.0
62 * Date: April 12, 1990.
63 * Comments: First released version.
64 *
65 ****************************************************************************/
66  
31 office 67 #if defined MWDEBUG
68 #include "memwatch.h"
69 #endif
70  
1 office 71 #ifndef __STDIO_H /* If we haven't already included stdio.h, do it. */
72 # include <stdio.h> /* Maybe someday I'll eliminate this. */
73 #endif
74  
75 #ifndef __STRING_H
76 # include <string.h> /* For index() */
77 #endif
78  
79 /************************************************************************
80 * Some constants.
81 ************************************************************************/
82  
83 #define DASH '-' /* This preceeds an option. */
84 #define ARG_COMING ':' /* In the option string, this indicates that
85 * that the option requires an argument. */
86 #define UNKNOWN_OPT '?' /* The char returned for unknown option. */
87  
88 /************************************************************************
89 * Internal error codes.
90 ************************************************************************/
91  
92 #define ERROR_BAD_OPTION 1
93 #define ERROR_MISSING_ARGUMENT 2
94  
95 /************************************************************************
96 * ANSI function prototypes.
97 ************************************************************************/
98  
99 int getopt(int argc, char *argv[], char *optString);
100 static int NextOption(char *argv[], char *optString);
101 static int RealOption(char *argv[], char *str, int *skip, int *ind,
102 int opt);
103 static int HandleArgument(char *argv[], int *optind, int *skip);
104 static void Error(int err, int c);
105 static void Pass(char *argv[], int *optind, int *optsSkipped);
106  
107 /************************************************************************
108 * Global variables. You must declare these externs in your program
109 * if you want to see their values!
110 ************************************************************************/
31 office 111  
1 office 112 char *optarg = NULL; /* This will point to a required argument, if any. */
113 int optind = 1; /* The index of the next argument in argv. */
114 int opterr = 1; /* 1 == print internal error messages. 0 else. */
115 int optopt; /* The actual option letter that was found. */
116  
117  
118 int getopt(int argc, char *argv[], char *optString)
119 {
120 optarg = NULL;
121 if (optind < argc) /* More arguments to check. */
122 return(NextOption(argv, optString));
123 else /* We're done. */
124 return(EOF);
125 }
126  
127  
128 /* If the current argument does not begin with DASH, it is not an option.
129 * Return EOF.
130 * If we have ONLY a DASH, and nothing after it... return EOF as well.
131 * If we have a DASH followed immediately by another DASH, this is the
132 * special "--" option that means "no more options follow." Return EOF.
133 * Otherwise, we have an actual option or list of options. Process it. */
31 office 134  
1 office 135 static int NextOption(char *argv[], char *optString)
136 {
137 static int optsSkipped = 0; /* In a single argv[i]. */
31 office 138  
1 office 139 if ((argv[optind][0] == DASH)
140 && ((optopt = argv[optind][1+optsSkipped]) != '\0'))
141 {
142 if (optopt == DASH)
143 {
144 optind++;
145 return(EOF);
146 }
147 else
148 return(RealOption(argv, optString, &optsSkipped,
149 &optind, optopt));
150 }
151 else
152 return(EOF);
153 }
154  
155  
156 /* At this point, we know that argv[optind] is an option or list of
157 * options. If this is a list of options, *optsSkipped tells us how
158 * many of those options have ALREADY been parsed on previous calls
159 * to getopt().
160 * If the option is not legal (not in optString), complain and return
161 * UNKNOWN_OPT.
162 * If the option requires no argument, just return the option letter.
163 * If the option requires an argument, call HandleArgument and return
164 * the option letter. */
31 office 165  
1 office 166 static int RealOption(char *argv[], char *optString, int *optsSkipped,
167 int *optind, int optopt)
168 {
169 char *where; /* Pointer to the letter in optString. */
170 int argWasOK; /* An indication that a required arg was found. */
171  
172 (*optsSkipped)++;
173  
174 if (optopt == ARG_COMING) /* Special case of "-:" */
175 {
176 Error(ERROR_BAD_OPTION, optopt);
177 Pass(argv, optind, optsSkipped);
178 return(UNKNOWN_OPT);
179 }
180  
181 else if (where = index(optString, optopt))
182 {
183 argWasOK = 1; /* Assume any argument will be found. */
184  
185 if (*(where+1) == ARG_COMING)
186 argWasOK = HandleArgument(argv, optind, optsSkipped);
187  
188 Pass(argv, optind, optsSkipped);
189  
190 return(argWasOK ? optopt : UNKNOWN_OPT);
191 }
192  
193 else
194 {
195 Error(ERROR_BAD_OPTION, optopt);
196 Pass(argv, optind, optsSkipped);
197 return(UNKNOWN_OPT);
198 }
199 }
200  
201  
202 /* We have an option in argv[optind] that requires an argument. If there
203 * is no whitespace after the option letter itself, take the rest of
204 * argv[optind] to be the argument.
205 * If there IS whitespace after the option letter, take argv[optind+1] to
206 * be the argument.
207 * Otherwise, if there is NO argument, complain!
208 * Return 1 on success, 0 on error.
209 */
210  
211 static int HandleArgument(char *argv[], int *optind, int *optsSkipped)
212 {
213 int OK;
214  
215 if (argv[*optind][1+(*optsSkipped)])
216 {
217 optarg = argv[*optind] + 1 + (*optsSkipped);
218 OK = 1;
219 }
220 else if (argv[(*optind)+1])
221 {
222 optarg = argv[(*optind)+1];
223 (*optind)++;
224 OK = 1;
225 }
226 else
227 {
228 Error(ERROR_MISSING_ARGUMENT, optopt);
229 OK = 0;
230 }
231  
232 (*optsSkipped) = 0;
233 (*optind)++;
234 return(OK);
235 }
236  
237  
238 /* Print an appropriate error message. */
239  
240 static void Error(int err, int c)
241 {
242 if (opterr)
243 {
244 fprintf(stderr, "-%c: ", c);
245 switch (err)
246 {
247 case ERROR_BAD_OPTION:
248 fprintf(stderr, "Illegal option.\n");
249 break;
250 case ERROR_MISSING_ARGUMENT:
251 fprintf(stderr,
252 "An argument is required, but missing.\n");
253 break;
254 default:
255 fprintf(stderr,
256 "An unknown error occurred.\n");
257 break;
258 }
259 }
260 }
261  
262  
263 /* We have reached the end of argv[optind]... there are no more options
264 * in it to parse. Skip to the next item in argv. */
265  
266 static void Pass(char *argv[], int *optind, int *optsSkipped)
267 {
268 if (argv[*optind]
269 && (argv[*optind][0] == DASH)
270 && (argv[*optind][1+(*optsSkipped)] == '\0'))
271 {
272 (*optind)++;
273 (*optsSkipped) = 0;
274 }
275 }
276  
277 /***************************************************************************
278 * A test program. Compile this file with -DTESTME as an option.
279 ***************************************************************************/
280  
281 #ifdef TESTME
282 main(int argc, char *argv[])
283 {
284 char c;
285 int i;
286  
287 while ((c = getopt(argc, argv, "a:b:cde")) != EOF)
288 {
289 printf("OPTION %c", c);
290 if ((c == 'a') || (c == 'b'))
291 printf(", arg=\"%s\"\n", optarg);
292 else
293 printf("\n");
294 }
295  
296 for (i=optind; i<argc; i++)
297 {
298 printf("Arg %d (argv[%d]): \"%s\"\n",
299 i - optind + 1,
300 i,
301 argv[i]);
302 }
303  
304 exit(0);
305 }
306 #endif