getarg.c revision 1.1 1 1.1 elric /* $NetBSD: getarg.c,v 1.1 2011/04/13 18:15:41 elric Exp $ */
2 1.1 elric
3 1.1 elric /*
4 1.1 elric * Copyright (c) 1997 - 2002 Kungliga Tekniska Hgskolan
5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden).
6 1.1 elric * All rights reserved.
7 1.1 elric *
8 1.1 elric * Redistribution and use in source and binary forms, with or without
9 1.1 elric * modification, are permitted provided that the following conditions
10 1.1 elric * are met:
11 1.1 elric *
12 1.1 elric * 1. Redistributions of source code must retain the above copyright
13 1.1 elric * notice, this list of conditions and the following disclaimer.
14 1.1 elric *
15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 elric * notice, this list of conditions and the following disclaimer in the
17 1.1 elric * documentation and/or other materials provided with the distribution.
18 1.1 elric *
19 1.1 elric * 3. Neither the name of the Institute nor the names of its contributors
20 1.1 elric * may be used to endorse or promote products derived from this software
21 1.1 elric * without specific prior written permission.
22 1.1 elric *
23 1.1 elric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 1.1 elric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 elric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 1.1 elric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 elric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 elric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 elric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 elric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 elric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 elric * SUCH DAMAGE.
34 1.1 elric */
35 1.1 elric
36 1.1 elric #include <config.h>
37 1.1 elric
38 1.1 elric #include <stdio.h>
39 1.1 elric #include <stdlib.h>
40 1.1 elric #include <string.h>
41 1.1 elric #include <krb5/roken.h>
42 1.1 elric #include <krb5/getarg.h>
43 1.1 elric
44 1.1 elric #define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag)
45 1.1 elric
46 1.1 elric static size_t
47 1.1 elric print_arg (char *string,
48 1.1 elric size_t len,
49 1.1 elric int mdoc,
50 1.1 elric int longp,
51 1.1 elric struct getargs *arg,
52 1.1 elric char *(i18n)(const char *))
53 1.1 elric {
54 1.1 elric const char *s;
55 1.1 elric
56 1.1 elric *string = '\0';
57 1.1 elric
58 1.1 elric if (ISFLAG(*arg) || (!longp && arg->type == arg_counter))
59 1.1 elric return 0;
60 1.1 elric
61 1.1 elric if(mdoc){
62 1.1 elric if(longp)
63 1.1 elric strlcat(string, "= Ns", len);
64 1.1 elric strlcat(string, " Ar ", len);
65 1.1 elric } else {
66 1.1 elric if (longp)
67 1.1 elric strlcat (string, "=", len);
68 1.1 elric else
69 1.1 elric strlcat (string, " ", len);
70 1.1 elric }
71 1.1 elric
72 1.1 elric if (arg->arg_help)
73 1.1 elric s = (*i18n)(arg->arg_help);
74 1.1 elric else if (arg->type == arg_integer || arg->type == arg_counter)
75 1.1 elric s = "integer";
76 1.1 elric else if (arg->type == arg_string)
77 1.1 elric s = "string";
78 1.1 elric else if (arg->type == arg_strings)
79 1.1 elric s = "strings";
80 1.1 elric else if (arg->type == arg_double)
81 1.1 elric s = "float";
82 1.1 elric else
83 1.1 elric s = "<undefined>";
84 1.1 elric
85 1.1 elric strlcat(string, s, len);
86 1.1 elric return 1 + strlen(s);
87 1.1 elric }
88 1.1 elric
89 1.1 elric static void
90 1.1 elric mandoc_template(struct getargs *args,
91 1.1 elric size_t num_args,
92 1.1 elric const char *progname,
93 1.1 elric const char *extra_string,
94 1.1 elric char *(i18n)(const char *))
95 1.1 elric {
96 1.1 elric size_t i;
97 1.1 elric char timestr[64], cmd[64];
98 1.1 elric char buf[128];
99 1.1 elric const char *p;
100 1.1 elric time_t t;
101 1.1 elric
102 1.1 elric printf(".\\\" Things to fix:\n");
103 1.1 elric printf(".\\\" * correct section, and operating system\n");
104 1.1 elric printf(".\\\" * remove Op from mandatory flags\n");
105 1.1 elric printf(".\\\" * use better macros for arguments (like .Pa for files)\n");
106 1.1 elric printf(".\\\"\n");
107 1.1 elric t = time(NULL);
108 1.1 elric strftime(timestr, sizeof(timestr), "%B %e, %Y", localtime(&t));
109 1.1 elric printf(".Dd %s\n", timestr);
110 1.1 elric p = strrchr(progname, '/');
111 1.1 elric if(p) p++; else p = progname;
112 1.1 elric strlcpy(cmd, p, sizeof(cmd));
113 1.1 elric strupr(cmd);
114 1.1 elric
115 1.1 elric printf(".Dt %s SECTION\n", cmd);
116 1.1 elric printf(".Os OPERATING_SYSTEM\n");
117 1.1 elric printf(".Sh NAME\n");
118 1.1 elric printf(".Nm %s\n", p);
119 1.1 elric printf(".Nd\n");
120 1.1 elric printf("in search of a description\n");
121 1.1 elric printf(".Sh SYNOPSIS\n");
122 1.1 elric printf(".Nm\n");
123 1.1 elric for(i = 0; i < num_args; i++){
124 1.1 elric /* we seem to hit a limit on number of arguments if doing
125 1.1 elric short and long flags with arguments -- split on two lines */
126 1.1 elric if(ISFLAG(args[i]) ||
127 1.1 elric args[i].short_name == 0 || args[i].long_name == NULL) {
128 1.1 elric printf(".Op ");
129 1.1 elric
130 1.1 elric if(args[i].short_name) {
131 1.1 elric print_arg(buf, sizeof(buf), 1, 0, args + i, i18n);
132 1.1 elric printf("Fl %c%s", args[i].short_name, buf);
133 1.1 elric if(args[i].long_name)
134 1.1 elric printf(" | ");
135 1.1 elric }
136 1.1 elric if(args[i].long_name) {
137 1.1 elric print_arg(buf, sizeof(buf), 1, 1, args + i, i18n);
138 1.1 elric printf("Fl -%s%s%s",
139 1.1 elric args[i].type == arg_negative_flag ? "no-" : "",
140 1.1 elric args[i].long_name, buf);
141 1.1 elric }
142 1.1 elric printf("\n");
143 1.1 elric } else {
144 1.1 elric print_arg(buf, sizeof(buf), 1, 0, args + i, i18n);
145 1.1 elric printf(".Oo Fl %c%s \\*(Ba Xo\n", args[i].short_name, buf);
146 1.1 elric print_arg(buf, sizeof(buf), 1, 1, args + i, i18n);
147 1.1 elric printf(".Fl -%s%s\n.Xc\n.Oc\n", args[i].long_name, buf);
148 1.1 elric }
149 1.1 elric /*
150 1.1 elric if(args[i].type == arg_strings)
151 1.1 elric fprintf (stderr, "...");
152 1.1 elric */
153 1.1 elric }
154 1.1 elric if (extra_string && *extra_string)
155 1.1 elric printf (".Ar %s\n", extra_string);
156 1.1 elric printf(".Sh DESCRIPTION\n");
157 1.1 elric printf("Supported options:\n");
158 1.1 elric printf(".Bl -tag -width Ds\n");
159 1.1 elric for(i = 0; i < num_args; i++){
160 1.1 elric printf(".It Xo\n");
161 1.1 elric if(args[i].short_name){
162 1.1 elric printf(".Fl %c", args[i].short_name);
163 1.1 elric print_arg(buf, sizeof(buf), 1, 0, args + i, i18n);
164 1.1 elric printf("%s", buf);
165 1.1 elric if(args[i].long_name)
166 1.1 elric printf(" ,");
167 1.1 elric printf("\n");
168 1.1 elric }
169 1.1 elric if(args[i].long_name){
170 1.1 elric printf(".Fl -%s%s",
171 1.1 elric args[i].type == arg_negative_flag ? "no-" : "",
172 1.1 elric args[i].long_name);
173 1.1 elric print_arg(buf, sizeof(buf), 1, 1, args + i, i18n);
174 1.1 elric printf("%s\n", buf);
175 1.1 elric }
176 1.1 elric printf(".Xc\n");
177 1.1 elric if(args[i].help)
178 1.1 elric printf("%s\n", args[i].help);
179 1.1 elric /*
180 1.1 elric if(args[i].type == arg_strings)
181 1.1 elric fprintf (stderr, "...");
182 1.1 elric */
183 1.1 elric }
184 1.1 elric printf(".El\n");
185 1.1 elric printf(".\\\".Sh ENVIRONMENT\n");
186 1.1 elric printf(".\\\".Sh FILES\n");
187 1.1 elric printf(".\\\".Sh EXAMPLES\n");
188 1.1 elric printf(".\\\".Sh DIAGNOSTICS\n");
189 1.1 elric printf(".\\\".Sh SEE ALSO\n");
190 1.1 elric printf(".\\\".Sh STANDARDS\n");
191 1.1 elric printf(".\\\".Sh HISTORY\n");
192 1.1 elric printf(".\\\".Sh AUTHORS\n");
193 1.1 elric printf(".\\\".Sh BUGS\n");
194 1.1 elric }
195 1.1 elric
196 1.1 elric static int
197 1.1 elric check_column(FILE *f, int col, int len, int columns)
198 1.1 elric {
199 1.1 elric if(col + len > columns) {
200 1.1 elric fprintf(f, "\n");
201 1.1 elric col = fprintf(f, " ");
202 1.1 elric }
203 1.1 elric return col;
204 1.1 elric }
205 1.1 elric
206 1.1 elric static char *
207 1.1 elric builtin_i18n(const char *str)
208 1.1 elric {
209 1.1 elric return rk_UNCONST(str);
210 1.1 elric }
211 1.1 elric
212 1.1 elric ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
213 1.1 elric arg_printusage (struct getargs *args,
214 1.1 elric size_t num_args,
215 1.1 elric const char *progname,
216 1.1 elric const char *extra_string)
217 1.1 elric {
218 1.1 elric arg_printusage_i18n(args, num_args, "Usage",
219 1.1 elric progname, extra_string, builtin_i18n);
220 1.1 elric }
221 1.1 elric
222 1.1 elric ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
223 1.1 elric arg_printusage_i18n (struct getargs *args,
224 1.1 elric size_t num_args,
225 1.1 elric const char *usage,
226 1.1 elric const char *progname,
227 1.1 elric const char *extra_string,
228 1.1 elric char *(*i18n)(const char *))
229 1.1 elric {
230 1.1 elric size_t i, max_len = 0;
231 1.1 elric char buf[128];
232 1.1 elric int col = 0, columns;
233 1.1 elric struct winsize ws;
234 1.1 elric
235 1.1 elric if (progname == NULL)
236 1.1 elric progname = getprogname();
237 1.1 elric
238 1.1 elric if (i18n == NULL)
239 1.1 elric i18n = builtin_i18n;
240 1.1 elric
241 1.1 elric if(getenv("GETARGMANDOC")){
242 1.1 elric mandoc_template(args, num_args, progname, extra_string, i18n);
243 1.1 elric return;
244 1.1 elric }
245 1.1 elric if(get_window_size(2, &ws) == 0)
246 1.1 elric columns = ws.ws_col;
247 1.1 elric else
248 1.1 elric columns = 80;
249 1.1 elric col = 0;
250 1.1 elric col += fprintf (stderr, "%s: %s", usage, progname);
251 1.1 elric buf[0] = '\0';
252 1.1 elric for (i = 0; i < num_args; ++i) {
253 1.1 elric if(args[i].short_name && ISFLAG(args[i])) {
254 1.1 elric char s[2];
255 1.1 elric if(buf[0] == '\0')
256 1.1 elric strlcpy(buf, "[-", sizeof(buf));
257 1.1 elric s[0] = args[i].short_name;
258 1.1 elric s[1] = '\0';
259 1.1 elric strlcat(buf, s, sizeof(buf));
260 1.1 elric }
261 1.1 elric }
262 1.1 elric if(buf[0] != '\0') {
263 1.1 elric strlcat(buf, "]", sizeof(buf));
264 1.1 elric col = check_column(stderr, col, strlen(buf) + 1, columns);
265 1.1 elric col += fprintf(stderr, " %s", buf);
266 1.1 elric }
267 1.1 elric
268 1.1 elric for (i = 0; i < num_args; ++i) {
269 1.1 elric size_t len = 0;
270 1.1 elric
271 1.1 elric if (args[i].long_name) {
272 1.1 elric buf[0] = '\0';
273 1.1 elric strlcat(buf, "[--", sizeof(buf));
274 1.1 elric len += 2;
275 1.1 elric if(args[i].type == arg_negative_flag) {
276 1.1 elric strlcat(buf, "no-", sizeof(buf));
277 1.1 elric len += 3;
278 1.1 elric }
279 1.1 elric strlcat(buf, args[i].long_name, sizeof(buf));
280 1.1 elric len += strlen(args[i].long_name);
281 1.1 elric len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf),
282 1.1 elric 0, 1, &args[i], i18n);
283 1.1 elric strlcat(buf, "]", sizeof(buf));
284 1.1 elric if(args[i].type == arg_strings)
285 1.1 elric strlcat(buf, "...", sizeof(buf));
286 1.1 elric col = check_column(stderr, col, strlen(buf) + 1, columns);
287 1.1 elric col += fprintf(stderr, " %s", buf);
288 1.1 elric }
289 1.1 elric if (args[i].short_name && !ISFLAG(args[i])) {
290 1.1 elric snprintf(buf, sizeof(buf), "[-%c", args[i].short_name);
291 1.1 elric len += 2;
292 1.1 elric len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf),
293 1.1 elric 0, 0, &args[i], i18n);
294 1.1 elric strlcat(buf, "]", sizeof(buf));
295 1.1 elric if(args[i].type == arg_strings)
296 1.1 elric strlcat(buf, "...", sizeof(buf));
297 1.1 elric col = check_column(stderr, col, strlen(buf) + 1, columns);
298 1.1 elric col += fprintf(stderr, " %s", buf);
299 1.1 elric }
300 1.1 elric if (args[i].long_name && args[i].short_name)
301 1.1 elric len += 2; /* ", " */
302 1.1 elric max_len = max(max_len, len);
303 1.1 elric }
304 1.1 elric if (extra_string) {
305 1.1 elric check_column(stderr, col, strlen(extra_string) + 1, columns);
306 1.1 elric fprintf (stderr, " %s\n", extra_string);
307 1.1 elric } else
308 1.1 elric fprintf (stderr, "\n");
309 1.1 elric for (i = 0; i < num_args; ++i) {
310 1.1 elric if (args[i].help) {
311 1.1 elric size_t count = 0;
312 1.1 elric
313 1.1 elric if (args[i].short_name) {
314 1.1 elric count += fprintf (stderr, "-%c", args[i].short_name);
315 1.1 elric print_arg (buf, sizeof(buf), 0, 0, &args[i], i18n);
316 1.1 elric count += fprintf(stderr, "%s", buf);
317 1.1 elric }
318 1.1 elric if (args[i].short_name && args[i].long_name)
319 1.1 elric count += fprintf (stderr, ", ");
320 1.1 elric if (args[i].long_name) {
321 1.1 elric count += fprintf (stderr, "--");
322 1.1 elric if (args[i].type == arg_negative_flag)
323 1.1 elric count += fprintf (stderr, "no-");
324 1.1 elric count += fprintf (stderr, "%s", args[i].long_name);
325 1.1 elric print_arg (buf, sizeof(buf), 0, 1, &args[i], i18n);
326 1.1 elric count += fprintf(stderr, "%s", buf);
327 1.1 elric }
328 1.1 elric while(count++ <= max_len)
329 1.1 elric putc (' ', stderr);
330 1.1 elric fprintf (stderr, "%s\n", (*i18n)(args[i].help));
331 1.1 elric }
332 1.1 elric }
333 1.1 elric }
334 1.1 elric
335 1.1 elric static int
336 1.1 elric add_string(getarg_strings *s, char *value)
337 1.1 elric {
338 1.1 elric char **strings;
339 1.1 elric
340 1.1 elric strings = realloc(s->strings, (s->num_strings + 1) * sizeof(*s->strings));
341 1.1 elric if (strings == NULL) {
342 1.1 elric free(s->strings);
343 1.1 elric s->strings = NULL;
344 1.1 elric s->num_strings = 0;
345 1.1 elric return ENOMEM;
346 1.1 elric }
347 1.1 elric s->strings = strings;
348 1.1 elric s->strings[s->num_strings] = value;
349 1.1 elric s->num_strings++;
350 1.1 elric return 0;
351 1.1 elric }
352 1.1 elric
353 1.1 elric static int
354 1.1 elric arg_match_long(struct getargs *args, size_t num_args,
355 1.1 elric char *argv, int argc, char **rargv, int *goptind)
356 1.1 elric {
357 1.1 elric int i;
358 1.1 elric char *goptarg = NULL;
359 1.1 elric int negate = 0;
360 1.1 elric int partial_match = 0;
361 1.1 elric struct getargs *partial = NULL;
362 1.1 elric struct getargs *current = NULL;
363 1.1 elric int argv_len;
364 1.1 elric char *p;
365 1.1 elric int p_len;
366 1.1 elric
367 1.1 elric argv_len = strlen(argv);
368 1.1 elric p = strchr (argv, '=');
369 1.1 elric if (p != NULL)
370 1.1 elric argv_len = p - argv;
371 1.1 elric
372 1.1 elric for (i = 0; i < num_args; ++i) {
373 1.1 elric if(args[i].long_name) {
374 1.1 elric int len = strlen(args[i].long_name);
375 1.1 elric p = argv;
376 1.1 elric p_len = argv_len;
377 1.1 elric negate = 0;
378 1.1 elric
379 1.1 elric for (;;) {
380 1.1 elric if (strncmp (args[i].long_name, p, p_len) == 0) {
381 1.1 elric if(p_len == len)
382 1.1 elric current = &args[i];
383 1.1 elric else {
384 1.1 elric ++partial_match;
385 1.1 elric partial = &args[i];
386 1.1 elric }
387 1.1 elric goptarg = p + p_len;
388 1.1 elric } else if (ISFLAG(args[i]) && strncmp (p, "no-", 3) == 0) {
389 1.1 elric negate = !negate;
390 1.1 elric p += 3;
391 1.1 elric p_len -= 3;
392 1.1 elric continue;
393 1.1 elric }
394 1.1 elric break;
395 1.1 elric }
396 1.1 elric if (current)
397 1.1 elric break;
398 1.1 elric }
399 1.1 elric }
400 1.1 elric if (current == NULL) {
401 1.1 elric if (partial_match == 1)
402 1.1 elric current = partial;
403 1.1 elric else
404 1.1 elric return ARG_ERR_NO_MATCH;
405 1.1 elric }
406 1.1 elric
407 1.1 elric if(*goptarg == '\0'
408 1.1 elric && !ISFLAG(*current)
409 1.1 elric && current->type != arg_collect
410 1.1 elric && current->type != arg_counter)
411 1.1 elric return ARG_ERR_NO_MATCH;
412 1.1 elric switch(current->type){
413 1.1 elric case arg_integer:
414 1.1 elric {
415 1.1 elric int tmp;
416 1.1 elric if(sscanf(goptarg + 1, "%d", &tmp) != 1)
417 1.1 elric return ARG_ERR_BAD_ARG;
418 1.1 elric *(int*)current->value = tmp;
419 1.1 elric return 0;
420 1.1 elric }
421 1.1 elric case arg_string:
422 1.1 elric {
423 1.1 elric *(char**)current->value = goptarg + 1;
424 1.1 elric return 0;
425 1.1 elric }
426 1.1 elric case arg_strings:
427 1.1 elric {
428 1.1 elric return add_string((getarg_strings*)current->value, goptarg + 1);
429 1.1 elric }
430 1.1 elric case arg_flag:
431 1.1 elric case arg_negative_flag:
432 1.1 elric {
433 1.1 elric int *flag = current->value;
434 1.1 elric if(*goptarg == '\0' ||
435 1.1 elric strcmp(goptarg + 1, "yes") == 0 ||
436 1.1 elric strcmp(goptarg + 1, "true") == 0){
437 1.1 elric *flag = !negate;
438 1.1 elric return 0;
439 1.1 elric } else if (*goptarg && strcmp(goptarg + 1, "maybe") == 0) {
440 1.1 elric *flag = rk_random() & 1;
441 1.1 elric } else {
442 1.1 elric *flag = negate;
443 1.1 elric return 0;
444 1.1 elric }
445 1.1 elric return ARG_ERR_BAD_ARG;
446 1.1 elric }
447 1.1 elric case arg_counter :
448 1.1 elric {
449 1.1 elric int val;
450 1.1 elric
451 1.1 elric if (*goptarg == '\0')
452 1.1 elric val = 1;
453 1.1 elric else if(sscanf(goptarg + 1, "%d", &val) != 1)
454 1.1 elric return ARG_ERR_BAD_ARG;
455 1.1 elric *(int *)current->value += val;
456 1.1 elric return 0;
457 1.1 elric }
458 1.1 elric case arg_double:
459 1.1 elric {
460 1.1 elric double tmp;
461 1.1 elric if(sscanf(goptarg + 1, "%lf", &tmp) != 1)
462 1.1 elric return ARG_ERR_BAD_ARG;
463 1.1 elric *(double*)current->value = tmp;
464 1.1 elric return 0;
465 1.1 elric }
466 1.1 elric case arg_collect:{
467 1.1 elric struct getarg_collect_info *c = current->value;
468 1.1 elric int o = argv - rargv[*goptind];
469 1.1 elric return (*c->func)(FALSE, argc, rargv, goptind, &o, c->data);
470 1.1 elric }
471 1.1 elric
472 1.1 elric default:
473 1.1 elric abort ();
474 1.1 elric UNREACHABLE(return 0);
475 1.1 elric }
476 1.1 elric }
477 1.1 elric
478 1.1 elric static int
479 1.1 elric arg_match_short (struct getargs *args, size_t num_args,
480 1.1 elric char *argv, int argc, char **rargv, int *goptind)
481 1.1 elric {
482 1.1 elric int j, k;
483 1.1 elric
484 1.1 elric for(j = 1; j > 0 && j < strlen(rargv[*goptind]); j++) {
485 1.1 elric for(k = 0; k < num_args; k++) {
486 1.1 elric char *goptarg;
487 1.1 elric
488 1.1 elric if(args[k].short_name == 0)
489 1.1 elric continue;
490 1.1 elric if(argv[j] == args[k].short_name) {
491 1.1 elric if(args[k].type == arg_flag) {
492 1.1 elric *(int*)args[k].value = 1;
493 1.1 elric break;
494 1.1 elric }
495 1.1 elric if(args[k].type == arg_negative_flag) {
496 1.1 elric *(int*)args[k].value = 0;
497 1.1 elric break;
498 1.1 elric }
499 1.1 elric if(args[k].type == arg_counter) {
500 1.1 elric ++*(int *)args[k].value;
501 1.1 elric break;
502 1.1 elric }
503 1.1 elric if(args[k].type == arg_collect) {
504 1.1 elric struct getarg_collect_info *c = args[k].value;
505 1.1 elric
506 1.1 elric if((*c->func)(TRUE, argc, rargv, goptind, &j, c->data))
507 1.1 elric return ARG_ERR_BAD_ARG;
508 1.1 elric break;
509 1.1 elric }
510 1.1 elric
511 1.1 elric if(argv[j + 1])
512 1.1 elric goptarg = &argv[j + 1];
513 1.1 elric else {
514 1.1 elric ++*goptind;
515 1.1 elric goptarg = rargv[*goptind];
516 1.1 elric }
517 1.1 elric if(goptarg == NULL) {
518 1.1 elric --*goptind;
519 1.1 elric return ARG_ERR_NO_ARG;
520 1.1 elric }
521 1.1 elric if(args[k].type == arg_integer) {
522 1.1 elric int tmp;
523 1.1 elric if(sscanf(goptarg, "%d", &tmp) != 1)
524 1.1 elric return ARG_ERR_BAD_ARG;
525 1.1 elric *(int*)args[k].value = tmp;
526 1.1 elric return 0;
527 1.1 elric } else if(args[k].type == arg_string) {
528 1.1 elric *(char**)args[k].value = goptarg;
529 1.1 elric return 0;
530 1.1 elric } else if(args[k].type == arg_strings) {
531 1.1 elric return add_string((getarg_strings*)args[k].value, goptarg);
532 1.1 elric } else if(args[k].type == arg_double) {
533 1.1 elric double tmp;
534 1.1 elric if(sscanf(goptarg, "%lf", &tmp) != 1)
535 1.1 elric return ARG_ERR_BAD_ARG;
536 1.1 elric *(double*)args[k].value = tmp;
537 1.1 elric return 0;
538 1.1 elric }
539 1.1 elric return ARG_ERR_BAD_ARG;
540 1.1 elric }
541 1.1 elric }
542 1.1 elric if (k == num_args)
543 1.1 elric return ARG_ERR_NO_MATCH;
544 1.1 elric }
545 1.1 elric return 0;
546 1.1 elric }
547 1.1 elric
548 1.1 elric ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
549 1.1 elric getarg(struct getargs *args, size_t num_args,
550 1.1 elric int argc, char **argv, int *goptind)
551 1.1 elric {
552 1.1 elric int i;
553 1.1 elric int ret = 0;
554 1.1 elric
555 1.1 elric rk_random_init();
556 1.1 elric (*goptind)++;
557 1.1 elric for(i = *goptind; i < argc; i++) {
558 1.1 elric if(argv[i][0] != '-')
559 1.1 elric break;
560 1.1 elric if(argv[i][1] == '-'){
561 1.1 elric if(argv[i][2] == 0){
562 1.1 elric i++;
563 1.1 elric break;
564 1.1 elric }
565 1.1 elric ret = arg_match_long (args, num_args, argv[i] + 2,
566 1.1 elric argc, argv, &i);
567 1.1 elric } else {
568 1.1 elric ret = arg_match_short (args, num_args, argv[i],
569 1.1 elric argc, argv, &i);
570 1.1 elric }
571 1.1 elric if(ret)
572 1.1 elric break;
573 1.1 elric }
574 1.1 elric *goptind = i;
575 1.1 elric return ret;
576 1.1 elric }
577 1.1 elric
578 1.1 elric ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
579 1.1 elric free_getarg_strings (getarg_strings *s)
580 1.1 elric {
581 1.1 elric free (s->strings);
582 1.1 elric }
583 1.1 elric
584 1.1 elric #if TEST
585 1.1 elric int foo_flag = 2;
586 1.1 elric int flag1 = 0;
587 1.1 elric int flag2 = 0;
588 1.1 elric int bar_int;
589 1.1 elric char *baz_string;
590 1.1 elric
591 1.1 elric struct getargs args[] = {
592 1.1 elric { NULL, '1', arg_flag, &flag1, "one", NULL },
593 1.1 elric { NULL, '2', arg_flag, &flag2, "two", NULL },
594 1.1 elric { "foo", 'f', arg_negative_flag, &foo_flag, "foo", NULL },
595 1.1 elric { "bar", 'b', arg_integer, &bar_int, "bar", "seconds"},
596 1.1 elric { "baz", 'x', arg_string, &baz_string, "baz", "name" },
597 1.1 elric };
598 1.1 elric
599 1.1 elric int main(int argc, char **argv)
600 1.1 elric {
601 1.1 elric int goptind = 0;
602 1.1 elric while(getarg(args, 5, argc, argv, &goptind))
603 1.1 elric printf("Bad arg: %s\n", argv[goptind]);
604 1.1 elric printf("flag1 = %d\n", flag1);
605 1.1 elric printf("flag2 = %d\n", flag2);
606 1.1 elric printf("foo_flag = %d\n", foo_flag);
607 1.1 elric printf("bar_int = %d\n", bar_int);
608 1.1 elric printf("baz_flag = %s\n", baz_string);
609 1.1 elric arg_printusage (args, 5, argv[0], "nothing here");
610 1.1 elric }
611 1.1 elric #endif
612