1 /* $NetBSD: getopt_long.c,v 1.3 2007/06/19 20:44:28 ginsbach Exp $ */
4 * Copyright (c) 2007 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
39 #define SKIPWS(p) while (isspace(*p)) p++
43 main(int argc
, char *argv
[])
45 size_t len
, lineno
= 0;
46 char *line
, *eptr
, *longopt
, *ptr
, *optstring
= NULL
, *result
= NULL
;
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) {
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) {
68 for (i
= 0; i
< nlongopts
; i
++)
69 if (longopts
[i
].name
!= NULL
)
70 free(__UNCONST(longopts
[i
].name
));
76 ptr
= strtok(&line
[10], WS
);
78 errx(1, "missing longopts at line %ld",
79 (unsigned long)lineno
);
80 maxnlongopts
= strtoul(ptr
, &eptr
, 10);
82 warnx("garbage in longopts at line %ld",
83 (unsigned long)lineno
);
84 maxnlongopts
++; /* space for trailer */
86 (struct option
*)calloc(sizeof(struct option
),
90 longopt_flags
= (int *)calloc(sizeof(int), maxnlongopts
);
91 if (longopt_flags
== NULL
)
93 } else if (strncmp(line
, "longopt:", 8) == 0) {
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
);
103 longopt
= strsep(&ptr
, ",");
105 errx(1, "missing longopt at line %ld",
106 (unsigned long)lineno
);
107 longopts
[nlongopts
].name
= strdup(longopt
);
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
;
122 errx(1, "unknown has_arg %s at line %ld",
123 longopt
, (unsigned long)lineno
);
127 longopt
= strsep(&ptr
, ",");
128 if (*longopt
!= '\0' &&
129 strncmp(longopt
, "NULL", 4) != 0)
130 longopts
[nlongopts
].flag
= &longopt_flags
[nlongopts
];
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);
141 errx(1, "invalid val at line %ld",
142 (unsigned long)lineno
);
144 longopts
[nlongopts
].val
= (int)longopt
[1];
146 } else if (strncmp(line
, "args:", 5) == 0) {
147 for (; nargs
>= 0; nargs
--) {
148 if (args
[nargs
] != NULL
)
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) {
161 optind
= optreset
= 1;
164 result
= strtok(&line
[8], WS
);
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
);
174 errx(1, "result: without args");
176 while ((c
= getopt_long(nargs
, args
, optstring
,
177 longopts
, &li
)) != -1) {
179 errx(1, "`:' found as argument char");
181 ptr
= strchr(optstring
, c
);
183 snprintf(arg
, sizeof(arg
),
189 snprintf(arg
, sizeof(arg
),
192 snprintf(arg
, sizeof(arg
),
193 "%c=%s,", c
, optarg
);
195 switch (longopts
[li
].has_arg
) {
197 snprintf(arg
, sizeof(arg
), "-%s,",
200 case required_argument
:
201 snprintf(arg
, sizeof(arg
),
203 longopts
[li
].name
, optarg
);
205 case optional_argument
:
206 snprintf(arg
, sizeof(arg
),
210 (optarg
)? optarg
: "");
213 errx(1, "internal error");
227 snprintf(arg
, sizeof(arg
), "%d", nargs
- optind
);
229 if (strcmp(buf
, result
) != 0)
230 errx(1, "`%s' != `%s'", buf
, result
);
232 errx(1, "unknown directive at line %ld",
233 (unsigned long)lineno
);