HuntnGather – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /****************************************************************************
2 * getopt(): Return the next user option on each iteration.
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  
67 #ifndef __STDIO_H /* If we haven't already included stdio.h, do it. */
68 # include <stdio.h> /* Maybe someday I'll eliminate this. */
69 #endif
70  
71 #ifndef __STRING_H
72 # include <string.h> /* For index() */
73 #endif
74  
75 /************************************************************************
76 * Some constants.
77 ************************************************************************/
78  
79 #define DASH '-' /* This preceeds an option. */
80 #define ARG_COMING ':' /* In the option string, this indicates that
81 * that the option requires an argument. */
82 #define UNKNOWN_OPT '?' /* The char returned for unknown option. */
83  
84 /************************************************************************
85 * Internal error codes.
86 ************************************************************************/
87  
88 #define ERROR_BAD_OPTION 1
89 #define ERROR_MISSING_ARGUMENT 2
90  
91 /************************************************************************
92 * ANSI function prototypes.
93 ************************************************************************/
94  
95 int getopt(int argc, char *argv[], char *optString);
96 static int NextOption(char *argv[], char *optString);
97 static int RealOption(char *argv[], char *str, int *skip, int *ind,
98 int opt);
99 static int HandleArgument(char *argv[], int *optind, int *skip);
100 static void Error(int err, int c);
101 static void Pass(char *argv[], int *optind, int *optsSkipped);
102  
103 /************************************************************************
104 * Global variables. You must declare these externs in your program
105 * if you want to see their values!
106 ************************************************************************/
107  
108 char *optarg = NULL; /* This will point to a required argument, if any. */
109 int optind = 1; /* The index of the next argument in argv. */
110 int opterr = 1; /* 1 == print internal error messages. 0 else. */
111 int optopt; /* The actual option letter that was found. */
112  
113  
114 int getopt(int argc, char *argv[], char *optString)
115 {
116 optarg = NULL;
117 if (optind < argc) /* More arguments to check. */
118 return(NextOption(argv, optString));
119 else /* We're done. */
120 return(EOF);
121 }
122  
123  
124 /* If the current argument does not begin with DASH, it is not an option.
125 * Return EOF.
126 * If we have ONLY a DASH, and nothing after it... return EOF as well.
127 * If we have a DASH followed immediately by another DASH, this is the
128 * special "--" option that means "no more options follow." Return EOF.
129 * Otherwise, we have an actual option or list of options. Process it. */
130  
131 static int NextOption(char *argv[], char *optString)
132 {
133 static int optsSkipped = 0; /* In a single argv[i]. */
134  
135 if ((argv[optind][0] == DASH)
136 && ((optopt = argv[optind][1+optsSkipped]) != '\0'))
137 {
138 if (optopt == DASH)
139 {
140 optind++;
141 return(EOF);
142 }
143 else
144 return(RealOption(argv, optString, &optsSkipped,
145 &optind, optopt));
146 }
147 else
148 return(EOF);
149 }
150  
151  
152 /* At this point, we know that argv[optind] is an option or list of
153 * options. If this is a list of options, *optsSkipped tells us how
154 * many of those options have ALREADY been parsed on previous calls
155 * to getopt().
156 * If the option is not legal (not in optString), complain and return
157 * UNKNOWN_OPT.
158 * If the option requires no argument, just return the option letter.
159 * If the option requires an argument, call HandleArgument and return
160 * the option letter. */
161  
162 static int RealOption(char *argv[], char *optString, int *optsSkipped,
163 int *optind, int optopt)
164 {
165 char *where; /* Pointer to the letter in optString. */
166 int argWasOK; /* An indication that a required arg was found. */
167  
168 (*optsSkipped)++;
169  
170 if (optopt == ARG_COMING) /* Special case of "-:" */
171 {
172 Error(ERROR_BAD_OPTION, optopt);
173 Pass(argv, optind, optsSkipped);
174 return(UNKNOWN_OPT);
175 }
176  
177 else if (where = index(optString, optopt))
178 {
179 argWasOK = 1; /* Assume any argument will be found. */
180  
181 if (*(where+1) == ARG_COMING)
182 argWasOK = HandleArgument(argv, optind, optsSkipped);
183  
184 Pass(argv, optind, optsSkipped);
185  
186 return(argWasOK ? optopt : UNKNOWN_OPT);
187 }
188  
189 else
190 {
191 Error(ERROR_BAD_OPTION, optopt);
192 Pass(argv, optind, optsSkipped);
193 return(UNKNOWN_OPT);
194 }
195 }
196  
197  
198 /* We have an option in argv[optind] that requires an argument. If there
199 * is no whitespace after the option letter itself, take the rest of
200 * argv[optind] to be the argument.
201 * If there IS whitespace after the option letter, take argv[optind+1] to
202 * be the argument.
203 * Otherwise, if there is NO argument, complain!
204 * Return 1 on success, 0 on error.
205 */
206  
207 static int HandleArgument(char *argv[], int *optind, int *optsSkipped)
208 {
209 int OK;
210  
211 if (argv[*optind][1+(*optsSkipped)])
212 {
213 optarg = argv[*optind] + 1 + (*optsSkipped);
214 OK = 1;
215 }
216 else if (argv[(*optind)+1])
217 {
218 optarg = argv[(*optind)+1];
219 (*optind)++;
220 OK = 1;
221 }
222 else
223 {
224 Error(ERROR_MISSING_ARGUMENT, optopt);
225 OK = 0;
226 }
227  
228 (*optsSkipped) = 0;
229 (*optind)++;
230 return(OK);
231 }
232  
233  
234 /* Print an appropriate error message. */
235  
236 static void Error(int err, int c)
237 {
238 if (opterr)
239 {
240 fprintf(stderr, "-%c: ", c);
241 switch (err)
242 {
243 case ERROR_BAD_OPTION:
244 fprintf(stderr, "Illegal option.\n");
245 break;
246 case ERROR_MISSING_ARGUMENT:
247 fprintf(stderr,
248 "An argument is required, but missing.\n");
249 break;
250 default:
251 fprintf(stderr,
252 "An unknown error occurred.\n");
253 break;
254 }
255 }
256 }
257  
258  
259 /* We have reached the end of argv[optind]... there are no more options
260 * in it to parse. Skip to the next item in argv. */
261  
262 static void Pass(char *argv[], int *optind, int *optsSkipped)
263 {
264 if (argv[*optind]
265 && (argv[*optind][0] == DASH)
266 && (argv[*optind][1+(*optsSkipped)] == '\0'))
267 {
268 (*optind)++;
269 (*optsSkipped) = 0;
270 }
271 }
272  
273 /***************************************************************************
274 * A test program. Compile this file with -DTESTME as an option.
275 ***************************************************************************/
276  
277 #ifdef TESTME
278 main(int argc, char *argv[])
279 {
280 char c;
281 int i;
282  
283 while ((c = getopt(argc, argv, "a:b:cde")) != EOF)
284 {
285 printf("OPTION %c", c);
286 if ((c == 'a') || (c == 'b'))
287 printf(", arg=\"%s\"\n", optarg);
288 else
289 printf("\n");
290 }
291  
292 for (i=optind; i<argc; i++)
293 {
294 printf("Arg %d (argv[%d]): \"%s\"\n",
295 i - optind + 1,
296 i,
297 argv[i]);
298 }
299  
300 exit(0);
301 }
302 #endif