1 /* $NetBSD: h_getopt_long.c,v 1.1 2011/01/01 23:56:49 pgoyette 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.
40 #define SKIPWS(p) while (isspace((int)(*p))) p++
44 main(int argc
, char *argv
[])
46 size_t len
, lineno
= 0;
47 char *line
, *eptr
, *longopt
, *ptr
, *optstring
= NULL
, *result
= NULL
;
55 int *longopt_flags
= NULL
;
56 struct option
*longopts
= NULL
;
58 while ((line
= fparseln(stdin
, &len
, &lineno
, NULL
, 0)) != NULL
) {
59 if (strncmp(line
, "optstring:", 10) == 0) {
62 optstring
= strtok(&line
[11], WS
);
63 if (optstring
== NULL
)
64 errx(1, "missing optstring at line %ld",
65 (unsigned long)lineno
);
66 optstring
= strdup(optstring
);
67 } else if (strncmp(line
, "longopts:", 9) == 0) {
70 for (i
= 0; i
< nlongopts
; i
++)
71 if (longopts
[i
].name
!= NULL
)
72 free(__UNCONST(longopts
[i
].name
));
78 ptr
= strtok(&line
[10], WS
);
80 errx(1, "missing longopts at line %ld",
81 (unsigned long)lineno
);
82 maxnlongopts
= strtoul(ptr
, &eptr
, 10);
84 warnx("garbage in longopts at line %ld",
85 (unsigned long)lineno
);
86 maxnlongopts
++; /* space for trailer */
88 (struct option
*)calloc(sizeof(struct option
),
92 longopt_flags
= (int *)calloc(sizeof(int), maxnlongopts
);
93 if (longopt_flags
== NULL
)
95 } else if (strncmp(line
, "longopt:", 8) == 0) {
97 errx(1, "longopt: without longopts at line %ld",
98 (unsigned long)lineno
);
99 if (nlongopts
>= maxnlongopts
)
100 errx(1, "longopt: too many options at line %ld",
101 (unsigned long)lineno
);
105 longopt
= strsep(&ptr
, ",");
107 errx(1, "missing longopt at line %ld",
108 (unsigned long)lineno
);
109 longopts
[nlongopts
].name
= strdup(longopt
);
112 longopt
= strsep(&ptr
, ",");
113 if (*longopt
!= '\0') {
114 if (strncmp(longopt
, "0", 1) == 0 ||
115 strncmp(longopt
, "no_argument", 2) == 0)
116 longopts
[nlongopts
].has_arg
= no_argument
;
117 else if (strncmp(longopt
, "1", 1) == 0 ||
118 strncmp(longopt
, "required_argument", 8) == 0)
119 longopts
[nlongopts
].has_arg
= required_argument
;
120 else if (strncmp(longopt
, "2", 1) == 0 ||
121 strncmp(longopt
, "optional_argument", 8) == 0)
122 longopts
[nlongopts
].has_arg
= optional_argument
;
124 errx(1, "unknown has_arg %s at line %ld",
125 longopt
, (unsigned long)lineno
);
129 longopt
= strsep(&ptr
, ",");
130 if (*longopt
!= '\0' &&
131 strncmp(longopt
, "NULL", 4) != 0)
132 longopts
[nlongopts
].flag
= &longopt_flags
[nlongopts
];
135 longopt
= strsep(&ptr
, ",");
136 if (*longopt
== '\0')
137 errx(1, "missing val at line %ld",
138 (unsigned long)lineno
);
139 if (*longopt
!= '\'') {
140 longopts
[nlongopts
].val
=
141 (int)strtoul(longopt
, &eptr
, 10);
143 errx(1, "invalid val at line %ld",
144 (unsigned long)lineno
);
146 longopts
[nlongopts
].val
= (int)longopt
[1];
148 } else if (strncmp(line
, "args:", 5) == 0) {
149 for (; nargs
>= 0; nargs
--) {
150 if (args
[nargs
] != NULL
)
153 args
[nargs
= 0] = strtok(&line
[6], WS
);
154 if (args
[nargs
] == NULL
)
155 errx(1, "Missing args");
157 args
[nargs
] = strdup(args
[nargs
]);
158 while ((args
[++nargs
] = strtok(NULL
, WS
)) != NULL
)
159 args
[nargs
] = strdup(args
[nargs
]);
160 } else if (strncmp(line
, "result:", 7) == 0) {
163 optind
= optreset
= 1;
166 result
= strtok(&line
[8], WS
);
168 errx(1, "missing result at line %ld",
169 (unsigned long)lineno
);
170 if (optstring
== NULL
)
171 errx(1, "result: without optstring");
172 if (longopts
== NULL
|| nlongopts
== 0)
173 errx(1, "result: without longopts");
174 result
= strdup(result
);
176 errx(1, "result: without args");
178 while ((c
= getopt_long(nargs
, args
, optstring
,
179 longopts
, &li
)) != -1) {
181 errx(1, "`:' found as argument char");
183 ptr
= strchr(optstring
, c
);
185 snprintf(arg
, sizeof(arg
),
191 snprintf(arg
, sizeof(arg
),
194 snprintf(arg
, sizeof(arg
),
195 "%c=%s,", c
, optarg
);
197 switch (longopts
[li
].has_arg
) {
199 snprintf(arg
, sizeof(arg
), "-%s,",
202 case required_argument
:
203 snprintf(arg
, sizeof(arg
),
205 longopts
[li
].name
, optarg
);
207 case optional_argument
:
208 snprintf(arg
, sizeof(arg
),
212 (optarg
)? optarg
: "");
215 errx(1, "internal error");
229 snprintf(arg
, sizeof(arg
), "%d", nargs
- optind
);
231 if (strcmp(buf
, result
) != 0)
232 errx(1, "`%s' != `%s'", buf
, result
);
234 errx(1, "unknown directive at line %ld",
235 (unsigned long)lineno
);