Line data Source code
1 : /*
2 : * Copyright 2008-2009 Katholieke Universiteit Leuven
3 : *
4 : * Use of this software is governed by the MIT license
5 : *
6 : * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 : * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8 : */
9 :
10 : #include <stdio.h>
11 : #include <stdlib.h>
12 : #include <string.h>
13 :
14 : #include <isl/arg.h>
15 : #include <isl/ctx.h>
16 : #include <isl_config.h>
17 :
18 : static struct isl_arg help_arg[] = {
19 : ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")
20 : };
21 :
22 338796 : static void set_default_choice(struct isl_arg *arg, void *opt)
23 : {
24 338796 : if (arg->offset == (size_t) -1)
25 37644 : return;
26 301152 : *(unsigned *)(((char *)opt) + arg->offset) = arg->u.choice.default_value;
27 : }
28 :
29 37644 : static void set_default_flags(struct isl_arg *arg, void *opt)
30 : {
31 37644 : *(unsigned *)(((char *)opt) + arg->offset) = arg->u.flags.default_value;
32 37644 : }
33 :
34 1054032 : static void set_default_bool(struct isl_arg *arg, void *opt)
35 : {
36 1054032 : if (arg->offset == (size_t) -1)
37 0 : return;
38 1054032 : *(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value;
39 : }
40 :
41 0 : static void set_default_child(struct isl_arg *arg, void *opt)
42 : {
43 : void *child;
44 :
45 0 : if (arg->offset == (size_t) -1)
46 0 : child = opt;
47 : else {
48 0 : child = calloc(1, arg->u.child.child->options_size);
49 0 : *(void **)(((char *)opt) + arg->offset) = child;
50 : }
51 :
52 0 : if (child)
53 0 : isl_args_set_defaults(arg->u.child.child, child);
54 0 : }
55 :
56 0 : static void set_default_user(struct isl_arg *arg, void *opt)
57 : {
58 0 : arg->u.user.init(((char *)opt) + arg->offset);
59 0 : }
60 :
61 75288 : static void set_default_int(struct isl_arg *arg, void *opt)
62 : {
63 75288 : *(int *)(((char *)opt) + arg->offset) = arg->u.i.default_value;
64 75288 : }
65 :
66 0 : static void set_default_long(struct isl_arg *arg, void *opt)
67 : {
68 0 : *(long *)(((char *)opt) + arg->offset) = arg->u.l.default_value;
69 0 : }
70 :
71 37644 : static void set_default_ulong(struct isl_arg *arg, void *opt)
72 : {
73 37644 : *(unsigned long *)(((char *)opt) + arg->offset) = arg->u.ul.default_value;
74 37644 : }
75 :
76 37644 : static void set_default_str(struct isl_arg *arg, void *opt)
77 : {
78 37644 : const char *str = NULL;
79 37644 : if (arg->u.str.default_value)
80 37644 : str = strdup(arg->u.str.default_value);
81 37644 : *(const char **)(((char *)opt) + arg->offset) = str;
82 37644 : }
83 :
84 0 : static void set_default_str_list(struct isl_arg *arg, void *opt)
85 : {
86 0 : *(const char ***)(((char *) opt) + arg->offset) = NULL;
87 0 : *(int *)(((char *) opt) + arg->u.str_list.offset_n) = 0;
88 0 : }
89 :
90 37644 : void isl_args_set_defaults(struct isl_args *args, void *opt)
91 : {
92 : int i;
93 :
94 1656336 : for (i = 0; args->args[i].type != isl_arg_end; ++i) {
95 1618692 : switch (args->args[i].type) {
96 : case isl_arg_choice:
97 338796 : set_default_choice(&args->args[i], opt);
98 338796 : break;
99 : case isl_arg_flags:
100 37644 : set_default_flags(&args->args[i], opt);
101 37644 : break;
102 : case isl_arg_bool:
103 1054032 : set_default_bool(&args->args[i], opt);
104 1054032 : break;
105 : case isl_arg_child:
106 0 : set_default_child(&args->args[i], opt);
107 0 : break;
108 : case isl_arg_user:
109 0 : set_default_user(&args->args[i], opt);
110 0 : break;
111 : case isl_arg_int:
112 75288 : set_default_int(&args->args[i], opt);
113 75288 : break;
114 : case isl_arg_long:
115 0 : set_default_long(&args->args[i], opt);
116 0 : break;
117 : case isl_arg_ulong:
118 37644 : set_default_ulong(&args->args[i], opt);
119 37644 : break;
120 : case isl_arg_arg:
121 : case isl_arg_str:
122 37644 : set_default_str(&args->args[i], opt);
123 37644 : break;
124 : case isl_arg_str_list:
125 0 : set_default_str_list(&args->args[i], opt);
126 0 : break;
127 : case isl_arg_alias:
128 : case isl_arg_footer:
129 : case isl_arg_version:
130 : case isl_arg_end:
131 37644 : break;
132 : }
133 : }
134 37644 : }
135 :
136 : static void free_args(struct isl_arg *arg, void *opt);
137 :
138 0 : static void free_child(struct isl_arg *arg, void *opt)
139 : {
140 0 : if (arg->offset == (size_t) -1)
141 0 : free_args(arg->u.child.child->args, opt);
142 : else
143 0 : isl_args_free(arg->u.child.child,
144 0 : *(void **)(((char *)opt) + arg->offset));
145 0 : }
146 :
147 0 : static void free_str_list(struct isl_arg *arg, void *opt)
148 : {
149 : int i;
150 0 : int n = *(int *)(((char *) opt) + arg->u.str_list.offset_n);
151 0 : char **list = *(char ***)(((char *) opt) + arg->offset);
152 :
153 0 : for (i = 0; i < n; ++i)
154 0 : free(list[i]);
155 0 : free(list);
156 0 : }
157 :
158 0 : static void free_user(struct isl_arg *arg, void *opt)
159 : {
160 0 : if (arg->u.user.clear)
161 0 : arg->u.user.clear(((char *)opt) + arg->offset);
162 0 : }
163 :
164 0 : static void free_args(struct isl_arg *arg, void *opt)
165 : {
166 : int i;
167 :
168 0 : for (i = 0; arg[i].type != isl_arg_end; ++i) {
169 0 : switch (arg[i].type) {
170 : case isl_arg_child:
171 0 : free_child(&arg[i], opt);
172 0 : break;
173 : case isl_arg_arg:
174 : case isl_arg_str:
175 0 : free(*(char **)(((char *)opt) + arg[i].offset));
176 0 : break;
177 : case isl_arg_str_list:
178 0 : free_str_list(&arg[i], opt);
179 0 : break;
180 : case isl_arg_user:
181 0 : free_user(&arg[i], opt);
182 0 : break;
183 : case isl_arg_alias:
184 : case isl_arg_bool:
185 : case isl_arg_choice:
186 : case isl_arg_flags:
187 : case isl_arg_int:
188 : case isl_arg_long:
189 : case isl_arg_ulong:
190 : case isl_arg_version:
191 : case isl_arg_footer:
192 : case isl_arg_end:
193 0 : break;
194 : }
195 : }
196 0 : }
197 :
198 0 : void isl_args_free(struct isl_args *args, void *opt)
199 : {
200 0 : if (!opt)
201 0 : return;
202 :
203 0 : free_args(args->args, opt);
204 :
205 0 : free(opt);
206 : }
207 :
208 : /* Data structure for collecting the prefixes of ancestor nodes.
209 : *
210 : * n is the number of prefixes.
211 : * prefix[i] for i < n is a prefix of an ancestor.
212 : * len[i] for i < n is the length of prefix[i].
213 : */
214 : struct isl_prefixes {
215 : int n;
216 : const char *prefix[10];
217 : size_t len[10];
218 : };
219 :
220 : /* Add "prefix" to the list of prefixes and return the updated
221 : * number of prefixes.
222 : */
223 0 : static int add_prefix(struct isl_prefixes *prefixes, const char *prefix)
224 : {
225 0 : int n = prefixes->n;
226 :
227 0 : if (!prefix)
228 0 : return n;
229 :
230 0 : if (prefixes->n >= 10) {
231 0 : fprintf(stderr, "too many prefixes\n");
232 0 : exit(EXIT_FAILURE);
233 : }
234 0 : prefixes->len[prefixes->n] = strlen(prefix);
235 0 : prefixes->prefix[prefixes->n] = prefix;
236 0 : prefixes->n++;
237 :
238 0 : return n;
239 : }
240 :
241 : /* Drop all prefixes starting at "first".
242 : */
243 0 : static void drop_prefix(struct isl_prefixes *prefixes, int first)
244 : {
245 0 : prefixes->n = first;
246 0 : }
247 :
248 : /* Print the prefixes in "prefixes".
249 : */
250 0 : static int print_prefixes(struct isl_prefixes *prefixes)
251 : {
252 : int i;
253 0 : int len = 0;
254 :
255 0 : if (!prefixes)
256 0 : return 0;
257 :
258 0 : for (i = 0; i < prefixes->n; ++i) {
259 0 : printf("%s-", prefixes->prefix[i]);
260 0 : len += strlen(prefixes->prefix[i]) + 1;
261 : }
262 :
263 0 : return len;
264 : }
265 :
266 : /* Check if "name" starts with one or more of the prefixes in "prefixes",
267 : * starting at *first. If so, advance the pointer beyond the prefixes
268 : * and return the updated pointer. Additionally, update *first to
269 : * the index after the last prefix found.
270 : */
271 0 : static const char *skip_prefixes(const char *name,
272 : struct isl_prefixes *prefixes, int *first)
273 : {
274 : int i;
275 :
276 0 : for (i = first ? *first : 0; i < prefixes->n; ++i) {
277 0 : size_t len = prefixes->len[i];
278 0 : const char *prefix = prefixes->prefix[i];
279 0 : if (strncmp(name, prefix, len) == 0 && name[len] == '-') {
280 0 : name += len + 1;
281 0 : if (first)
282 0 : *first = i + 1;
283 : }
284 : }
285 :
286 0 : return name;
287 : }
288 :
289 0 : static int print_arg_help(struct isl_arg *decl, struct isl_prefixes *prefixes,
290 : int no)
291 : {
292 0 : int len = 0;
293 :
294 0 : if (!decl->long_name) {
295 0 : printf(" -%c", decl->short_name);
296 0 : return 4;
297 : }
298 :
299 0 : if (decl->short_name) {
300 0 : printf(" -%c, --", decl->short_name);
301 0 : len += 8;
302 0 : } else if (decl->flags & ISL_ARG_SINGLE_DASH) {
303 0 : printf(" -");
304 0 : len += 3;
305 : } else {
306 0 : printf(" --");
307 0 : len += 8;
308 : }
309 :
310 0 : if (no) {
311 0 : printf("no-");
312 0 : len += 3;
313 : }
314 0 : len += print_prefixes(prefixes);
315 0 : printf("%s", decl->long_name);
316 0 : len += strlen(decl->long_name);
317 :
318 0 : while ((++decl)->type == isl_arg_alias) {
319 0 : printf(", --");
320 0 : len += 4;
321 0 : if (no) {
322 0 : printf("no-");
323 0 : len += 3;
324 : }
325 0 : printf("%s", decl->long_name);
326 0 : len += strlen(decl->long_name);
327 : }
328 :
329 0 : return len;
330 : }
331 :
332 0 : const void *isl_memrchr(const void *s, int c, size_t n)
333 : {
334 0 : const char *p = s;
335 0 : while (n-- > 0)
336 0 : if (p[n] == c)
337 0 : return p + n;
338 0 : return NULL;
339 : }
340 :
341 0 : static int wrap_msg(const char *s, int indent, int pos)
342 : {
343 : int len;
344 0 : int wrap_len = 75 - indent;
345 :
346 0 : if (pos + 1 >= indent)
347 0 : printf("\n%*s", indent, "");
348 : else
349 0 : printf("%*s", indent - pos, "");
350 :
351 0 : len = strlen(s);
352 0 : while (len > wrap_len) {
353 0 : const char *space = isl_memrchr(s, ' ', wrap_len);
354 : int l;
355 :
356 0 : if (!space)
357 0 : space = strchr(s + wrap_len, ' ');
358 0 : if (!space)
359 0 : break;
360 0 : l = space - s;
361 0 : printf("%.*s", l, s);
362 0 : s = space + 1;
363 0 : len -= l + 1;
364 0 : printf("\n%*s", indent, "");
365 : }
366 :
367 0 : printf("%s", s);
368 0 : return len;
369 : }
370 :
371 0 : static int print_help_msg(struct isl_arg *decl, int pos)
372 : {
373 0 : if (!decl->help_msg)
374 0 : return pos;
375 :
376 0 : return wrap_msg(decl->help_msg, 30, pos);
377 : }
378 :
379 0 : static void print_default(struct isl_arg *decl, const char *def, int pos)
380 : {
381 0 : const char *default_prefix = "[default: ";
382 0 : const char *default_suffix = "]";
383 : int len;
384 :
385 0 : len = strlen(default_prefix) + strlen(def) + strlen(default_suffix);
386 :
387 0 : if (!decl->help_msg) {
388 0 : if (pos >= 29)
389 0 : printf("\n%30s", "");
390 : else
391 0 : printf("%*s", 30 - pos, "");
392 : } else {
393 0 : if (pos + len >= 48)
394 0 : printf("\n%30s", "");
395 : else
396 0 : printf(" ");
397 : }
398 0 : printf("%s%s%s", default_prefix, def, default_suffix);
399 0 : }
400 :
401 0 : static void print_default_choice(struct isl_arg *decl, void *opt, int pos)
402 : {
403 : int i;
404 0 : const char *s = "none";
405 : unsigned *p;
406 :
407 0 : p = (unsigned *)(((char *) opt) + decl->offset);
408 0 : for (i = 0; decl->u.choice.choice[i].name; ++i)
409 0 : if (decl->u.choice.choice[i].value == *p) {
410 0 : s = decl->u.choice.choice[i].name;
411 0 : break;
412 : }
413 :
414 0 : print_default(decl, s, pos);
415 0 : }
416 :
417 0 : static void print_choice_help(struct isl_arg *decl,
418 : struct isl_prefixes *prefixes, void *opt)
419 : {
420 : int i;
421 : int pos;
422 :
423 0 : pos = print_arg_help(decl, prefixes, 0);
424 0 : printf("=");
425 0 : pos++;
426 :
427 0 : for (i = 0; decl->u.choice.choice[i].name; ++i) {
428 0 : if (i) {
429 0 : printf("|");
430 0 : pos++;
431 : }
432 0 : printf("%s", decl->u.choice.choice[i].name);
433 0 : pos += strlen(decl->u.choice.choice[i].name);
434 : }
435 :
436 0 : pos = print_help_msg(decl, pos);
437 0 : print_default_choice(decl, opt, pos);
438 :
439 0 : printf("\n");
440 0 : }
441 :
442 0 : static void print_default_flags(struct isl_arg *decl, void *opt, int pos)
443 : {
444 : int i, first;
445 0 : const char *default_prefix = "[default: ";
446 0 : const char *default_suffix = "]";
447 0 : int len = strlen(default_prefix) + strlen(default_suffix);
448 : unsigned *p;
449 :
450 0 : p = (unsigned *)(((char *) opt) + decl->offset);
451 0 : for (i = 0; decl->u.flags.flags[i].name; ++i)
452 0 : if ((*p & decl->u.flags.flags[i].mask) ==
453 0 : decl->u.flags.flags[i].value)
454 0 : len += strlen(decl->u.flags.flags[i].name);
455 :
456 0 : if (!decl->help_msg) {
457 0 : if (pos >= 29)
458 0 : printf("\n%30s", "");
459 : else
460 0 : printf("%*s", 30 - pos, "");
461 : } else {
462 0 : if (pos + len >= 48)
463 0 : printf("\n%30s", "");
464 : else
465 0 : printf(" ");
466 : }
467 0 : printf("%s", default_prefix);
468 :
469 0 : for (first = 1, i = 0; decl->u.flags.flags[i].name; ++i)
470 0 : if ((*p & decl->u.flags.flags[i].mask) ==
471 0 : decl->u.flags.flags[i].value) {
472 0 : if (!first)
473 0 : printf(",");
474 0 : printf("%s", decl->u.flags.flags[i].name);
475 0 : first = 0;
476 : }
477 :
478 0 : printf("%s", default_suffix);
479 0 : }
480 :
481 0 : static void print_flags_help(struct isl_arg *decl,
482 : struct isl_prefixes *prefixes, void *opt)
483 : {
484 : int i, j;
485 : int pos;
486 :
487 0 : pos = print_arg_help(decl, prefixes, 0);
488 0 : printf("=");
489 0 : pos++;
490 :
491 0 : for (i = 0; decl->u.flags.flags[i].name; ++i) {
492 0 : if (i) {
493 0 : printf(",");
494 0 : pos++;
495 : }
496 0 : for (j = i;
497 0 : decl->u.flags.flags[j].mask == decl->u.flags.flags[i].mask;
498 0 : ++j) {
499 0 : if (j != i) {
500 0 : printf("|");
501 0 : pos++;
502 : }
503 0 : printf("%s", decl->u.flags.flags[j].name);
504 0 : pos += strlen(decl->u.flags.flags[j].name);
505 : }
506 0 : i = j - 1;
507 : }
508 :
509 0 : pos = print_help_msg(decl, pos);
510 0 : print_default_flags(decl, opt, pos);
511 :
512 0 : printf("\n");
513 0 : }
514 :
515 0 : static void print_bool_help(struct isl_arg *decl,
516 : struct isl_prefixes *prefixes, void *opt)
517 : {
518 : int pos;
519 0 : unsigned *p = opt ? (unsigned *)(((char *) opt) + decl->offset) : NULL;
520 0 : int no = p ? *p == 1 : 0;
521 0 : pos = print_arg_help(decl, prefixes, no);
522 0 : pos = print_help_msg(decl, pos);
523 0 : if (decl->offset != (size_t) -1)
524 0 : print_default(decl, no ? "yes" : "no", pos);
525 0 : printf("\n");
526 0 : }
527 :
528 0 : static int print_argument_name(struct isl_arg *decl, const char *name, int pos)
529 : {
530 0 : printf("%c<%s>", decl->long_name ? '=' : ' ', name);
531 0 : return pos + 3 + strlen(name);
532 : }
533 :
534 0 : static void print_int_help(struct isl_arg *decl,
535 : struct isl_prefixes *prefixes, void *opt)
536 : {
537 : int pos;
538 : char val[20];
539 0 : int *p = (int *)(((char *) opt) + decl->offset);
540 0 : pos = print_arg_help(decl, prefixes, 0);
541 0 : pos = print_argument_name(decl, decl->argument_name, pos);
542 0 : pos = print_help_msg(decl, pos);
543 0 : snprintf(val, sizeof(val), "%d", *p);
544 0 : print_default(decl, val, pos);
545 0 : printf("\n");
546 0 : }
547 :
548 0 : static void print_long_help(struct isl_arg *decl,
549 : struct isl_prefixes *prefixes, void *opt)
550 : {
551 : int pos;
552 0 : long *p = (long *)(((char *) opt) + decl->offset);
553 0 : pos = print_arg_help(decl, prefixes, 0);
554 0 : if (*p != decl->u.l.default_selected) {
555 0 : printf("[");
556 0 : pos++;
557 : }
558 0 : printf("=long");
559 0 : pos += 5;
560 0 : if (*p != decl->u.l.default_selected) {
561 0 : printf("]");
562 0 : pos++;
563 : }
564 0 : print_help_msg(decl, pos);
565 0 : printf("\n");
566 0 : }
567 :
568 0 : static void print_ulong_help(struct isl_arg *decl,
569 : struct isl_prefixes *prefixes)
570 : {
571 : int pos;
572 0 : pos = print_arg_help(decl, prefixes, 0);
573 0 : printf("=ulong");
574 0 : pos += 6;
575 0 : print_help_msg(decl, pos);
576 0 : printf("\n");
577 0 : }
578 :
579 0 : static void print_str_help(struct isl_arg *decl,
580 : struct isl_prefixes *prefixes, void *opt)
581 : {
582 : int pos;
583 0 : const char *a = decl->argument_name ? decl->argument_name : "string";
584 0 : const char **p = (const char **)(((char *) opt) + decl->offset);
585 0 : pos = print_arg_help(decl, prefixes, 0);
586 0 : pos = print_argument_name(decl, a, pos);
587 0 : pos = print_help_msg(decl, pos);
588 0 : if (*p)
589 0 : print_default(decl, *p, pos);
590 0 : printf("\n");
591 0 : }
592 :
593 0 : static void print_str_list_help(struct isl_arg *decl,
594 : struct isl_prefixes *prefixes)
595 : {
596 : int pos;
597 0 : const char *a = decl->argument_name ? decl->argument_name : "string";
598 0 : pos = print_arg_help(decl, prefixes, 0);
599 0 : pos = print_argument_name(decl, a, pos);
600 0 : pos = print_help_msg(decl, pos);
601 0 : printf("\n");
602 0 : }
603 :
604 0 : static void print_help(struct isl_arg *arg,
605 : struct isl_prefixes *prefixes, void *opt)
606 : {
607 : int i;
608 0 : int any = 0;
609 :
610 0 : for (i = 0; arg[i].type != isl_arg_end; ++i) {
611 0 : if (arg[i].flags & ISL_ARG_HIDDEN)
612 0 : continue;
613 0 : switch (arg[i].type) {
614 : case isl_arg_flags:
615 0 : print_flags_help(&arg[i], prefixes, opt);
616 0 : any = 1;
617 0 : break;
618 : case isl_arg_choice:
619 0 : print_choice_help(&arg[i], prefixes, opt);
620 0 : any = 1;
621 0 : break;
622 : case isl_arg_bool:
623 0 : print_bool_help(&arg[i], prefixes, opt);
624 0 : any = 1;
625 0 : break;
626 : case isl_arg_int:
627 0 : print_int_help(&arg[i], prefixes, opt);
628 0 : any = 1;
629 0 : break;
630 : case isl_arg_long:
631 0 : print_long_help(&arg[i], prefixes, opt);
632 0 : any = 1;
633 0 : break;
634 : case isl_arg_ulong:
635 0 : print_ulong_help(&arg[i], prefixes);
636 0 : any = 1;
637 0 : break;
638 : case isl_arg_str:
639 0 : print_str_help(&arg[i], prefixes, opt);
640 0 : any = 1;
641 0 : break;
642 : case isl_arg_str_list:
643 0 : print_str_list_help(&arg[i], prefixes);
644 0 : any = 1;
645 0 : break;
646 : case isl_arg_alias:
647 : case isl_arg_version:
648 : case isl_arg_arg:
649 : case isl_arg_footer:
650 : case isl_arg_child:
651 : case isl_arg_user:
652 : case isl_arg_end:
653 0 : break;
654 : }
655 : }
656 :
657 0 : for (i = 0; arg[i].type != isl_arg_end; ++i) {
658 : void *child;
659 : int first;
660 :
661 0 : if (arg[i].type != isl_arg_child)
662 0 : continue;
663 0 : if (arg[i].flags & ISL_ARG_HIDDEN)
664 0 : continue;
665 :
666 0 : if (any)
667 0 : printf("\n");
668 0 : if (arg[i].help_msg)
669 0 : printf(" %s\n", arg[i].help_msg);
670 0 : if (arg[i].offset == (size_t) -1)
671 0 : child = opt;
672 : else
673 0 : child = *(void **)(((char *) opt) + arg[i].offset);
674 0 : first = add_prefix(prefixes, arg[i].long_name);
675 0 : print_help(arg[i].u.child.child->args, prefixes, child);
676 0 : drop_prefix(prefixes, first);
677 0 : any = 1;
678 : }
679 0 : }
680 :
681 0 : static const char *prog_name(const char *prog)
682 : {
683 : const char *slash;
684 :
685 0 : slash = strrchr(prog, '/');
686 0 : if (slash)
687 0 : prog = slash + 1;
688 0 : if (strncmp(prog, "lt-", 3) == 0)
689 0 : prog += 3;
690 :
691 0 : return prog;
692 : }
693 :
694 0 : static int any_version(struct isl_arg *decl)
695 : {
696 : int i;
697 :
698 0 : for (i = 0; decl[i].type != isl_arg_end; ++i) {
699 0 : switch (decl[i].type) {
700 : case isl_arg_version:
701 0 : return 1;
702 : case isl_arg_child:
703 0 : if (any_version(decl[i].u.child.child->args))
704 0 : return 1;
705 0 : break;
706 : default:
707 0 : break;
708 : }
709 : }
710 :
711 0 : return 0;
712 : }
713 :
714 0 : static void print_help_and_exit(struct isl_arg *arg, const char *prog,
715 : void *opt)
716 : {
717 : int i;
718 0 : struct isl_prefixes prefixes = { 0 };
719 :
720 0 : printf("Usage: %s [OPTION...]", prog_name(prog));
721 :
722 0 : for (i = 0; arg[i].type != isl_arg_end; ++i)
723 0 : if (arg[i].type == isl_arg_arg)
724 0 : printf(" %s", arg[i].argument_name);
725 :
726 0 : printf("\n\n");
727 :
728 0 : print_help(arg, &prefixes, opt);
729 0 : printf("\n");
730 0 : if (any_version(arg))
731 0 : printf(" -V, --version\n");
732 0 : print_bool_help(help_arg, NULL, NULL);
733 :
734 0 : for (i = 0; arg[i].type != isl_arg_end; ++i) {
735 0 : if (arg[i].type != isl_arg_footer)
736 0 : continue;
737 0 : wrap_msg(arg[i].help_msg, 0, 0);
738 0 : printf("\n");
739 : }
740 :
741 0 : exit(0);
742 : }
743 :
744 0 : static int match_long_name(struct isl_arg *decl,
745 : const char *start, const char *end)
746 : {
747 : do {
748 0 : if (end - start == strlen(decl->long_name) &&
749 0 : !strncmp(start, decl->long_name, end - start))
750 0 : return 1;
751 0 : } while ((++decl)->type == isl_arg_alias);
752 :
753 0 : return 0;
754 : }
755 :
756 0 : static const char *skip_dash_dash(struct isl_arg *decl, const char *arg)
757 : {
758 0 : if (!strncmp(arg, "--", 2))
759 0 : return arg + 2;
760 0 : if ((decl->flags & ISL_ARG_SINGLE_DASH) && arg[0] == '-')
761 0 : return arg + 1;
762 0 : return NULL;
763 : }
764 :
765 0 : static const char *skip_name(struct isl_arg *decl, const char *arg,
766 : struct isl_prefixes *prefixes, int need_argument, int *has_argument)
767 : {
768 : const char *equal;
769 : const char *name;
770 : const char *end;
771 :
772 0 : if (arg[0] == '-' && arg[1] && arg[1] == decl->short_name) {
773 0 : if (need_argument && !arg[2])
774 0 : return NULL;
775 0 : if (has_argument)
776 0 : *has_argument = arg[2] != '\0';
777 0 : return arg + 2;
778 : }
779 0 : if (!decl->long_name)
780 0 : return NULL;
781 :
782 0 : name = skip_dash_dash(decl, arg);
783 0 : if (!name)
784 0 : return NULL;
785 :
786 0 : equal = strchr(name, '=');
787 0 : if (need_argument && !equal)
788 0 : return NULL;
789 :
790 0 : if (has_argument)
791 0 : *has_argument = !!equal;
792 0 : end = equal ? equal : name + strlen(name);
793 :
794 0 : name = skip_prefixes(name, prefixes, NULL);
795 :
796 0 : if (!match_long_name(decl, name, end))
797 0 : return NULL;
798 :
799 0 : return equal ? equal + 1 : end;
800 : }
801 :
802 0 : static int parse_choice_option(struct isl_arg *decl, char **arg,
803 : struct isl_prefixes *prefixes, void *opt)
804 : {
805 : int i;
806 : int has_argument;
807 : const char *choice;
808 :
809 0 : choice = skip_name(decl, arg[0], prefixes, 0, &has_argument);
810 0 : if (!choice)
811 0 : return 0;
812 :
813 0 : if (!has_argument && (!arg[1] || arg[1][0] == '-')) {
814 0 : unsigned u = decl->u.choice.default_selected;
815 0 : if (decl->offset != (size_t) -1)
816 0 : *(unsigned *)(((char *)opt) + decl->offset) = u;
817 0 : if (decl->u.choice.set)
818 0 : decl->u.choice.set(opt, u);
819 :
820 0 : return 1;
821 : }
822 :
823 0 : if (!has_argument)
824 0 : choice = arg[1];
825 :
826 0 : for (i = 0; decl->u.choice.choice[i].name; ++i) {
827 : unsigned u;
828 :
829 0 : if (strcmp(choice, decl->u.choice.choice[i].name))
830 0 : continue;
831 :
832 0 : u = decl->u.choice.choice[i].value;
833 0 : if (decl->offset != (size_t) -1)
834 0 : *(unsigned *)(((char *)opt) + decl->offset) = u;
835 0 : if (decl->u.choice.set)
836 0 : decl->u.choice.set(opt, u);
837 :
838 0 : return has_argument ? 1 : 2;
839 : }
840 :
841 0 : return 0;
842 : }
843 :
844 0 : static int set_flag(struct isl_arg *decl, unsigned *val, const char *flag,
845 : size_t len)
846 : {
847 : int i;
848 :
849 0 : for (i = 0; decl->u.flags.flags[i].name; ++i) {
850 0 : if (strncmp(flag, decl->u.flags.flags[i].name, len))
851 0 : continue;
852 :
853 0 : *val &= ~decl->u.flags.flags[i].mask;
854 0 : *val |= decl->u.flags.flags[i].value;
855 :
856 0 : return 1;
857 : }
858 :
859 0 : return 0;
860 : }
861 :
862 0 : static int parse_flags_option(struct isl_arg *decl, char **arg,
863 : struct isl_prefixes *prefixes, void *opt)
864 : {
865 : int has_argument;
866 : const char *flags;
867 : const char *comma;
868 : unsigned val;
869 :
870 0 : flags = skip_name(decl, arg[0], prefixes, 0, &has_argument);
871 0 : if (!flags)
872 0 : return 0;
873 :
874 0 : if (!has_argument && !arg[1])
875 0 : return 0;
876 :
877 0 : if (!has_argument)
878 0 : flags = arg[1];
879 :
880 0 : val = 0;
881 :
882 0 : while ((comma = strchr(flags, ',')) != NULL) {
883 0 : if (!set_flag(decl, &val, flags, comma - flags))
884 0 : return 0;
885 0 : flags = comma + 1;
886 : }
887 0 : if (!set_flag(decl, &val, flags, strlen(flags)))
888 0 : return 0;
889 :
890 0 : *(unsigned *)(((char *)opt) + decl->offset) = val;
891 :
892 0 : return has_argument ? 1 : 2;
893 : }
894 :
895 0 : static int parse_bool_option(struct isl_arg *decl, char **arg,
896 : struct isl_prefixes *prefixes, void *opt)
897 : {
898 : const char *name;
899 0 : unsigned *p = (unsigned *)(((char *)opt) + decl->offset);
900 : int next_prefix;
901 :
902 0 : if (skip_name(decl, arg[0], prefixes, 0, NULL)) {
903 0 : if ((decl->flags & ISL_ARG_BOOL_ARG) && arg[1]) {
904 : char *endptr;
905 0 : int val = strtol(arg[1], &endptr, 0);
906 0 : if (*endptr == '\0' && (val == 0 || val == 1)) {
907 0 : if (decl->offset != (size_t) -1)
908 0 : *p = val;
909 0 : if (decl->u.b.set)
910 0 : decl->u.b.set(opt, val);
911 0 : return 2;
912 : }
913 : }
914 0 : if (decl->offset != (size_t) -1)
915 0 : *p = 1;
916 0 : if (decl->u.b.set)
917 0 : decl->u.b.set(opt, 1);
918 :
919 0 : return 1;
920 : }
921 :
922 0 : if (!decl->long_name)
923 0 : return 0;
924 :
925 0 : name = skip_dash_dash(decl, arg[0]);
926 0 : if (!name)
927 0 : return 0;
928 :
929 0 : next_prefix = 0;
930 0 : name = skip_prefixes(name, prefixes, &next_prefix);
931 :
932 0 : if (strncmp(name, "no-", 3))
933 0 : return 0;
934 0 : name += 3;
935 :
936 0 : name = skip_prefixes(name, prefixes, &next_prefix);
937 :
938 0 : if (match_long_name(decl, name, name + strlen(name))) {
939 0 : if (decl->offset != (size_t) -1)
940 0 : *p = 0;
941 0 : if (decl->u.b.set)
942 0 : decl->u.b.set(opt, 0);
943 :
944 0 : return 1;
945 : }
946 :
947 0 : return 0;
948 : }
949 :
950 0 : static int parse_str_option(struct isl_arg *decl, char **arg,
951 : struct isl_prefixes *prefixes, void *opt)
952 : {
953 : int has_argument;
954 : const char *s;
955 0 : char **p = (char **)(((char *)opt) + decl->offset);
956 :
957 0 : s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
958 0 : if (!s)
959 0 : return 0;
960 :
961 0 : if (has_argument) {
962 0 : free(*p);
963 0 : *p = strdup(s);
964 0 : return 1;
965 : }
966 :
967 0 : if (arg[1]) {
968 0 : free(*p);
969 0 : *p = strdup(arg[1]);
970 0 : return 2;
971 : }
972 :
973 0 : return 0;
974 : }
975 :
976 0 : static int isl_arg_str_list_append(struct isl_arg *decl, void *opt,
977 : const char *s)
978 : {
979 0 : int *n = (int *)(((char *) opt) + decl->u.str_list.offset_n);
980 0 : char **list = *(char ***)(((char *) opt) + decl->offset);
981 :
982 0 : list = realloc(list, (*n + 1) * sizeof(char *));
983 0 : if (!list)
984 0 : return -1;
985 0 : *(char ***)(((char *) opt) + decl->offset) = list;
986 0 : list[*n] = strdup(s);
987 0 : (*n)++;
988 0 : return 0;
989 : }
990 :
991 0 : static int parse_str_list_option(struct isl_arg *decl, char **arg,
992 : struct isl_prefixes *prefixes, void *opt)
993 : {
994 : int has_argument;
995 : const char *s;
996 :
997 0 : s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
998 0 : if (!s)
999 0 : return 0;
1000 :
1001 0 : if (has_argument) {
1002 0 : isl_arg_str_list_append(decl, opt, s);
1003 0 : return 1;
1004 : }
1005 :
1006 0 : if (arg[1]) {
1007 0 : isl_arg_str_list_append(decl, opt, arg[1]);
1008 0 : return 2;
1009 : }
1010 :
1011 0 : return 0;
1012 : }
1013 :
1014 0 : static int parse_int_option(struct isl_arg *decl, char **arg,
1015 : struct isl_prefixes *prefixes, void *opt)
1016 : {
1017 : int has_argument;
1018 : const char *val;
1019 : char *endptr;
1020 0 : int *p = (int *)(((char *)opt) + decl->offset);
1021 :
1022 0 : val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1023 0 : if (!val)
1024 0 : return 0;
1025 :
1026 0 : if (has_argument) {
1027 0 : *p = atoi(val);
1028 0 : return 1;
1029 : }
1030 :
1031 0 : if (arg[1]) {
1032 0 : int i = strtol(arg[1], &endptr, 0);
1033 0 : if (*endptr == '\0') {
1034 0 : *p = i;
1035 0 : return 2;
1036 : }
1037 : }
1038 :
1039 0 : return 0;
1040 : }
1041 :
1042 0 : static int parse_long_option(struct isl_arg *decl, char **arg,
1043 : struct isl_prefixes *prefixes, void *opt)
1044 : {
1045 : int has_argument;
1046 : const char *val;
1047 : char *endptr;
1048 0 : long *p = (long *)(((char *)opt) + decl->offset);
1049 :
1050 0 : val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1051 0 : if (!val)
1052 0 : return 0;
1053 :
1054 0 : if (has_argument) {
1055 0 : long l = strtol(val, NULL, 0);
1056 0 : *p = l;
1057 0 : if (decl->u.l.set)
1058 0 : decl->u.l.set(opt, l);
1059 0 : return 1;
1060 : }
1061 :
1062 0 : if (arg[1]) {
1063 0 : long l = strtol(arg[1], &endptr, 0);
1064 0 : if (*endptr == '\0') {
1065 0 : *p = l;
1066 0 : if (decl->u.l.set)
1067 0 : decl->u.l.set(opt, l);
1068 0 : return 2;
1069 : }
1070 : }
1071 :
1072 0 : if (decl->u.l.default_value != decl->u.l.default_selected) {
1073 0 : *p = decl->u.l.default_selected;
1074 0 : if (decl->u.l.set)
1075 0 : decl->u.l.set(opt, decl->u.l.default_selected);
1076 0 : return 1;
1077 : }
1078 :
1079 0 : return 0;
1080 : }
1081 :
1082 0 : static int parse_ulong_option(struct isl_arg *decl, char **arg,
1083 : struct isl_prefixes *prefixes, void *opt)
1084 : {
1085 : int has_argument;
1086 : const char *val;
1087 : char *endptr;
1088 0 : unsigned long *p = (unsigned long *)(((char *)opt) + decl->offset);
1089 :
1090 0 : val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1091 0 : if (!val)
1092 0 : return 0;
1093 :
1094 0 : if (has_argument) {
1095 0 : *p = strtoul(val, NULL, 0);
1096 0 : return 1;
1097 : }
1098 :
1099 0 : if (arg[1]) {
1100 0 : unsigned long ul = strtoul(arg[1], &endptr, 0);
1101 0 : if (*endptr == '\0') {
1102 0 : *p = ul;
1103 0 : return 2;
1104 : }
1105 : }
1106 :
1107 0 : return 0;
1108 : }
1109 :
1110 : static int parse_option(struct isl_arg *decl, char **arg,
1111 : struct isl_prefixes *prefixes, void *opt);
1112 :
1113 0 : static int parse_child_option(struct isl_arg *decl, char **arg,
1114 : struct isl_prefixes *prefixes, void *opt)
1115 : {
1116 : void *child;
1117 : int first, parsed;
1118 :
1119 0 : if (decl->offset == (size_t) -1)
1120 0 : child = opt;
1121 : else
1122 0 : child = *(void **)(((char *)opt) + decl->offset);
1123 :
1124 0 : first = add_prefix(prefixes, decl->long_name);
1125 0 : parsed = parse_option(decl->u.child.child->args, arg, prefixes, child);
1126 0 : drop_prefix(prefixes, first);
1127 :
1128 0 : return parsed;
1129 : }
1130 :
1131 0 : static int parse_option(struct isl_arg *decl, char **arg,
1132 : struct isl_prefixes *prefixes, void *opt)
1133 : {
1134 : int i;
1135 :
1136 0 : for (i = 0; decl[i].type != isl_arg_end; ++i) {
1137 0 : int parsed = 0;
1138 0 : switch (decl[i].type) {
1139 : case isl_arg_choice:
1140 0 : parsed = parse_choice_option(&decl[i], arg,
1141 : prefixes, opt);
1142 0 : break;
1143 : case isl_arg_flags:
1144 0 : parsed = parse_flags_option(&decl[i], arg,
1145 : prefixes, opt);
1146 0 : break;
1147 : case isl_arg_int:
1148 0 : parsed = parse_int_option(&decl[i], arg, prefixes, opt);
1149 0 : break;
1150 : case isl_arg_long:
1151 0 : parsed = parse_long_option(&decl[i], arg,
1152 : prefixes, opt);
1153 0 : break;
1154 : case isl_arg_ulong:
1155 0 : parsed = parse_ulong_option(&decl[i], arg,
1156 : prefixes, opt);
1157 0 : break;
1158 : case isl_arg_bool:
1159 0 : parsed = parse_bool_option(&decl[i], arg,
1160 : prefixes, opt);
1161 0 : break;
1162 : case isl_arg_str:
1163 0 : parsed = parse_str_option(&decl[i], arg, prefixes, opt);
1164 0 : break;
1165 : case isl_arg_str_list:
1166 0 : parsed = parse_str_list_option(&decl[i], arg, prefixes,
1167 : opt);
1168 0 : break;
1169 : case isl_arg_child:
1170 0 : parsed = parse_child_option(&decl[i], arg,
1171 : prefixes, opt);
1172 0 : break;
1173 : case isl_arg_alias:
1174 : case isl_arg_arg:
1175 : case isl_arg_footer:
1176 : case isl_arg_user:
1177 : case isl_arg_version:
1178 : case isl_arg_end:
1179 0 : break;
1180 : }
1181 0 : if (parsed)
1182 0 : return parsed;
1183 : }
1184 :
1185 0 : return 0;
1186 : }
1187 :
1188 0 : static void print_version(struct isl_arg *decl)
1189 : {
1190 : int i;
1191 :
1192 0 : for (i = 0; decl[i].type != isl_arg_end; ++i) {
1193 0 : switch (decl[i].type) {
1194 : case isl_arg_version:
1195 0 : decl[i].u.version.print_version();
1196 0 : break;
1197 : case isl_arg_child:
1198 0 : print_version(decl[i].u.child.child->args);
1199 0 : break;
1200 : default:
1201 0 : break;
1202 : }
1203 : }
1204 0 : }
1205 :
1206 0 : static void print_version_and_exit(struct isl_arg *decl)
1207 : {
1208 0 : print_version(decl);
1209 :
1210 0 : exit(0);
1211 : }
1212 :
1213 0 : static int drop_argument(int argc, char **argv, int drop, int n)
1214 : {
1215 0 : for (; drop + n < argc; ++drop)
1216 0 : argv[drop] = argv[drop + n];
1217 :
1218 0 : return argc - n;
1219 : }
1220 :
1221 0 : static int n_arg(struct isl_arg *arg)
1222 : {
1223 : int i;
1224 0 : int n_arg = 0;
1225 :
1226 0 : for (i = 0; arg[i].type != isl_arg_end; ++i)
1227 0 : if (arg[i].type == isl_arg_arg)
1228 0 : n_arg++;
1229 :
1230 0 : return n_arg;
1231 : }
1232 :
1233 0 : static int next_arg(struct isl_arg *arg, int a)
1234 : {
1235 0 : for (++a; arg[a].type != isl_arg_end; ++a)
1236 0 : if (arg[a].type == isl_arg_arg)
1237 0 : return a;
1238 :
1239 0 : return -1;
1240 : }
1241 :
1242 : /* Unless ISL_ARG_SKIP_HELP is set, check if "arg" is
1243 : * equal to "--help" and if so call print_help_and_exit.
1244 : */
1245 0 : static void check_help(struct isl_args *args, char *arg, char *prog, void *opt,
1246 : unsigned flags)
1247 : {
1248 0 : if (ISL_FL_ISSET(flags, ISL_ARG_SKIP_HELP))
1249 0 : return;
1250 :
1251 0 : if (strcmp(arg, "--help") == 0)
1252 0 : print_help_and_exit(args->args, prog, opt);
1253 : }
1254 :
1255 0 : int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
1256 : unsigned flags)
1257 : {
1258 0 : int a = -1;
1259 0 : int skip = 0;
1260 : int i;
1261 : int n;
1262 0 : struct isl_prefixes prefixes = { 0 };
1263 :
1264 0 : n = n_arg(args->args);
1265 :
1266 0 : for (i = 1; i < argc; ++i) {
1267 0 : if ((strcmp(argv[i], "--version") == 0 ||
1268 0 : strcmp(argv[i], "-V") == 0) && any_version(args->args))
1269 0 : print_version_and_exit(args->args);
1270 : }
1271 :
1272 0 : while (argc > 1 + skip) {
1273 : int parsed;
1274 0 : if (argv[1 + skip][0] != '-') {
1275 0 : a = next_arg(args->args, a);
1276 0 : if (a >= 0) {
1277 : char **p;
1278 0 : p = (char **)(((char *)opt)+args->args[a].offset);
1279 0 : free(*p);
1280 0 : *p = strdup(argv[1 + skip]);
1281 0 : argc = drop_argument(argc, argv, 1 + skip, 1);
1282 0 : --n;
1283 0 : } else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
1284 0 : fprintf(stderr, "%s: extra argument: %s\n",
1285 0 : prog_name(argv[0]), argv[1 + skip]);
1286 0 : exit(-1);
1287 : } else
1288 0 : ++skip;
1289 0 : continue;
1290 : }
1291 0 : check_help(args, argv[1 + skip], argv[0], opt, flags);
1292 0 : parsed = parse_option(args->args, &argv[1 + skip],
1293 : &prefixes, opt);
1294 0 : if (parsed)
1295 0 : argc = drop_argument(argc, argv, 1 + skip, parsed);
1296 0 : else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
1297 0 : fprintf(stderr, "%s: unrecognized option: %s\n",
1298 0 : prog_name(argv[0]), argv[1 + skip]);
1299 0 : exit(-1);
1300 : } else
1301 0 : ++skip;
1302 : }
1303 :
1304 0 : if (n > 0) {
1305 0 : fprintf(stderr, "%s: expecting %d more argument(s)\n",
1306 : prog_name(argv[0]), n);
1307 0 : exit(-1);
1308 : }
1309 :
1310 0 : return argc;
1311 : }
|