getarg.c revision 1.5 1 1.5 christos /* $NetBSD: getarg.c,v 1.5 2017/01/29 19:23:28 christos 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.5 christos #include <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.3 pettai printf(".Nd in search of a description\n");
120 1.1 elric printf(".Sh SYNOPSIS\n");
121 1.1 elric printf(".Nm\n");
122 1.1 elric for(i = 0; i < num_args; i++){
123 1.1 elric /* we seem to hit a limit on number of arguments if doing
124 1.1 elric short and long flags with arguments -- split on two lines */
125 1.1 elric if(ISFLAG(args[i]) ||
126 1.1 elric args[i].short_name == 0 || args[i].long_name == NULL) {
127 1.1 elric printf(".Op ");
128 1.1 elric
129 1.1 elric if(args[i].short_name) {
130 1.1 elric print_arg(buf, sizeof(buf), 1, 0, args + i, i18n);
131 1.1 elric printf("Fl %c%s", args[i].short_name, buf);
132 1.1 elric if(args[i].long_name)
133 1.1 elric printf(" | ");
134 1.1 elric }
135 1.1 elric if(args[i].long_name) {
136 1.1 elric print_arg(buf, sizeof(buf), 1, 1, args + i, i18n);
137 1.3 pettai printf("Fl Fl %s%s%s",
138 1.1 elric args[i].type == arg_negative_flag ? "no-" : "",
139 1.1 elric args[i].long_name, buf);
140 1.1 elric }
141 1.1 elric printf("\n");
142 1.1 elric } else {
143 1.1 elric print_arg(buf, sizeof(buf), 1, 0, args + i, i18n);
144 1.1 elric printf(".Oo Fl %c%s \\*(Ba Xo\n", args[i].short_name, buf);
145 1.1 elric print_arg(buf, sizeof(buf), 1, 1, args + i, i18n);
146 1.3 pettai printf(".Fl Fl %s%s\n.Xc\n.Oc\n", args[i].long_name, buf);
147 1.1 elric }
148 1.1 elric /*
149 1.1 elric if(args[i].type == arg_strings)
150 1.1 elric fprintf (stderr, "...");
151 1.1 elric */
152 1.1 elric }
153 1.1 elric if (extra_string && *extra_string)
154 1.1 elric printf (".Ar %s\n", extra_string);
155 1.1 elric printf(".Sh DESCRIPTION\n");
156 1.1 elric printf("Supported options:\n");
157 1.1 elric printf(".Bl -tag -width Ds\n");
158 1.1 elric for(i = 0; i < num_args; i++){
159 1.1 elric printf(".It Xo\n");
160 1.1 elric if(args[i].short_name){
161 1.1 elric printf(".Fl %c", args[i].short_name);
162 1.1 elric print_arg(buf, sizeof(buf), 1, 0, args + i, i18n);
163 1.1 elric printf("%s", buf);
164 1.1 elric if(args[i].long_name)
165 1.1 elric printf(" ,");
166 1.1 elric printf("\n");
167 1.1 elric }
168 1.1 elric if(args[i].long_name){
169 1.3 pettai printf(".Fl Fl %s%s",
170 1.1 elric args[i].type == arg_negative_flag ? "no-" : "",
171 1.1 elric args[i].long_name);
172 1.1 elric print_arg(buf, sizeof(buf), 1, 1, args + i, i18n);
173 1.1 elric printf("%s\n", buf);
174 1.1 elric }
175 1.1 elric printf(".Xc\n");
176 1.1 elric if(args[i].help)
177 1.1 elric printf("%s\n", args[i].help);
178 1.1 elric /*
179 1.1 elric if(args[i].type == arg_strings)
180 1.1 elric fprintf (stderr, "...");
181 1.1 elric */
182 1.1 elric }
183 1.1 elric printf(".El\n");
184 1.1 elric printf(".\\\".Sh ENVIRONMENT\n");
185 1.1 elric printf(".\\\".Sh FILES\n");
186 1.1 elric printf(".\\\".Sh EXAMPLES\n");
187 1.1 elric printf(".\\\".Sh DIAGNOSTICS\n");
188 1.1 elric printf(".\\\".Sh SEE ALSO\n");
189 1.1 elric printf(".\\\".Sh STANDARDS\n");
190 1.1 elric printf(".\\\".Sh HISTORY\n");
191 1.1 elric printf(".\\\".Sh AUTHORS\n");
192 1.1 elric printf(".\\\".Sh BUGS\n");
193 1.1 elric }
194 1.1 elric
195 1.1 elric static int
196 1.1 elric check_column(FILE *f, int col, int len, int columns)
197 1.1 elric {
198 1.1 elric if(col + len > columns) {
199 1.1 elric fprintf(f, "\n");
200 1.1 elric col = fprintf(f, " ");
201 1.1 elric }
202 1.1 elric return col;
203 1.1 elric }
204 1.1 elric
205 1.1 elric static char *
206 1.1 elric builtin_i18n(const char *str)
207 1.1 elric {
208 1.1 elric return rk_UNCONST(str);
209 1.1 elric }
210 1.1 elric
211 1.1 elric ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
212 1.1 elric arg_printusage (struct getargs *args,
213 1.1 elric size_t num_args,
214 1.1 elric const char *progname,
215 1.1 elric const char *extra_string)
216 1.1 elric {
217 1.1 elric arg_printusage_i18n(args, num_args, "Usage",
218 1.1 elric progname, extra_string, builtin_i18n);
219 1.1 elric }
220 1.1 elric
221 1.1 elric ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
222 1.1 elric arg_printusage_i18n (struct getargs *args,
223 1.1 elric size_t num_args,
224 1.1 elric const char *usage,
225 1.1 elric const char *progname,
226 1.1 elric const char *extra_string,
227 1.1 elric char *(*i18n)(const char *))
228 1.1 elric {
229 1.1 elric size_t i, max_len = 0;
230 1.1 elric char buf[128];
231 1.1 elric int col = 0, columns;
232 1.1 elric
233 1.1 elric if (progname == NULL)
234 1.1 elric progname = getprogname();
235 1.1 elric
236 1.1 elric if (i18n == NULL)
237 1.1 elric i18n = builtin_i18n;
238 1.1 elric
239 1.1 elric if(getenv("GETARGMANDOC")){
240 1.1 elric mandoc_template(args, num_args, progname, extra_string, i18n);
241 1.1 elric return;
242 1.1 elric }
243 1.2 elric if(get_window_size(2, NULL, &columns) == -1)
244 1.1 elric columns = 80;
245 1.1 elric col = 0;
246 1.1 elric col += fprintf (stderr, "%s: %s", usage, progname);
247 1.1 elric buf[0] = '\0';
248 1.1 elric for (i = 0; i < num_args; ++i) {
249 1.1 elric if(args[i].short_name && ISFLAG(args[i])) {
250 1.1 elric char s[2];
251 1.1 elric if(buf[0] == '\0')
252 1.1 elric strlcpy(buf, "[-", sizeof(buf));
253 1.1 elric s[0] = args[i].short_name;
254 1.1 elric s[1] = '\0';
255 1.1 elric strlcat(buf, s, sizeof(buf));
256 1.1 elric }
257 1.1 elric }
258 1.1 elric if(buf[0] != '\0') {
259 1.1 elric strlcat(buf, "]", sizeof(buf));
260 1.1 elric col = check_column(stderr, col, strlen(buf) + 1, columns);
261 1.1 elric col += fprintf(stderr, " %s", buf);
262 1.1 elric }
263 1.1 elric
264 1.1 elric for (i = 0; i < num_args; ++i) {
265 1.1 elric size_t len = 0;
266 1.1 elric
267 1.1 elric if (args[i].long_name) {
268 1.1 elric buf[0] = '\0';
269 1.1 elric strlcat(buf, "[--", sizeof(buf));
270 1.1 elric len += 2;
271 1.1 elric if(args[i].type == arg_negative_flag) {
272 1.1 elric strlcat(buf, "no-", sizeof(buf));
273 1.1 elric len += 3;
274 1.1 elric }
275 1.1 elric strlcat(buf, args[i].long_name, sizeof(buf));
276 1.1 elric len += strlen(args[i].long_name);
277 1.1 elric len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf),
278 1.1 elric 0, 1, &args[i], i18n);
279 1.1 elric strlcat(buf, "]", sizeof(buf));
280 1.1 elric if(args[i].type == arg_strings)
281 1.1 elric strlcat(buf, "...", sizeof(buf));
282 1.1 elric col = check_column(stderr, col, strlen(buf) + 1, columns);
283 1.1 elric col += fprintf(stderr, " %s", buf);
284 1.1 elric }
285 1.1 elric if (args[i].short_name && !ISFLAG(args[i])) {
286 1.1 elric snprintf(buf, sizeof(buf), "[-%c", args[i].short_name);
287 1.1 elric len += 2;
288 1.1 elric len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf),
289 1.1 elric 0, 0, &args[i], i18n);
290 1.1 elric strlcat(buf, "]", sizeof(buf));
291 1.1 elric if(args[i].type == arg_strings)
292 1.1 elric strlcat(buf, "...", sizeof(buf));
293 1.1 elric col = check_column(stderr, col, strlen(buf) + 1, columns);
294 1.1 elric col += fprintf(stderr, " %s", buf);
295 1.1 elric }
296 1.1 elric if (args[i].long_name && args[i].short_name)
297 1.1 elric len += 2; /* ", " */
298 1.1 elric max_len = max(max_len, len);
299 1.1 elric }
300 1.1 elric if (extra_string) {
301 1.1 elric check_column(stderr, col, strlen(extra_string) + 1, columns);
302 1.1 elric fprintf (stderr, " %s\n", extra_string);
303 1.1 elric } else
304 1.1 elric fprintf (stderr, "\n");
305 1.1 elric for (i = 0; i < num_args; ++i) {
306 1.1 elric if (args[i].help) {
307 1.1 elric size_t count = 0;
308 1.1 elric
309 1.1 elric if (args[i].short_name) {
310 1.1 elric count += fprintf (stderr, "-%c", args[i].short_name);
311 1.1 elric print_arg (buf, sizeof(buf), 0, 0, &args[i], i18n);
312 1.1 elric count += fprintf(stderr, "%s", buf);
313 1.1 elric }
314 1.1 elric if (args[i].short_name && args[i].long_name)
315 1.1 elric count += fprintf (stderr, ", ");
316 1.1 elric if (args[i].long_name) {
317 1.1 elric count += fprintf (stderr, "--");
318 1.1 elric if (args[i].type == arg_negative_flag)
319 1.1 elric count += fprintf (stderr, "no-");
320 1.1 elric count += fprintf (stderr, "%s", args[i].long_name);
321 1.1 elric print_arg (buf, sizeof(buf), 0, 1, &args[i], i18n);
322 1.1 elric count += fprintf(stderr, "%s", buf);
323 1.1 elric }
324 1.1 elric while(count++ <= max_len)
325 1.1 elric putc (' ', stderr);
326 1.1 elric fprintf (stderr, "%s\n", (*i18n)(args[i].help));
327 1.1 elric }
328 1.1 elric }
329 1.1 elric }
330 1.1 elric
331 1.1 elric static int
332 1.1 elric add_string(getarg_strings *s, char *value)
333 1.1 elric {
334 1.1 elric char **strings;
335 1.1 elric
336 1.1 elric strings = realloc(s->strings, (s->num_strings + 1) * sizeof(*s->strings));
337 1.1 elric if (strings == NULL) {
338 1.1 elric free(s->strings);
339 1.1 elric s->strings = NULL;
340 1.1 elric s->num_strings = 0;
341 1.1 elric return ENOMEM;
342 1.1 elric }
343 1.1 elric s->strings = strings;
344 1.1 elric s->strings[s->num_strings] = value;
345 1.1 elric s->num_strings++;
346 1.1 elric return 0;
347 1.1 elric }
348 1.1 elric
349 1.1 elric static int
350 1.1 elric arg_match_long(struct getargs *args, size_t num_args,
351 1.1 elric char *argv, int argc, char **rargv, int *goptind)
352 1.1 elric {
353 1.3 pettai size_t i;
354 1.1 elric char *goptarg = NULL;
355 1.1 elric int negate = 0;
356 1.1 elric int partial_match = 0;
357 1.1 elric struct getargs *partial = NULL;
358 1.1 elric struct getargs *current = NULL;
359 1.1 elric int argv_len;
360 1.1 elric char *p;
361 1.1 elric int p_len;
362 1.1 elric
363 1.1 elric argv_len = strlen(argv);
364 1.1 elric p = strchr (argv, '=');
365 1.1 elric if (p != NULL)
366 1.1 elric argv_len = p - argv;
367 1.1 elric
368 1.1 elric for (i = 0; i < num_args; ++i) {
369 1.1 elric if(args[i].long_name) {
370 1.1 elric int len = strlen(args[i].long_name);
371 1.1 elric p = argv;
372 1.1 elric p_len = argv_len;
373 1.1 elric negate = 0;
374 1.1 elric
375 1.1 elric for (;;) {
376 1.1 elric if (strncmp (args[i].long_name, p, p_len) == 0) {
377 1.1 elric if(p_len == len)
378 1.1 elric current = &args[i];
379 1.1 elric else {
380 1.1 elric ++partial_match;
381 1.1 elric partial = &args[i];
382 1.1 elric }
383 1.1 elric goptarg = p + p_len;
384 1.1 elric } else if (ISFLAG(args[i]) && strncmp (p, "no-", 3) == 0) {
385 1.1 elric negate = !negate;
386 1.1 elric p += 3;
387 1.1 elric p_len -= 3;
388 1.1 elric continue;
389 1.1 elric }
390 1.1 elric break;
391 1.1 elric }
392 1.1 elric if (current)
393 1.1 elric break;
394 1.1 elric }
395 1.1 elric }
396 1.1 elric if (current == NULL) {
397 1.1 elric if (partial_match == 1)
398 1.1 elric current = partial;
399 1.1 elric else
400 1.1 elric return ARG_ERR_NO_MATCH;
401 1.1 elric }
402 1.1 elric
403 1.1 elric if(*goptarg == '\0'
404 1.1 elric && !ISFLAG(*current)
405 1.1 elric && current->type != arg_collect
406 1.1 elric && current->type != arg_counter)
407 1.1 elric return ARG_ERR_NO_MATCH;
408 1.1 elric switch(current->type){
409 1.1 elric case arg_integer:
410 1.1 elric {
411 1.1 elric int tmp;
412 1.1 elric if(sscanf(goptarg + 1, "%d", &tmp) != 1)
413 1.1 elric return ARG_ERR_BAD_ARG;
414 1.1 elric *(int*)current->value = tmp;
415 1.1 elric return 0;
416 1.1 elric }
417 1.1 elric case arg_string:
418 1.1 elric {
419 1.1 elric *(char**)current->value = goptarg + 1;
420 1.1 elric return 0;
421 1.1 elric }
422 1.1 elric case arg_strings:
423 1.1 elric {
424 1.1 elric return add_string((getarg_strings*)current->value, goptarg + 1);
425 1.1 elric }
426 1.1 elric case arg_flag:
427 1.1 elric case arg_negative_flag:
428 1.1 elric {
429 1.1 elric int *flag = current->value;
430 1.1 elric if(*goptarg == '\0' ||
431 1.1 elric strcmp(goptarg + 1, "yes") == 0 ||
432 1.1 elric strcmp(goptarg + 1, "true") == 0){
433 1.1 elric *flag = !negate;
434 1.1 elric return 0;
435 1.1 elric } else if (*goptarg && strcmp(goptarg + 1, "maybe") == 0) {
436 1.1 elric *flag = rk_random() & 1;
437 1.1 elric } else {
438 1.1 elric *flag = negate;
439 1.1 elric return 0;
440 1.1 elric }
441 1.1 elric return ARG_ERR_BAD_ARG;
442 1.1 elric }
443 1.1 elric case arg_counter :
444 1.1 elric {
445 1.1 elric int val;
446 1.1 elric
447 1.1 elric if (*goptarg == '\0')
448 1.1 elric val = 1;
449 1.1 elric else if(sscanf(goptarg + 1, "%d", &val) != 1)
450 1.1 elric return ARG_ERR_BAD_ARG;
451 1.1 elric *(int *)current->value += val;
452 1.1 elric return 0;
453 1.1 elric }
454 1.1 elric case arg_double:
455 1.1 elric {
456 1.1 elric double tmp;
457 1.1 elric if(sscanf(goptarg + 1, "%lf", &tmp) != 1)
458 1.1 elric return ARG_ERR_BAD_ARG;
459 1.1 elric *(double*)current->value = tmp;
460 1.1 elric return 0;
461 1.1 elric }
462 1.1 elric case arg_collect:{
463 1.1 elric struct getarg_collect_info *c = current->value;
464 1.1 elric int o = argv - rargv[*goptind];
465 1.1 elric return (*c->func)(FALSE, argc, rargv, goptind, &o, c->data);
466 1.1 elric }
467 1.1 elric
468 1.1 elric default:
469 1.1 elric abort ();
470 1.1 elric UNREACHABLE(return 0);
471 1.1 elric }
472 1.1 elric }
473 1.1 elric
474 1.1 elric static int
475 1.1 elric arg_match_short (struct getargs *args, size_t num_args,
476 1.1 elric char *argv, int argc, char **rargv, int *goptind)
477 1.1 elric {
478 1.3 pettai size_t j, k;
479 1.1 elric
480 1.1 elric for(j = 1; j > 0 && j < strlen(rargv[*goptind]); j++) {
481 1.1 elric for(k = 0; k < num_args; k++) {
482 1.1 elric char *goptarg;
483 1.1 elric
484 1.1 elric if(args[k].short_name == 0)
485 1.1 elric continue;
486 1.1 elric if(argv[j] == args[k].short_name) {
487 1.1 elric if(args[k].type == arg_flag) {
488 1.1 elric *(int*)args[k].value = 1;
489 1.1 elric break;
490 1.1 elric }
491 1.1 elric if(args[k].type == arg_negative_flag) {
492 1.1 elric *(int*)args[k].value = 0;
493 1.1 elric break;
494 1.1 elric }
495 1.1 elric if(args[k].type == arg_counter) {
496 1.1 elric ++*(int *)args[k].value;
497 1.1 elric break;
498 1.1 elric }
499 1.1 elric if(args[k].type == arg_collect) {
500 1.1 elric struct getarg_collect_info *c = args[k].value;
501 1.3 pettai int a = (int)j;
502 1.1 elric
503 1.3 pettai if((*c->func)(TRUE, argc, rargv, goptind, &a, c->data))
504 1.1 elric return ARG_ERR_BAD_ARG;
505 1.3 pettai j = a;
506 1.1 elric break;
507 1.1 elric }
508 1.1 elric
509 1.1 elric if(argv[j + 1])
510 1.1 elric goptarg = &argv[j + 1];
511 1.1 elric else {
512 1.1 elric ++*goptind;
513 1.1 elric goptarg = rargv[*goptind];
514 1.1 elric }
515 1.1 elric if(goptarg == NULL) {
516 1.1 elric --*goptind;
517 1.1 elric return ARG_ERR_NO_ARG;
518 1.1 elric }
519 1.1 elric if(args[k].type == arg_integer) {
520 1.1 elric int tmp;
521 1.1 elric if(sscanf(goptarg, "%d", &tmp) != 1)
522 1.1 elric return ARG_ERR_BAD_ARG;
523 1.1 elric *(int*)args[k].value = tmp;
524 1.1 elric return 0;
525 1.1 elric } else if(args[k].type == arg_string) {
526 1.1 elric *(char**)args[k].value = goptarg;
527 1.1 elric return 0;
528 1.1 elric } else if(args[k].type == arg_strings) {
529 1.1 elric return add_string((getarg_strings*)args[k].value, goptarg);
530 1.1 elric } else if(args[k].type == arg_double) {
531 1.1 elric double tmp;
532 1.1 elric if(sscanf(goptarg, "%lf", &tmp) != 1)
533 1.1 elric return ARG_ERR_BAD_ARG;
534 1.1 elric *(double*)args[k].value = tmp;
535 1.1 elric return 0;
536 1.1 elric }
537 1.1 elric return ARG_ERR_BAD_ARG;
538 1.1 elric }
539 1.1 elric }
540 1.1 elric if (k == num_args)
541 1.1 elric return ARG_ERR_NO_MATCH;
542 1.1 elric }
543 1.1 elric return 0;
544 1.1 elric }
545 1.1 elric
546 1.1 elric ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
547 1.1 elric getarg(struct getargs *args, size_t num_args,
548 1.1 elric int argc, char **argv, int *goptind)
549 1.1 elric {
550 1.1 elric int i;
551 1.1 elric int ret = 0;
552 1.1 elric
553 1.1 elric rk_random_init();
554 1.1 elric (*goptind)++;
555 1.1 elric for(i = *goptind; i < argc; i++) {
556 1.1 elric if(argv[i][0] != '-')
557 1.1 elric break;
558 1.1 elric if(argv[i][1] == '-'){
559 1.1 elric if(argv[i][2] == 0){
560 1.1 elric i++;
561 1.1 elric break;
562 1.1 elric }
563 1.1 elric ret = arg_match_long (args, num_args, argv[i] + 2,
564 1.1 elric argc, argv, &i);
565 1.1 elric } else {
566 1.1 elric ret = arg_match_short (args, num_args, argv[i],
567 1.1 elric argc, argv, &i);
568 1.1 elric }
569 1.1 elric if(ret)
570 1.1 elric break;
571 1.1 elric }
572 1.1 elric *goptind = i;
573 1.1 elric return ret;
574 1.1 elric }
575 1.1 elric
576 1.1 elric ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
577 1.1 elric free_getarg_strings (getarg_strings *s)
578 1.1 elric {
579 1.1 elric free (s->strings);
580 1.1 elric }
581 1.1 elric
582 1.1 elric #if TEST
583 1.1 elric int foo_flag = 2;
584 1.1 elric int flag1 = 0;
585 1.1 elric int flag2 = 0;
586 1.1 elric int bar_int;
587 1.1 elric char *baz_string;
588 1.1 elric
589 1.1 elric struct getargs args[] = {
590 1.1 elric { NULL, '1', arg_flag, &flag1, "one", NULL },
591 1.1 elric { NULL, '2', arg_flag, &flag2, "two", NULL },
592 1.1 elric { "foo", 'f', arg_negative_flag, &foo_flag, "foo", NULL },
593 1.1 elric { "bar", 'b', arg_integer, &bar_int, "bar", "seconds"},
594 1.1 elric { "baz", 'x', arg_string, &baz_string, "baz", "name" },
595 1.1 elric };
596 1.1 elric
597 1.1 elric int main(int argc, char **argv)
598 1.1 elric {
599 1.1 elric int goptind = 0;
600 1.4 christos while (getarg(args, 5, argc, argv, &goptind))
601 1.1 elric printf("Bad arg: %s\n", argv[goptind]);
602 1.1 elric printf("flag1 = %d\n", flag1);
603 1.1 elric printf("flag2 = %d\n", flag2);
604 1.1 elric printf("foo_flag = %d\n", foo_flag);
605 1.1 elric printf("bar_int = %d\n", bar_int);
606 1.1 elric printf("baz_flag = %s\n", baz_string);
607 1.1 elric arg_printusage (args, 5, argv[0], "nothing here");
608 1.1 elric }
609 1.1 elric #endif
610