Sync usage with man page.
[netbsd-mini2440.git] / regress / lib / libc / stdlib / getopt_long / getopt_long.c
blob5d861a4cb2733562575da5b872fc01759a889460
1 /* $NetBSD: getopt_long.c,v 1.3 2007/06/19 20:44:28 ginsbach Exp $ */
3 /*-
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <err.h>
33 #include <getopt.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <unistd.h>
39 #define SKIPWS(p) while (isspace(*p)) p++
40 #define WS "\t\n "
42 int
43 main(int argc, char *argv[])
45 size_t len, lineno = 0;
46 char *line, *eptr, *longopt, *ptr, *optstring = NULL, *result = NULL;
47 char buf[1024];
48 char *args[128];
49 char arg[256];
50 int nargs = -1;
51 int c;
52 int nlongopts, maxnlongopts;
53 int *longopt_flags = NULL;
54 struct option *longopts = NULL;
56 while ((line = fparseln(stdin, &len, &lineno, NULL, 0)) != NULL) {
57 if (strncmp(line, "optstring:", 10) == 0) {
58 if (optstring)
59 free(optstring);
60 optstring = strtok(&line[11], WS);
61 if (optstring == NULL)
62 errx(1, "missing optstring at line %ld",
63 (unsigned long)lineno);
64 optstring = strdup(optstring);
65 } else if (strncmp(line, "longopts:", 9) == 0) {
66 if (longopts) {
67 int i;
68 for (i = 0; i < nlongopts; i++)
69 if (longopts[i].name != NULL)
70 free(__UNCONST(longopts[i].name));
71 free(longopts);
73 if (longopt_flags)
74 free(longopt_flags);
75 nlongopts = 0;
76 ptr = strtok(&line[10], WS);
77 if (ptr == NULL)
78 errx(1, "missing longopts at line %ld",
79 (unsigned long)lineno);
80 maxnlongopts = strtoul(ptr, &eptr, 10);
81 if (*eptr != '\0')
82 warnx("garbage in longopts at line %ld",
83 (unsigned long)lineno);
84 maxnlongopts++; /* space for trailer */
85 longopts =
86 (struct option *)calloc(sizeof(struct option),
87 maxnlongopts);
88 if (longopts == NULL)
89 err(1, "calloc");
90 longopt_flags = (int *)calloc(sizeof(int), maxnlongopts);
91 if (longopt_flags == NULL)
92 err(1, "calloc");
93 } else if (strncmp(line, "longopt:", 8) == 0) {
94 if (longopts == NULL)
95 errx(1, "longopt: without longopts at line %ld",
96 (unsigned long)lineno);
97 if (nlongopts >= maxnlongopts)
98 errx(1, "longopt: too many options at line %ld",
99 (unsigned long)lineno);
100 /* name */
101 ptr = &line[9];
102 SKIPWS(ptr);
103 longopt = strsep(&ptr, ",");
104 if (longopt == NULL)
105 errx(1, "missing longopt at line %ld",
106 (unsigned long)lineno);
107 longopts[nlongopts].name = strdup(longopt);
108 /* has_arg */
109 SKIPWS(ptr);
110 longopt = strsep(&ptr, ",");
111 if (*longopt != '\0') {
112 if (strncmp(longopt, "0", 1) == 0 ||
113 strncmp(longopt, "no_argument", 2) == 0)
114 longopts[nlongopts].has_arg = no_argument;
115 else if (strncmp(longopt, "1", 1) == 0 ||
116 strncmp(longopt, "required_argument", 8) == 0)
117 longopts[nlongopts].has_arg = required_argument;
118 else if (strncmp(longopt, "2", 1) == 0 ||
119 strncmp(longopt, "optional_argument", 8) == 0)
120 longopts[nlongopts].has_arg = optional_argument;
121 else
122 errx(1, "unknown has_arg %s at line %ld",
123 longopt, (unsigned long)lineno);
125 /* flag */
126 SKIPWS(ptr);
127 longopt = strsep(&ptr, ",");
128 if (*longopt != '\0' &&
129 strncmp(longopt, "NULL", 4) != 0)
130 longopts[nlongopts].flag = &longopt_flags[nlongopts];
131 /* val */
132 SKIPWS(ptr);
133 longopt = strsep(&ptr, ",");
134 if (*longopt == '\0')
135 errx(1, "missing val at line %ld",
136 (unsigned long)lineno);
137 if (*longopt != '\'') {
138 longopts[nlongopts].val =
139 (int)strtoul(longopt, &eptr, 10);
140 if (*eptr != '\0')
141 errx(1, "invalid val at line %ld",
142 (unsigned long)lineno);
143 } else
144 longopts[nlongopts].val = (int)longopt[1];
145 nlongopts++;
146 } else if (strncmp(line, "args:", 5) == 0) {
147 for (; nargs >= 0; nargs--) {
148 if (args[nargs] != NULL)
149 free(args[nargs]);
151 args[nargs = 0] = strtok(&line[6], WS);
152 if (args[nargs] == NULL)
153 errx(1, "Missing args");
155 args[nargs] = strdup(args[nargs]);
156 while ((args[++nargs] = strtok(NULL, WS)) != NULL)
157 args[nargs] = strdup(args[nargs]);
158 } else if (strncmp(line, "result:", 7) == 0) {
159 int li;
160 buf[0] = '\0';
161 optind = optreset = 1;
162 if (result)
163 free(result);
164 result = strtok(&line[8], WS);
165 if (result == NULL)
166 errx(1, "missing result at line %ld",
167 (unsigned long)lineno);
168 if (optstring == NULL)
169 errx(1, "result: without optstring");
170 if (longopts == NULL || nlongopts == 0)
171 errx(1, "result: without longopts");
172 result = strdup(result);
173 if (nargs == -1)
174 errx(1, "result: without args");
175 li = -2;
176 while ((c = getopt_long(nargs, args, optstring,
177 longopts, &li)) != -1) {
178 if (c == ':')
179 errx(1, "`:' found as argument char");
180 if (li == -2) {
181 ptr = strchr(optstring, c);
182 if (ptr == NULL) {
183 snprintf(arg, sizeof(arg),
184 "!%c,", c);
185 strcat(buf, arg);
186 continue;
188 if (ptr[1] != ':')
189 snprintf(arg, sizeof(arg),
190 "%c,", c);
191 else
192 snprintf(arg, sizeof(arg),
193 "%c=%s,", c, optarg);
194 } else {
195 switch (longopts[li].has_arg) {
196 case no_argument:
197 snprintf(arg, sizeof(arg), "-%s,",
198 longopts[li].name);
199 break;
200 case required_argument:
201 snprintf(arg, sizeof(arg),
202 "-%s=%s,",
203 longopts[li].name, optarg);
204 break;
205 case optional_argument:
206 snprintf(arg, sizeof(arg),
207 "-%s%s%s,",
208 longopts[li].name,
209 (optarg)? "=" : "",
210 (optarg)? optarg : "");
211 break;
212 default:
213 errx(1, "internal error");
216 strcat(buf, arg);
217 li = -2;
219 len = strlen(buf);
220 if (len > 0) {
221 buf[len - 1] = '|';
222 buf[len] = '\0';
223 } else {
224 buf[0] = '|';
225 buf[1] = '\0';
227 snprintf(arg, sizeof(arg), "%d", nargs - optind);
228 strcat(buf, arg);
229 if (strcmp(buf, result) != 0)
230 errx(1, "`%s' != `%s'", buf, result);
231 } else
232 errx(1, "unknown directive at line %ld",
233 (unsigned long)lineno);
234 free(line);
236 return 0;