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