Build SDL as linklib.
[AROS-Contrib.git] / regina / getopt.c
blobbde34a0919124a65f2229b4a1cebf21be36562b3
1 /*----------------------------------------------------*- Fundamental -*-
3 Module: getopt() [X/OPEN]
5 File: getopt.c
7 Assoc. files: config.h (but see below)
9 Description: This module implements a command line parser. It
10 returns option flags (specified by the user) and
11 associated values (if any) to the calling program.
13 Notes: This module began life as a Pascal routine for Oregon
14 Software's Pascal-2 compiler, and was later rewritten
15 into C.
17 Acknowl.: Some features of the AT&T public domain getopt()
18 released to Usenet have been incorporated:
20 * It is now possible to use syscalls for error
21 messages. I disagree slightly with this: the
22 only reason I can think of is to avoid getting
23 the stdio-package in linkage. getopt() is likely
24 to be used in programs where code size is a minor
25 issue. However, I've made it configurable.
27 Author: Anders Thulin
28 Rydsvagen 288
29 S-582 50 Linkoping
30 SWEDEN
32 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
34 This program/module/routine has been developed as a part of `The Source Code
35 Project', a personal attempt at producing well-written, portable software
36 primarily intended to be executed in the ANSI C and POSIX / X/OPEN Unix
37 environments.
39 The program/module/routine is hereby placed in the public domain, which
40 means that it may be freely copied, sold for profit or for fun, praised or
41 buried as your fancy takes you.
43 Comments on the portability and adaptability of the program/module/routine
44 will be appreciated, and, if they result in modifications, acknowledged in
45 future releases.
47 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49 Edit history :
51 Vers Ed Date By Comments
52 ---- --- ---------- ---------------- -------------------------------
53 1.0 0 1987-12-18 Anders Thulin Initial version
54 1 1988-06-06 Anders Thulin Got a copy of the AT&T public
55 domain getopt(). Changed
56 a few things to the better.
58 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
60 /* #include "config.h" -- included below: */
62 /*----------------------------------------------------*- Fundamental -*-
64 Module: getopt(3c)
66 File: config.h
68 Associated files: getopt.c
70 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
72 /*--- Configuration: ------------------------------------------------
74 getopt() may write error messages to stderr.
76 USE_STDIO == 0 Use write(2, ...) for error messages
77 USE_STDIO == 1 Use fprintf(stderr, ...) for error messages
79 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
81 #define USE_STDIO 1 /* Default is 1 */
83 /* -- end of "config.h" */
85 #include <assert.h>
86 #include <stdio.h> /* for EOF and (optionally) fprintf() */
87 #include <string.h>
89 char *optarg = (char *) 0; /* Points to option argument (if any) */
90 int opterr = 1; /* Enable error reporting */
91 int optind = 1; /* Begin with argv[optind] */
94 #define BUMP(p) (*++p == '\0' ? (optind++, (char *) 0) : p)
96 #if USE_STDIO
97 # define ERROR(pname, s, ch) \
98 do { \
99 if (opterr != 0) { \
100 fprintf(stderr, "%s: %s -- '%c'\n", pname, (s), (ch)); \
102 } while (0)
103 #else
104 # define ERROR(pname, s, c) do { \
105 if (opterr != 0) { \
106 #if __STDC__ != 0 \
107 extern int write(int, char *, unsigned); \
108 #else \
109 extern int write(); \
110 #endif \
111 char errbuf[4]; \
112 errbuf[0] = errbuf[2] = '\''; \
113 errbuf[1] = (c); errbuf[3] = '\0'; \
114 write(2, (pname), strlen(pname)); \
115 write(2, ": " s " -- ", strlen(s)+6); \
116 write(2, errbuf, strlen(errbuf)); \
118 } while (1 == 0)
119 #endif /* USE_STDIO */
122 /*----------------------------------------------------------------------
124 Routine: getopt
126 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
128 int getopt(argc, argv, optstring)
129 int argc;
130 char *argv[];
131 char *optstring;
133 static char *ap = (char *) 0;
134 char *vp;
135 char ch;
137 optarg = (char *) 0; /* Presume no-argument option */
139 if (optind >= argc) { /* Reached end of argv[] */
140 return EOF;
144 * ap points into argv[optind], and is used to keep track of how far
145 * we have parsed the current option string. Remember that an argv[]
146 * string may contain several separate option letters (e.g. the line
147 * 'foo -abc -x -y' contains five option letters, but only three
148 * arguments).
150 * If ap == 0, we have reached a new string. Check that it *is* a
151 * legal option, that is:
153 * + check that the first character is '-'
154 * + check that the string isn't "-"
155 * + check that the string isn't "--"
159 if (ap == (char *) 0) {
160 ap = argv[optind];
162 if (*ap != '-') { /* Doesn't begin with '-' -- not an option */
163 ap = (char *) 0;
164 return EOF;
167 ap++; /* Examine second character */
169 if (*ap == '\0') { /* String was "-" -- not an option */
170 ap = (char *) 0;
171 return EOF;
174 if (*ap == '-' && *(ap+1) == '\0') { /* String is "--" -- n.a.o. */
175 ap = (char *) 0;
176 optind++;
177 return EOF;
182 * At this point we know that the string appears to be an option string.
183 * Check that the current character really is one of those specified in
184 * 'optstring' (remember, ':' is NOT a permissible option character, as
185 * it is used in optstring to specify that the option takes an argument).
187 * Also note that strchr() treats the terminating NUL character as a part
188 * of the string -- hence strchr() always finds NUL in optstring. The
189 * routine relies on ch never taking the value NUL.
193 ch = *ap;
194 assert(ch != '\0');
196 if (ch == ':' || (vp = strchr(optstring, ch)) == (char *) 0) {
197 ERROR(argv[0], "illegal option", ch);
198 ap = BUMP(ap);
199 return '?';
203 * ch is a permissible option letter, and vp points to it in optstring.
204 * If it takes an argument, that is it is followed by ':' in optstring,
205 * extract the argument, and set optarg to point to it. If not, just
206 * return the option letter.
210 if (*++vp == ':') {
211 optarg = BUMP(ap);
212 if (optarg == (char *) 0) { /* option value might be in next argument */
213 if (optind >= argc) { /* No, it wasn't */
214 ERROR(argv[0], "option requires an argument", ch);
215 ch = '?';
217 else {
218 optarg = argv[optind];
221 optind++;
222 ap = (char *) 0;
224 else {
225 ap = BUMP(ap);
228 return ch;
231 #ifdef TEST
233 /*----------------------------------------------------------------------
235 Routine: main()
237 Description: This routine provides confidence testing of the
238 getopt() routine. It is rather crude at present. A
239 better way of doing things would be to build argument
240 structures in memory, sending them to getopt(), and
241 check that the returned values are as expected.
243 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
245 int main(argc, argv)
246 int argc;
247 char *argv[];
249 int c;
250 char *opts = "abcd:g0%";
252 extern char *optarg;
253 extern int optind;
255 fprintf(stderr, "optstring = '%s'\n", opts);
257 while ( (c = getopt(argc, argv, opts)) != EOF) {
258 switch(c) {
259 default :
260 fprintf(stderr, "getopt() returned unknown character (0x%x)\n", c);
261 break;
263 case '?' :
264 fprintf(stderr, "getopt() returned '?' -- error detected\n");
265 break;
267 case 'a' :
268 case 'b' :
269 case 'c' :
270 case 'g' :
271 case '0' :
272 case '%' :
273 fprintf(stderr, "getopt() returned option letter %c\n", c);
274 break;
276 case 'd' :
277 fprintf(stderr, "getopt() returned option letter %c\n", c);
278 fprintf(stderr, "option value is '%s'\n", optarg);
279 break;
284 fprintf(stderr, "end of option list detected\n");
285 if (optind < argc) {
286 fprintf(stderr, "remaining arguments are:\n");
287 for ( ; optind <argc; optind++) {
288 fprintf(stderr, "argv[%d] = '%s'\n", optind, argv[optind]);
292 return 0;
294 #endif