getopt_long.c revision 1.1 1 1.1 mcr /*
2 1.1 mcr * Copyright (c) 1987, 1993, 1994, 1996
3 1.1 mcr * The Regents of the University of California. All rights reserved.
4 1.1 mcr *
5 1.1 mcr * Redistribution and use in source and binary forms, with or without
6 1.1 mcr * modification, are permitted provided that the following conditions
7 1.1 mcr * are met:
8 1.1 mcr * 1. Redistributions of source code must retain the above copyright
9 1.1 mcr * notice, this list of conditions and the following disclaimer.
10 1.1 mcr * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 mcr * notice, this list of conditions and the following disclaimer in the
12 1.1 mcr * documentation and/or other materials provided with the distribution.
13 1.1 mcr * 3. All advertising materials mentioning features or use of this software
14 1.1 mcr * must display the following acknowledgement:
15 1.1 mcr * This product includes software developed by the University of
16 1.1 mcr * California, Berkeley and its contributors.
17 1.1 mcr * 4. Neither the name of the University nor the names of its contributors
18 1.1 mcr * may be used to endorse or promote products derived from this software
19 1.1 mcr * without specific prior written permission.
20 1.1 mcr *
21 1.1 mcr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1 mcr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1 mcr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1 mcr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1 mcr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1 mcr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1 mcr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1 mcr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1 mcr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1 mcr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1 mcr * SUCH DAMAGE.
32 1.1 mcr */
33 1.1 mcr
34 1.1 mcr #include <stdio.h>
35 1.1 mcr #include <stdlib.h>
36 1.1 mcr #include <string.h>
37 1.1 mcr #include <sys/cdefs.h>
38 1.1 mcr #include "getopt.h"
39 1.1 mcr
40 1.1 mcr extern int opterr; /* if error message should be printed */
41 1.1 mcr extern int optind; /* index into parent argv vector */
42 1.1 mcr extern int optopt; /* character checked for validity */
43 1.1 mcr extern int optreset; /* reset getopt */
44 1.1 mcr extern char *optarg; /* argument associated with option */
45 1.1 mcr
46 1.1 mcr static char * __progname __P((char *));
47 1.1 mcr int getopt_internal __P((int, char * const *, const char *));
48 1.1 mcr
49 1.1 mcr static char * __progname(nargv0)
50 1.1 mcr char * nargv0;
51 1.1 mcr {
52 1.1 mcr char * tmp = strrchr(nargv0, '/');
53 1.1 mcr if (tmp) tmp++; else tmp = nargv0;
54 1.1 mcr return(tmp);
55 1.1 mcr }
56 1.1 mcr
57 1.1 mcr #define BADCH (int)'?'
58 1.1 mcr #define BADARG (int)':'
59 1.1 mcr #define EMSG ""
60 1.1 mcr
61 1.1 mcr /*
62 1.1 mcr * getopt --
63 1.1 mcr * Parse argc/argv argument vector.
64 1.1 mcr */
65 1.1 mcr int
66 1.1 mcr getopt_internal(nargc, nargv, ostr)
67 1.1 mcr int nargc;
68 1.1 mcr char * const *nargv;
69 1.1 mcr const char *ostr;
70 1.1 mcr {
71 1.1 mcr static char *place = EMSG; /* option letter processing */
72 1.1 mcr char *oli; /* option letter list index */
73 1.1 mcr
74 1.1 mcr if (optreset || !*place) { /* update scanning pointer */
75 1.1 mcr optreset = 0;
76 1.1 mcr if (optind >= nargc || *(place = nargv[optind]) != '-') {
77 1.1 mcr place = EMSG;
78 1.1 mcr return (-1);
79 1.1 mcr }
80 1.1 mcr if (place[1] && *++place == '-') { /* found "--" */
81 1.1 mcr /* ++optind; */
82 1.1 mcr place = EMSG;
83 1.1 mcr return (-2);
84 1.1 mcr }
85 1.1 mcr } /* option letter okay? */
86 1.1 mcr if ((optopt = (int)*place++) == (int)':' ||
87 1.1 mcr !(oli = strchr(ostr, optopt))) {
88 1.1 mcr /*
89 1.1 mcr * if the user didn't specify '-' as an option,
90 1.1 mcr * assume it means -1.
91 1.1 mcr */
92 1.1 mcr if (optopt == (int)'-')
93 1.1 mcr return (-1);
94 1.1 mcr if (!*place)
95 1.1 mcr ++optind;
96 1.1 mcr if (opterr && *ostr != ':')
97 1.1 mcr (void)fprintf(stderr,
98 1.1 mcr "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
99 1.1 mcr return (BADCH);
100 1.1 mcr }
101 1.1 mcr if (*++oli != ':') { /* don't need argument */
102 1.1 mcr optarg = NULL;
103 1.1 mcr if (!*place)
104 1.1 mcr ++optind;
105 1.1 mcr } else { /* need an argument */
106 1.1 mcr if (*place) /* no white space */
107 1.1 mcr optarg = place;
108 1.1 mcr else if (nargc <= ++optind) { /* no arg */
109 1.1 mcr place = EMSG;
110 1.1 mcr if ((opterr) && (*ostr != ':'))
111 1.1 mcr (void)fprintf(stderr,
112 1.1 mcr "%s: option requires an argument -- %c\n",
113 1.1 mcr __progname(nargv[0]), optopt);
114 1.1 mcr return (BADARG);
115 1.1 mcr } else /* white space */
116 1.1 mcr optarg = nargv[optind];
117 1.1 mcr place = EMSG;
118 1.1 mcr ++optind;
119 1.1 mcr }
120 1.1 mcr return (optopt); /* dump back option letter */
121 1.1 mcr }
122 1.1 mcr
123 1.1 mcr #if 0
124 1.1 mcr /*
125 1.1 mcr * getopt --
126 1.1 mcr * Parse argc/argv argument vector.
127 1.1 mcr */
128 1.1 mcr int
129 1.1 mcr getopt2(nargc, nargv, ostr)
130 1.1 mcr int nargc;
131 1.1 mcr char * const *nargv;
132 1.1 mcr const char *ostr;
133 1.1 mcr {
134 1.1 mcr int retval;
135 1.1 mcr
136 1.1 mcr if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
137 1.1 mcr retval = -1;
138 1.1 mcr ++optind;
139 1.1 mcr }
140 1.1 mcr return(retval);
141 1.1 mcr }
142 1.1 mcr #endif
143 1.1 mcr
144 1.1 mcr /*
145 1.1 mcr * getopt_long --
146 1.1 mcr * Parse argc/argv argument vector.
147 1.1 mcr */
148 1.1 mcr int
149 1.1 mcr getopt_long(nargc, nargv, options, long_options, index)
150 1.1 mcr int nargc;
151 1.1 mcr char ** nargv;
152 1.1 mcr char * options;
153 1.1 mcr struct option * long_options;
154 1.1 mcr int * index;
155 1.1 mcr {
156 1.1 mcr int retval;
157 1.1 mcr
158 1.1 mcr if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
159 1.1 mcr char *current_argv = nargv[optind++] + 2, *has_equal;
160 1.1 mcr int i, current_argv_len, match = -1;
161 1.1 mcr
162 1.1 mcr if (*current_argv == '\0') {
163 1.1 mcr return(-1);
164 1.1 mcr }
165 1.1 mcr if ((has_equal = strchr(current_argv, '=')) != NULL) {
166 1.1 mcr current_argv_len = has_equal - current_argv;
167 1.1 mcr has_equal++;
168 1.1 mcr } else
169 1.1 mcr current_argv_len = strlen(current_argv);
170 1.1 mcr
171 1.1 mcr for (i = 0; long_options[i].name; i++) {
172 1.1 mcr if (strncmp(current_argv, long_options[i].name, current_argv_len))
173 1.1 mcr continue;
174 1.1 mcr
175 1.1 mcr if (strlen(long_options[i].name) == (unsigned)current_argv_len) {
176 1.1 mcr match = i;
177 1.1 mcr break;
178 1.1 mcr }
179 1.1 mcr if (match == -1)
180 1.1 mcr match = i;
181 1.1 mcr }
182 1.1 mcr if (match != -1) {
183 1.1 mcr if (long_options[match].has_arg == required_argument ||
184 1.1 mcr long_options[match].has_arg == optional_argument) {
185 1.1 mcr if (has_equal)
186 1.1 mcr optarg = has_equal;
187 1.1 mcr else
188 1.1 mcr optarg = nargv[optind++];
189 1.1 mcr }
190 1.1 mcr if ((long_options[match].has_arg == required_argument)
191 1.1 mcr && (optarg == NULL)) {
192 1.1 mcr /*
193 1.1 mcr * Missing argument, leading :
194 1.1 mcr * indicates no error should be generated
195 1.1 mcr */
196 1.1 mcr if ((opterr) && (*options != ':'))
197 1.1 mcr (void)fprintf(stderr,
198 1.1 mcr "%s: option requires an argument -- %s\n",
199 1.1 mcr __progname(nargv[0]), current_argv);
200 1.1 mcr return (BADARG);
201 1.1 mcr }
202 1.1 mcr } else { /* No matching argument */
203 1.1 mcr if ((opterr) && (*options != ':'))
204 1.1 mcr (void)fprintf(stderr,
205 1.1 mcr "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
206 1.1 mcr return (BADCH);
207 1.1 mcr }
208 1.1 mcr if (long_options[match].flag) {
209 1.1 mcr *long_options[match].flag = long_options[match].val;
210 1.1 mcr retval = 0;
211 1.1 mcr } else
212 1.1 mcr retval = long_options[match].val;
213 1.1 mcr if (index)
214 1.1 mcr *index = match;
215 1.1 mcr }
216 1.1 mcr return(retval);
217 1.1 mcr }
218 1.1 mcr
219