1 /*----------------------------------------------------*- Fundamental -*-
3 Module: getopt() [X/OPEN]
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
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.
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
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
47 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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 -*-
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" */
86 #include <stdio.h> /* for EOF and (optionally) fprintf() */
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)
97 # define ERROR(pname, s, ch) \
100 fprintf(stderr, "%s: %s -- '%c'\n", pname, (s), (ch)); \
104 # define ERROR(pname, s, c) do { \
107 extern int write(int, char *, unsigned); \
109 extern int write(); \
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)); \
119 #endif /* USE_STDIO */
122 /*----------------------------------------------------------------------
126 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
128 int getopt(argc
, argv
, optstring
)
133 static char *ap
= (char *) 0;
137 optarg
= (char *) 0; /* Presume no-argument option */
139 if (optind
>= argc
) { /* Reached end of argv[] */
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
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) {
162 if (*ap
!= '-') { /* Doesn't begin with '-' -- not an option */
167 ap
++; /* Examine second character */
169 if (*ap
== '\0') { /* String was "-" -- not an option */
174 if (*ap
== '-' && *(ap
+1) == '\0') { /* String is "--" -- n.a.o. */
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.
196 if (ch
== ':' || (vp
= strchr(optstring
, ch
)) == (char *) 0) {
197 ERROR(argv
[0], "illegal option", ch
);
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.
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
);
218 optarg
= argv
[optind
];
233 /*----------------------------------------------------------------------
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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
250 char *opts
= "abcd:g0%";
255 fprintf(stderr
, "optstring = '%s'\n", opts
);
257 while ( (c
= getopt(argc
, argv
, opts
)) != EOF
) {
260 fprintf(stderr
, "getopt() returned unknown character (0x%x)\n", c
);
264 fprintf(stderr
, "getopt() returned '?' -- error detected\n");
273 fprintf(stderr
, "getopt() returned option letter %c\n", c
);
277 fprintf(stderr
, "getopt() returned option letter %c\n", c
);
278 fprintf(stderr
, "option value is '%s'\n", optarg
);
284 fprintf(stderr
, "end of option list detected\n");
286 fprintf(stderr
, "remaining arguments are:\n");
287 for ( ; optind
<argc
; optind
++) {
288 fprintf(stderr
, "argv[%d] = '%s'\n", optind
, argv
[optind
]);