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(int argc
, char * const argv
[], const char *optstring
)
130 static char *ap
= (char *) 0;
134 optarg
= (char *) 0; /* Presume no-argument option */
136 if (optind
>= argc
) { /* Reached end of argv[] */
141 * ap points into argv[optind], and is used to keep track of how far
142 * we have parsed the current option string. Remember that an argv[]
143 * string may contain several separate option letters (e.g. the line
144 * 'foo -abc -x -y' contains five option letters, but only three
147 * If ap == 0, we have reached a new string. Check that it *is* a
148 * legal option, that is:
150 * + check that the first character is '-'
151 * + check that the string isn't "-"
152 * + check that the string isn't "--"
156 if (ap
== (char *) 0) {
159 if (*ap
!= '-') { /* Doesn't begin with '-' -- not an option */
164 ap
++; /* Examine second character */
166 if (*ap
== '\0') { /* String was "-" -- not an option */
171 if (*ap
== '-' && *(ap
+1) == '\0') { /* String is "--" -- n.a.o. */
179 * At this point we know that the string appears to be an option string.
180 * Check that the current character really is one of those specified in
181 * 'optstring' (remember, ':' is NOT a permissible option character, as
182 * it is used in optstring to specify that the option takes an argument).
184 * Also note that strchr() treats the terminating NUL character as a part
185 * of the string -- hence strchr() always finds NUL in optstring. The
186 * routine relies on ch never taking the value NUL.
193 if (ch
== ':' || (vp
= strchr(optstring
, ch
)) == (char *) 0) {
194 ERROR(argv
[0], "illegal option", ch
);
200 * ch is a permissible option letter, and vp points to it in optstring.
201 * If it takes an argument, that is it is followed by ':' in optstring,
202 * extract the argument, and set optarg to point to it. If not, just
203 * return the option letter.
209 if (optarg
== (char *) 0) { /* option value might be in next argument */
210 if (optind
>= argc
) { /* No, it wasn't */
211 ERROR(argv
[0], "option requires an argument", ch
);
215 optarg
= argv
[optind
];
230 /*----------------------------------------------------------------------
234 Description: This routine provides confidence testing of the
235 getopt() routine. It is rather crude at present. A
236 better way of doing things would be to build argument
237 structures in memory, sending them to getopt(), and
238 check that the returned values are as expected.
240 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
247 char *opts
= "abcd:g0%";
252 fprintf(stderr
, "optstring = '%s'\n", opts
);
254 while ( (c
= getopt(argc
, argv
, opts
)) != EOF
) {
257 fprintf(stderr
, "getopt() returned unknown character (0x%x)\n", c
);
261 fprintf(stderr
, "getopt() returned '?' -- error detected\n");
270 fprintf(stderr
, "getopt() returned option letter %c\n", c
);
274 fprintf(stderr
, "getopt() returned option letter %c\n", c
);
275 fprintf(stderr
, "option value is '%s'\n", optarg
);
281 fprintf(stderr
, "end of option list detected\n");
283 fprintf(stderr
, "remaining arguments are:\n");
284 for ( ; optind
<argc
; optind
++) {
285 fprintf(stderr
, "argv[%d] = '%s'\n", optind
, argv
[optind
]);