isl_ast_graft_list_extract_shared_enforced: allow empty list of grafts
[isl.git] / isl_arg.c
blobd85dccecf4e28ccebc8b8c63ea8bb12f3a4ddda5
1 /*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 #include <isl/arg.h>
15 #include <isl/ctx.h>
16 #include <isl_config.h>
18 static struct isl_arg help_arg[] = {
19 ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")
22 static void set_default_choice(struct isl_arg *arg, void *opt)
24 if (arg->offset == (size_t) -1)
25 return;
26 *(unsigned *)(((char *)opt) + arg->offset) = arg->u.choice.default_value;
29 static void set_default_flags(struct isl_arg *arg, void *opt)
31 *(unsigned *)(((char *)opt) + arg->offset) = arg->u.flags.default_value;
34 static void set_default_bool(struct isl_arg *arg, void *opt)
36 if (arg->offset == (size_t) -1)
37 return;
38 *(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value;
41 static void set_default_child(struct isl_arg *arg, void *opt)
43 void *child;
45 if (arg->offset == (size_t) -1)
46 child = opt;
47 else {
48 child = calloc(1, arg->u.child.child->options_size);
49 *(void **)(((char *)opt) + arg->offset) = child;
52 if (child)
53 isl_args_set_defaults(arg->u.child.child, child);
56 static void set_default_user(struct isl_arg *arg, void *opt)
58 arg->u.user.init(((char *)opt) + arg->offset);
61 static void set_default_int(struct isl_arg *arg, void *opt)
63 *(int *)(((char *)opt) + arg->offset) = arg->u.i.default_value;
66 static void set_default_long(struct isl_arg *arg, void *opt)
68 *(long *)(((char *)opt) + arg->offset) = arg->u.l.default_value;
71 static void set_default_ulong(struct isl_arg *arg, void *opt)
73 *(unsigned long *)(((char *)opt) + arg->offset) = arg->u.ul.default_value;
76 static void set_default_str(struct isl_arg *arg, void *opt)
78 const char *str = NULL;
79 if (arg->u.str.default_value)
80 str = strdup(arg->u.str.default_value);
81 *(const char **)(((char *)opt) + arg->offset) = str;
84 static void set_default_str_list(struct isl_arg *arg, void *opt)
86 *(const char ***)(((char *) opt) + arg->offset) = NULL;
87 *(int *)(((char *) opt) + arg->u.str_list.offset_n) = 0;
90 void isl_args_set_defaults(struct isl_args *args, void *opt)
92 int i;
94 for (i = 0; args->args[i].type != isl_arg_end; ++i) {
95 switch (args->args[i].type) {
96 case isl_arg_choice:
97 set_default_choice(&args->args[i], opt);
98 break;
99 case isl_arg_flags:
100 set_default_flags(&args->args[i], opt);
101 break;
102 case isl_arg_bool:
103 set_default_bool(&args->args[i], opt);
104 break;
105 case isl_arg_child:
106 set_default_child(&args->args[i], opt);
107 break;
108 case isl_arg_user:
109 set_default_user(&args->args[i], opt);
110 break;
111 case isl_arg_int:
112 set_default_int(&args->args[i], opt);
113 break;
114 case isl_arg_long:
115 set_default_long(&args->args[i], opt);
116 break;
117 case isl_arg_ulong:
118 set_default_ulong(&args->args[i], opt);
119 break;
120 case isl_arg_arg:
121 case isl_arg_str:
122 set_default_str(&args->args[i], opt);
123 break;
124 case isl_arg_str_list:
125 set_default_str_list(&args->args[i], opt);
126 break;
127 case isl_arg_alias:
128 case isl_arg_footer:
129 case isl_arg_version:
130 case isl_arg_end:
131 break;
136 static void free_args(struct isl_arg *arg, void *opt);
138 static void free_child(struct isl_arg *arg, void *opt)
140 if (arg->offset == (size_t) -1)
141 free_args(arg->u.child.child->args, opt);
142 else
143 isl_args_free(arg->u.child.child,
144 *(void **)(((char *)opt) + arg->offset));
147 static void free_str_list(struct isl_arg *arg, void *opt)
149 int i;
150 int n = *(int *)(((char *) opt) + arg->u.str_list.offset_n);
151 char **list = *(char ***)(((char *) opt) + arg->offset);
153 for (i = 0; i < n; ++i)
154 free(list[i]);
155 free(list);
158 static void free_user(struct isl_arg *arg, void *opt)
160 if (arg->u.user.clear)
161 arg->u.user.clear(((char *)opt) + arg->offset);
164 static void free_args(struct isl_arg *arg, void *opt)
166 int i;
168 for (i = 0; arg[i].type != isl_arg_end; ++i) {
169 switch (arg[i].type) {
170 case isl_arg_child:
171 free_child(&arg[i], opt);
172 break;
173 case isl_arg_arg:
174 case isl_arg_str:
175 free(*(char **)(((char *)opt) + arg[i].offset));
176 break;
177 case isl_arg_str_list:
178 free_str_list(&arg[i], opt);
179 break;
180 case isl_arg_user:
181 free_user(&arg[i], opt);
182 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 break;
198 void isl_args_free(struct isl_args *args, void *opt)
200 if (!opt)
201 return;
203 free_args(args->args, opt);
205 free(opt);
208 /* Data structure for collecting the prefixes of ancestor nodes.
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].
214 struct isl_prefixes {
215 int n;
216 const char *prefix[10];
217 size_t len[10];
220 /* Add "prefix" to the list of prefixes and return the updated
221 * number of prefixes.
223 static int add_prefix(struct isl_prefixes *prefixes, const char *prefix)
225 int n = prefixes->n;
227 if (!prefix)
228 return n;
230 if (prefixes->n >= 10) {
231 fprintf(stderr, "too many prefixes\n");
232 exit(EXIT_FAILURE);
234 prefixes->len[prefixes->n] = strlen(prefix);
235 prefixes->prefix[prefixes->n] = prefix;
236 prefixes->n++;
238 return n;
241 /* Drop all prefixes starting at "first".
243 static void drop_prefix(struct isl_prefixes *prefixes, int first)
245 prefixes->n = first;
248 /* Print the prefixes in "prefixes".
250 static int print_prefixes(struct isl_prefixes *prefixes)
252 int i;
253 int len = 0;
255 if (!prefixes)
256 return 0;
258 for (i = 0; i < prefixes->n; ++i) {
259 printf("%s-", prefixes->prefix[i]);
260 len += strlen(prefixes->prefix[i]) + 1;
263 return len;
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.
271 static const char *skip_prefixes(const char *name,
272 struct isl_prefixes *prefixes, int *first)
274 int i;
276 for (i = first ? *first : 0; i < prefixes->n; ++i) {
277 size_t len = prefixes->len[i];
278 const char *prefix = prefixes->prefix[i];
279 if (strncmp(name, prefix, len) == 0 && name[len] == '-') {
280 name += len + 1;
281 if (first)
282 *first = i + 1;
286 return name;
289 static int print_arg_help(struct isl_arg *decl, struct isl_prefixes *prefixes,
290 int no)
292 int len = 0;
294 if (!decl->long_name) {
295 printf(" -%c", decl->short_name);
296 return 4;
299 if (decl->short_name) {
300 printf(" -%c, --", decl->short_name);
301 len += 8;
302 } else if (decl->flags & ISL_ARG_SINGLE_DASH) {
303 printf(" -");
304 len += 3;
305 } else {
306 printf(" --");
307 len += 8;
310 if (no) {
311 printf("no-");
312 len += 3;
314 len += print_prefixes(prefixes);
315 printf("%s", decl->long_name);
316 len += strlen(decl->long_name);
318 while ((++decl)->type == isl_arg_alias) {
319 printf(", --");
320 len += 4;
321 if (no) {
322 printf("no-");
323 len += 3;
325 printf("%s", decl->long_name);
326 len += strlen(decl->long_name);
329 return len;
332 const void *isl_memrchr(const void *s, int c, size_t n)
334 const char *p = s;
335 while (n-- > 0)
336 if (p[n] == c)
337 return p + n;
338 return NULL;
341 static int wrap_msg(const char *s, int indent, int pos)
343 int len;
344 int wrap_len = 75 - indent;
346 if (pos + 1 >= indent)
347 printf("\n%*s", indent, "");
348 else
349 printf("%*s", indent - pos, "");
351 len = strlen(s);
352 while (len > wrap_len) {
353 const char *space = isl_memrchr(s, ' ', wrap_len);
354 int l;
356 if (!space)
357 space = strchr(s + wrap_len, ' ');
358 if (!space)
359 break;
360 l = space - s;
361 printf("%.*s", l, s);
362 s = space + 1;
363 len -= l + 1;
364 printf("\n%*s", indent, "");
367 printf("%s", s);
368 return len;
371 static int print_help_msg(struct isl_arg *decl, int pos)
373 if (!decl->help_msg)
374 return pos;
376 return wrap_msg(decl->help_msg, 30, pos);
379 static void print_default(struct isl_arg *decl, const char *def, int pos)
381 const char *default_prefix = "[default: ";
382 const char *default_suffix = "]";
383 int len;
385 len = strlen(default_prefix) + strlen(def) + strlen(default_suffix);
387 if (!decl->help_msg) {
388 if (pos >= 29)
389 printf("\n%30s", "");
390 else
391 printf("%*s", 30 - pos, "");
392 } else {
393 if (pos + len >= 48)
394 printf("\n%30s", "");
395 else
396 printf(" ");
398 printf("%s%s%s", default_prefix, def, default_suffix);
401 static void print_default_choice(struct isl_arg *decl, void *opt, int pos)
403 int i;
404 const char *s = "none";
405 unsigned *p;
407 p = (unsigned *)(((char *) opt) + decl->offset);
408 for (i = 0; decl->u.choice.choice[i].name; ++i)
409 if (decl->u.choice.choice[i].value == *p) {
410 s = decl->u.choice.choice[i].name;
411 break;
414 print_default(decl, s, pos);
417 static void print_choice_help(struct isl_arg *decl,
418 struct isl_prefixes *prefixes, void *opt)
420 int i;
421 int pos;
423 pos = print_arg_help(decl, prefixes, 0);
424 printf("=");
425 pos++;
427 for (i = 0; decl->u.choice.choice[i].name; ++i) {
428 if (i) {
429 printf("|");
430 pos++;
432 printf("%s", decl->u.choice.choice[i].name);
433 pos += strlen(decl->u.choice.choice[i].name);
436 pos = print_help_msg(decl, pos);
437 print_default_choice(decl, opt, pos);
439 printf("\n");
442 static void print_default_flags(struct isl_arg *decl, void *opt, int pos)
444 int i, first;
445 const char *default_prefix = "[default: ";
446 const char *default_suffix = "]";
447 int len = strlen(default_prefix) + strlen(default_suffix);
448 unsigned *p;
450 p = (unsigned *)(((char *) opt) + decl->offset);
451 for (i = 0; decl->u.flags.flags[i].name; ++i)
452 if ((*p & decl->u.flags.flags[i].mask) ==
453 decl->u.flags.flags[i].value)
454 len += strlen(decl->u.flags.flags[i].name);
456 if (!decl->help_msg) {
457 if (pos >= 29)
458 printf("\n%30s", "");
459 else
460 printf("%*s", 30 - pos, "");
461 } else {
462 if (pos + len >= 48)
463 printf("\n%30s", "");
464 else
465 printf(" ");
467 printf("%s", default_prefix);
469 for (first = 1, i = 0; decl->u.flags.flags[i].name; ++i)
470 if ((*p & decl->u.flags.flags[i].mask) ==
471 decl->u.flags.flags[i].value) {
472 if (!first)
473 printf(",");
474 printf("%s", decl->u.flags.flags[i].name);
475 first = 0;
478 printf("%s", default_suffix);
481 static void print_flags_help(struct isl_arg *decl,
482 struct isl_prefixes *prefixes, void *opt)
484 int i, j;
485 int pos;
487 pos = print_arg_help(decl, prefixes, 0);
488 printf("=");
489 pos++;
491 for (i = 0; decl->u.flags.flags[i].name; ++i) {
492 if (i) {
493 printf(",");
494 pos++;
496 for (j = i;
497 decl->u.flags.flags[j].mask == decl->u.flags.flags[i].mask;
498 ++j) {
499 if (j != i) {
500 printf("|");
501 pos++;
503 printf("%s", decl->u.flags.flags[j].name);
504 pos += strlen(decl->u.flags.flags[j].name);
506 i = j - 1;
509 pos = print_help_msg(decl, pos);
510 print_default_flags(decl, opt, pos);
512 printf("\n");
515 static void print_bool_help(struct isl_arg *decl,
516 struct isl_prefixes *prefixes, void *opt)
518 int pos;
519 unsigned *p = opt ? (unsigned *)(((char *) opt) + decl->offset) : NULL;
520 int no = p ? *p == 1 : 0;
521 pos = print_arg_help(decl, prefixes, no);
522 pos = print_help_msg(decl, pos);
523 if (decl->offset != (size_t) -1)
524 print_default(decl, no ? "yes" : "no", pos);
525 printf("\n");
528 static int print_argument_name(struct isl_arg *decl, const char *name, int pos)
530 printf("%c<%s>", decl->long_name ? '=' : ' ', name);
531 return pos + 3 + strlen(name);
534 static void print_int_help(struct isl_arg *decl,
535 struct isl_prefixes *prefixes, void *opt)
537 int pos;
538 char val[20];
539 int *p = (int *)(((char *) opt) + decl->offset);
540 pos = print_arg_help(decl, prefixes, 0);
541 pos = print_argument_name(decl, decl->argument_name, pos);
542 pos = print_help_msg(decl, pos);
543 snprintf(val, sizeof(val), "%d", *p);
544 print_default(decl, val, pos);
545 printf("\n");
548 static void print_long_help(struct isl_arg *decl,
549 struct isl_prefixes *prefixes, void *opt)
551 int pos;
552 long *p = (long *)(((char *) opt) + decl->offset);
553 pos = print_arg_help(decl, prefixes, 0);
554 if (*p != decl->u.l.default_selected) {
555 printf("[");
556 pos++;
558 printf("=long");
559 pos += 5;
560 if (*p != decl->u.l.default_selected) {
561 printf("]");
562 pos++;
564 print_help_msg(decl, pos);
565 printf("\n");
568 static void print_ulong_help(struct isl_arg *decl,
569 struct isl_prefixes *prefixes)
571 int pos;
572 pos = print_arg_help(decl, prefixes, 0);
573 printf("=ulong");
574 pos += 6;
575 print_help_msg(decl, pos);
576 printf("\n");
579 static void print_str_help(struct isl_arg *decl,
580 struct isl_prefixes *prefixes, void *opt)
582 int pos;
583 const char *a = decl->argument_name ? decl->argument_name : "string";
584 const char **p = (const char **)(((char *) opt) + decl->offset);
585 pos = print_arg_help(decl, prefixes, 0);
586 pos = print_argument_name(decl, a, pos);
587 pos = print_help_msg(decl, pos);
588 if (*p)
589 print_default(decl, *p, pos);
590 printf("\n");
593 static void print_str_list_help(struct isl_arg *decl,
594 struct isl_prefixes *prefixes)
596 int pos;
597 const char *a = decl->argument_name ? decl->argument_name : "string";
598 pos = print_arg_help(decl, prefixes, 0);
599 pos = print_argument_name(decl, a, pos);
600 pos = print_help_msg(decl, pos);
601 printf("\n");
604 static void print_help(struct isl_arg *arg,
605 struct isl_prefixes *prefixes, void *opt)
607 int i;
608 int any = 0;
610 for (i = 0; arg[i].type != isl_arg_end; ++i) {
611 if (arg[i].flags & ISL_ARG_HIDDEN)
612 continue;
613 switch (arg[i].type) {
614 case isl_arg_flags:
615 print_flags_help(&arg[i], prefixes, opt);
616 any = 1;
617 break;
618 case isl_arg_choice:
619 print_choice_help(&arg[i], prefixes, opt);
620 any = 1;
621 break;
622 case isl_arg_bool:
623 print_bool_help(&arg[i], prefixes, opt);
624 any = 1;
625 break;
626 case isl_arg_int:
627 print_int_help(&arg[i], prefixes, opt);
628 any = 1;
629 break;
630 case isl_arg_long:
631 print_long_help(&arg[i], prefixes, opt);
632 any = 1;
633 break;
634 case isl_arg_ulong:
635 print_ulong_help(&arg[i], prefixes);
636 any = 1;
637 break;
638 case isl_arg_str:
639 print_str_help(&arg[i], prefixes, opt);
640 any = 1;
641 break;
642 case isl_arg_str_list:
643 print_str_list_help(&arg[i], prefixes);
644 any = 1;
645 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 break;
657 for (i = 0; arg[i].type != isl_arg_end; ++i) {
658 void *child;
659 int first;
661 if (arg[i].type != isl_arg_child)
662 continue;
663 if (arg[i].flags & ISL_ARG_HIDDEN)
664 continue;
666 if (any)
667 printf("\n");
668 if (arg[i].help_msg)
669 printf(" %s\n", arg[i].help_msg);
670 if (arg[i].offset == (size_t) -1)
671 child = opt;
672 else
673 child = *(void **)(((char *) opt) + arg[i].offset);
674 first = add_prefix(prefixes, arg[i].long_name);
675 print_help(arg[i].u.child.child->args, prefixes, child);
676 drop_prefix(prefixes, first);
677 any = 1;
681 static const char *prog_name(const char *prog)
683 const char *slash;
685 slash = strrchr(prog, '/');
686 if (slash)
687 prog = slash + 1;
688 if (strncmp(prog, "lt-", 3) == 0)
689 prog += 3;
691 return prog;
694 static int any_version(struct isl_arg *decl)
696 int i;
698 for (i = 0; decl[i].type != isl_arg_end; ++i) {
699 switch (decl[i].type) {
700 case isl_arg_version:
701 return 1;
702 case isl_arg_child:
703 if (any_version(decl[i].u.child.child->args))
704 return 1;
705 break;
706 default:
707 break;
711 return 0;
714 static void print_help_and_exit(struct isl_arg *arg, const char *prog,
715 void *opt)
717 int i;
718 struct isl_prefixes prefixes = { 0 };
720 printf("Usage: %s [OPTION...]", prog_name(prog));
722 for (i = 0; arg[i].type != isl_arg_end; ++i)
723 if (arg[i].type == isl_arg_arg)
724 printf(" %s", arg[i].argument_name);
726 printf("\n\n");
728 print_help(arg, &prefixes, opt);
729 printf("\n");
730 if (any_version(arg))
731 printf(" -V, --version\n");
732 print_bool_help(help_arg, NULL, NULL);
734 for (i = 0; arg[i].type != isl_arg_end; ++i) {
735 if (arg[i].type != isl_arg_footer)
736 continue;
737 wrap_msg(arg[i].help_msg, 0, 0);
738 printf("\n");
741 exit(0);
744 static int match_long_name(struct isl_arg *decl,
745 const char *start, const char *end)
747 do {
748 if (end - start == strlen(decl->long_name) &&
749 !strncmp(start, decl->long_name, end - start))
750 return 1;
751 } while ((++decl)->type == isl_arg_alias);
753 return 0;
756 static const char *skip_dash_dash(struct isl_arg *decl, const char *arg)
758 if (!strncmp(arg, "--", 2))
759 return arg + 2;
760 if ((decl->flags & ISL_ARG_SINGLE_DASH) && arg[0] == '-')
761 return arg + 1;
762 return NULL;
765 static const char *skip_name(struct isl_arg *decl, const char *arg,
766 struct isl_prefixes *prefixes, int need_argument, int *has_argument)
768 const char *equal;
769 const char *name;
770 const char *end;
772 if (arg[0] == '-' && arg[1] && arg[1] == decl->short_name) {
773 if (need_argument && !arg[2])
774 return NULL;
775 if (has_argument)
776 *has_argument = arg[2] != '\0';
777 return arg + 2;
779 if (!decl->long_name)
780 return NULL;
782 name = skip_dash_dash(decl, arg);
783 if (!name)
784 return NULL;
786 equal = strchr(name, '=');
787 if (need_argument && !equal)
788 return NULL;
790 if (has_argument)
791 *has_argument = !!equal;
792 end = equal ? equal : name + strlen(name);
794 name = skip_prefixes(name, prefixes, NULL);
796 if (!match_long_name(decl, name, end))
797 return NULL;
799 return equal ? equal + 1 : end;
802 static int parse_choice_option(struct isl_arg *decl, char **arg,
803 struct isl_prefixes *prefixes, void *opt)
805 int i;
806 int has_argument;
807 const char *choice;
809 choice = skip_name(decl, arg[0], prefixes, 0, &has_argument);
810 if (!choice)
811 return 0;
813 if (!has_argument && (!arg[1] || arg[1][0] == '-')) {
814 unsigned u = decl->u.choice.default_selected;
815 *(unsigned *)(((char *)opt) + decl->offset) = u;
816 if (decl->u.choice.set)
817 decl->u.choice.set(opt, u);
819 return 1;
822 if (!has_argument)
823 choice = arg[1];
825 for (i = 0; decl->u.choice.choice[i].name; ++i) {
826 unsigned u;
828 if (strcmp(choice, decl->u.choice.choice[i].name))
829 continue;
831 u = decl->u.choice.choice[i].value;
832 *(unsigned *)(((char *)opt) + decl->offset) = u;
833 if (decl->u.choice.set)
834 decl->u.choice.set(opt, u);
836 return has_argument ? 1 : 2;
839 return 0;
842 static int set_flag(struct isl_arg *decl, unsigned *val, const char *flag,
843 size_t len)
845 int i;
847 for (i = 0; decl->u.flags.flags[i].name; ++i) {
848 if (strncmp(flag, decl->u.flags.flags[i].name, len))
849 continue;
851 *val &= ~decl->u.flags.flags[i].mask;
852 *val |= decl->u.flags.flags[i].value;
854 return 1;
857 return 0;
860 static int parse_flags_option(struct isl_arg *decl, char **arg,
861 struct isl_prefixes *prefixes, void *opt)
863 int has_argument;
864 const char *flags;
865 const char *comma;
866 unsigned val;
868 flags = skip_name(decl, arg[0], prefixes, 0, &has_argument);
869 if (!flags)
870 return 0;
872 if (!has_argument && !arg[1])
873 return 0;
875 if (!has_argument)
876 flags = arg[1];
878 val = 0;
880 while ((comma = strchr(flags, ',')) != NULL) {
881 if (!set_flag(decl, &val, flags, comma - flags))
882 return 0;
883 flags = comma + 1;
885 if (!set_flag(decl, &val, flags, strlen(flags)))
886 return 0;
888 *(unsigned *)(((char *)opt) + decl->offset) = val;
890 return has_argument ? 1 : 2;
893 static int parse_bool_option(struct isl_arg *decl, char **arg,
894 struct isl_prefixes *prefixes, void *opt)
896 const char *name;
897 unsigned *p = (unsigned *)(((char *)opt) + decl->offset);
898 int next_prefix;
900 if (skip_name(decl, arg[0], prefixes, 0, NULL)) {
901 if ((decl->flags & ISL_ARG_BOOL_ARG) && arg[1]) {
902 char *endptr;
903 int val = strtol(arg[1], &endptr, 0);
904 if (*endptr == '\0' && (val == 0 || val == 1)) {
905 if (decl->offset != (size_t) -1)
906 *p = val;
907 if (decl->u.b.set)
908 decl->u.b.set(opt, val);
909 return 2;
912 if (decl->offset != (size_t) -1)
913 *p = 1;
914 if (decl->u.b.set)
915 decl->u.b.set(opt, 1);
917 return 1;
920 if (!decl->long_name)
921 return 0;
923 name = skip_dash_dash(decl, arg[0]);
924 if (!name)
925 return 0;
927 next_prefix = 0;
928 name = skip_prefixes(name, prefixes, &next_prefix);
930 if (strncmp(name, "no-", 3))
931 return 0;
932 name += 3;
934 name = skip_prefixes(name, prefixes, &next_prefix);
936 if (match_long_name(decl, name, name + strlen(name))) {
937 if (decl->offset != (size_t) -1)
938 *p = 0;
939 if (decl->u.b.set)
940 decl->u.b.set(opt, 0);
942 return 1;
945 return 0;
948 static int parse_str_option(struct isl_arg *decl, char **arg,
949 struct isl_prefixes *prefixes, void *opt)
951 int has_argument;
952 const char *s;
953 char **p = (char **)(((char *)opt) + decl->offset);
955 s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
956 if (!s)
957 return 0;
959 if (has_argument) {
960 free(*p);
961 *p = strdup(s);
962 return 1;
965 if (arg[1]) {
966 free(*p);
967 *p = strdup(arg[1]);
968 return 2;
971 return 0;
974 static int isl_arg_str_list_append(struct isl_arg *decl, void *opt,
975 const char *s)
977 int *n = (int *)(((char *) opt) + decl->u.str_list.offset_n);
978 char **list = *(char ***)(((char *) opt) + decl->offset);
980 list = realloc(list, (*n + 1) * sizeof(char *));
981 if (!list)
982 return -1;
983 *(char ***)(((char *) opt) + decl->offset) = list;
984 list[*n] = strdup(s);
985 (*n)++;
986 return 0;
989 static int parse_str_list_option(struct isl_arg *decl, char **arg,
990 struct isl_prefixes *prefixes, void *opt)
992 int has_argument;
993 const char *s;
995 s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
996 if (!s)
997 return 0;
999 if (has_argument) {
1000 isl_arg_str_list_append(decl, opt, s);
1001 return 1;
1004 if (arg[1]) {
1005 isl_arg_str_list_append(decl, opt, arg[1]);
1006 return 2;
1009 return 0;
1012 static int parse_int_option(struct isl_arg *decl, char **arg,
1013 struct isl_prefixes *prefixes, void *opt)
1015 int has_argument;
1016 const char *val;
1017 char *endptr;
1018 int *p = (int *)(((char *)opt) + decl->offset);
1020 val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1021 if (!val)
1022 return 0;
1024 if (has_argument) {
1025 *p = atoi(val);
1026 return 1;
1029 if (arg[1]) {
1030 int i = strtol(arg[1], &endptr, 0);
1031 if (*endptr == '\0') {
1032 *p = i;
1033 return 2;
1037 return 0;
1040 static int parse_long_option(struct isl_arg *decl, char **arg,
1041 struct isl_prefixes *prefixes, void *opt)
1043 int has_argument;
1044 const char *val;
1045 char *endptr;
1046 long *p = (long *)(((char *)opt) + decl->offset);
1048 val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1049 if (!val)
1050 return 0;
1052 if (has_argument) {
1053 long l = strtol(val, NULL, 0);
1054 *p = l;
1055 if (decl->u.l.set)
1056 decl->u.l.set(opt, l);
1057 return 1;
1060 if (arg[1]) {
1061 long l = strtol(arg[1], &endptr, 0);
1062 if (*endptr == '\0') {
1063 *p = l;
1064 if (decl->u.l.set)
1065 decl->u.l.set(opt, l);
1066 return 2;
1070 if (decl->u.l.default_value != decl->u.l.default_selected) {
1071 *p = decl->u.l.default_selected;
1072 if (decl->u.l.set)
1073 decl->u.l.set(opt, decl->u.l.default_selected);
1074 return 1;
1077 return 0;
1080 static int parse_ulong_option(struct isl_arg *decl, char **arg,
1081 struct isl_prefixes *prefixes, void *opt)
1083 int has_argument;
1084 const char *val;
1085 char *endptr;
1086 unsigned long *p = (unsigned long *)(((char *)opt) + decl->offset);
1088 val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
1089 if (!val)
1090 return 0;
1092 if (has_argument) {
1093 *p = strtoul(val, NULL, 0);
1094 return 1;
1097 if (arg[1]) {
1098 unsigned long ul = strtoul(arg[1], &endptr, 0);
1099 if (*endptr == '\0') {
1100 *p = ul;
1101 return 2;
1105 return 0;
1108 static int parse_option(struct isl_arg *decl, char **arg,
1109 struct isl_prefixes *prefixes, void *opt);
1111 static int parse_child_option(struct isl_arg *decl, char **arg,
1112 struct isl_prefixes *prefixes, void *opt)
1114 void *child;
1115 int first, parsed;
1117 if (decl->offset == (size_t) -1)
1118 child = opt;
1119 else
1120 child = *(void **)(((char *)opt) + decl->offset);
1122 first = add_prefix(prefixes, decl->long_name);
1123 parsed = parse_option(decl->u.child.child->args, arg, prefixes, child);
1124 drop_prefix(prefixes, first);
1126 return parsed;
1129 static int parse_option(struct isl_arg *decl, char **arg,
1130 struct isl_prefixes *prefixes, void *opt)
1132 int i;
1134 for (i = 0; decl[i].type != isl_arg_end; ++i) {
1135 int parsed = 0;
1136 switch (decl[i].type) {
1137 case isl_arg_choice:
1138 parsed = parse_choice_option(&decl[i], arg,
1139 prefixes, opt);
1140 break;
1141 case isl_arg_flags:
1142 parsed = parse_flags_option(&decl[i], arg,
1143 prefixes, opt);
1144 break;
1145 case isl_arg_int:
1146 parsed = parse_int_option(&decl[i], arg, prefixes, opt);
1147 break;
1148 case isl_arg_long:
1149 parsed = parse_long_option(&decl[i], arg,
1150 prefixes, opt);
1151 break;
1152 case isl_arg_ulong:
1153 parsed = parse_ulong_option(&decl[i], arg,
1154 prefixes, opt);
1155 break;
1156 case isl_arg_bool:
1157 parsed = parse_bool_option(&decl[i], arg,
1158 prefixes, opt);
1159 break;
1160 case isl_arg_str:
1161 parsed = parse_str_option(&decl[i], arg, prefixes, opt);
1162 break;
1163 case isl_arg_str_list:
1164 parsed = parse_str_list_option(&decl[i], arg, prefixes,
1165 opt);
1166 break;
1167 case isl_arg_child:
1168 parsed = parse_child_option(&decl[i], arg,
1169 prefixes, opt);
1170 break;
1171 case isl_arg_alias:
1172 case isl_arg_arg:
1173 case isl_arg_footer:
1174 case isl_arg_user:
1175 case isl_arg_version:
1176 case isl_arg_end:
1177 break;
1179 if (parsed)
1180 return parsed;
1183 return 0;
1186 static void print_version(struct isl_arg *decl)
1188 int i;
1190 for (i = 0; decl[i].type != isl_arg_end; ++i) {
1191 switch (decl[i].type) {
1192 case isl_arg_version:
1193 decl[i].u.version.print_version();
1194 break;
1195 case isl_arg_child:
1196 print_version(decl[i].u.child.child->args);
1197 break;
1198 default:
1199 break;
1204 static void print_version_and_exit(struct isl_arg *decl)
1206 print_version(decl);
1208 exit(0);
1211 static int drop_argument(int argc, char **argv, int drop, int n)
1213 for (; drop + n < argc; ++drop)
1214 argv[drop] = argv[drop + n];
1216 return argc - n;
1219 static int n_arg(struct isl_arg *arg)
1221 int i;
1222 int n_arg = 0;
1224 for (i = 0; arg[i].type != isl_arg_end; ++i)
1225 if (arg[i].type == isl_arg_arg)
1226 n_arg++;
1228 return n_arg;
1231 static int next_arg(struct isl_arg *arg, int a)
1233 for (++a; arg[a].type != isl_arg_end; ++a)
1234 if (arg[a].type == isl_arg_arg)
1235 return a;
1237 return -1;
1240 /* Unless ISL_ARG_SKIP_HELP is set, check if "arg" is
1241 * equal to "--help" and if so call print_help_and_exit.
1243 static void check_help(struct isl_args *args, char *arg, char *prog, void *opt,
1244 unsigned flags)
1246 if (ISL_FL_ISSET(flags, ISL_ARG_SKIP_HELP))
1247 return;
1249 if (strcmp(arg, "--help") == 0)
1250 print_help_and_exit(args->args, prog, opt);
1253 int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
1254 unsigned flags)
1256 int a = -1;
1257 int skip = 0;
1258 int i;
1259 int n;
1260 struct isl_prefixes prefixes = { 0 };
1262 n = n_arg(args->args);
1264 for (i = 1; i < argc; ++i) {
1265 if ((strcmp(argv[i], "--version") == 0 ||
1266 strcmp(argv[i], "-V") == 0) && any_version(args->args))
1267 print_version_and_exit(args->args);
1270 while (argc > 1 + skip) {
1271 int parsed;
1272 if (argv[1 + skip][0] != '-') {
1273 a = next_arg(args->args, a);
1274 if (a >= 0) {
1275 char **p;
1276 p = (char **)(((char *)opt)+args->args[a].offset);
1277 free(*p);
1278 *p = strdup(argv[1 + skip]);
1279 argc = drop_argument(argc, argv, 1 + skip, 1);
1280 --n;
1281 } else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
1282 fprintf(stderr, "%s: extra argument: %s\n",
1283 prog_name(argv[0]), argv[1 + skip]);
1284 exit(-1);
1285 } else
1286 ++skip;
1287 continue;
1289 check_help(args, argv[1 + skip], argv[0], opt, flags);
1290 parsed = parse_option(args->args, &argv[1 + skip],
1291 &prefixes, opt);
1292 if (parsed)
1293 argc = drop_argument(argc, argv, 1 + skip, parsed);
1294 else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
1295 fprintf(stderr, "%s: unrecognized option: %s\n",
1296 prog_name(argv[0]), argv[1 + skip]);
1297 exit(-1);
1298 } else
1299 ++skip;
1302 if (n > 0) {
1303 fprintf(stderr, "%s: expecting %d more argument(s)\n",
1304 prog_name(argv[0]), n);
1305 exit(-1);
1308 return argc;