2 * Copyright 2008-2009 Katholieke Universiteit Leuven
4 * Use of this software is governed by the GNU LGPLv2.1 license
6 * Written by Sven Verdoolaege, K.U.Leuven, Departement
7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
17 static struct isl_arg help_arg
[] = {
18 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 *(unsigned *)(((char *)opt
) + arg
->offset
) = arg
->u
.choice
.default_value
;
27 static void set_default_flags(struct isl_arg
*arg
, void *opt
)
29 *(unsigned *)(((char *)opt
) + arg
->offset
) = arg
->u
.flags
.default_value
;
32 static void set_default_bool(struct isl_arg
*arg
, void *opt
)
34 if (arg
->offset
== (size_t) -1)
36 *(unsigned *)(((char *)opt
) + arg
->offset
) = arg
->u
.b
.default_value
;
39 static void set_default_child(struct isl_arg
*arg
, void *opt
)
41 void *child
= calloc(1, arg
->u
.child
.size
);
44 isl_arg_set_defaults(arg
->u
.child
.child
, child
);
46 *(void **)(((char *)opt
) + arg
->offset
) = child
;
49 static void set_default_user(struct isl_arg
*arg
, void *opt
)
51 arg
->u
.user
.init(((char *)opt
) + arg
->offset
);
54 static void set_default_int(struct isl_arg
*arg
, void *opt
)
56 *(int *)(((char *)opt
) + arg
->offset
) = arg
->u
.i
.default_value
;
59 static void set_default_long(struct isl_arg
*arg
, void *opt
)
61 *(long *)(((char *)opt
) + arg
->offset
) = arg
->u
.l
.default_value
;
64 static void set_default_ulong(struct isl_arg
*arg
, void *opt
)
66 *(unsigned long *)(((char *)opt
) + arg
->offset
) = arg
->u
.ul
.default_value
;
69 static void set_default_str(struct isl_arg
*arg
, void *opt
)
71 const char *str
= NULL
;
72 if (arg
->u
.str
.default_value
)
73 str
= strdup(arg
->u
.str
.default_value
);
74 *(const char **)(((char *)opt
) + arg
->offset
) = str
;
77 void isl_arg_set_defaults(struct isl_arg
*arg
, void *opt
)
81 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
82 switch (arg
[i
].type
) {
84 set_default_choice(&arg
[i
], opt
);
87 set_default_flags(&arg
[i
], opt
);
90 set_default_bool(&arg
[i
], opt
);
93 set_default_child(&arg
[i
], opt
);
96 set_default_user(&arg
[i
], opt
);
99 set_default_int(&arg
[i
], opt
);
102 set_default_long(&arg
[i
], opt
);
105 set_default_ulong(&arg
[i
], opt
);
109 set_default_str(&arg
[i
], opt
);
112 case isl_arg_version
:
119 void isl_arg_free(struct isl_arg
*arg
, void *opt
)
126 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
127 switch (arg
[i
].type
) {
129 isl_arg_free(arg
[i
].u
.child
.child
,
130 *(void **)(((char *)opt
) + arg
[i
].offset
));
134 free(*(char **)(((char *)opt
) + arg
[i
].offset
));
137 if (arg
[i
].u
.user
.clear
)
138 arg
[i
].u
.user
.clear(((char *)opt
) + arg
[i
].offset
);
147 case isl_arg_version
:
156 static int print_arg_help(struct isl_arg
*decl
, const char *prefix
, int no
)
160 if (!decl
->long_name
) {
161 printf(" -%c", decl
->short_name
);
165 if (decl
->short_name
) {
166 printf(" -%c, --", decl
->short_name
);
168 } else if (decl
->flags
& ISL_ARG_SINGLE_DASH
) {
177 printf("%s-", prefix
);
178 len
+= strlen(prefix
) + 1;
184 printf("%s", decl
->long_name
);
185 len
+= strlen(decl
->long_name
);
187 while ((++decl
)->type
== isl_arg_alias
) {
194 printf("%s", decl
->long_name
);
195 len
+= strlen(decl
->long_name
);
201 const void *isl_memrchr(const void *s
, int c
, size_t n
)
210 static int print_help_msg(struct isl_arg
*decl
, int pos
)
219 printf("\n%30s", "");
221 printf("%*s", 30 - pos
, "");
226 const char *space
= isl_memrchr(s
, ' ', 45);
230 space
= strchr(s
+ 45, ' ');
234 printf("%.*s", l
, s
);
237 printf("\n%30s", "");
244 static void print_default(struct isl_arg
*decl
, const char *def
, int pos
)
247 const char *default_prefix
= "[default: ";
248 const char *default_suffix
= "]";
251 len
= strlen(default_prefix
) + strlen(def
) + strlen(default_suffix
);
253 if (!decl
->help_msg
) {
255 printf("\n%30s", "");
257 printf("%*s", 30 - pos
, "");
261 printf("\n%30s", "");
265 printf("%s%s%s", default_prefix
, def
, default_suffix
);
268 static void print_default_choice(struct isl_arg
*decl
, int pos
)
271 const char *s
= "none";
273 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
)
274 if (decl
->u
.choice
.choice
[i
].value
== decl
->u
.choice
.default_value
) {
275 s
= decl
->u
.choice
.choice
[i
].name
;
279 print_default(decl
, s
, pos
);
282 static void print_choice_help(struct isl_arg
*decl
, const char *prefix
)
287 pos
= print_arg_help(decl
, prefix
, 0);
291 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
) {
296 printf("%s", decl
->u
.choice
.choice
[i
].name
);
297 pos
+= strlen(decl
->u
.choice
.choice
[i
].name
);
300 pos
= print_help_msg(decl
, pos
);
301 print_default_choice(decl
, pos
);
306 static void print_default_flags(struct isl_arg
*decl
, int pos
)
309 const char *default_prefix
= "[default: ";
310 const char *default_suffix
= "]";
311 int len
= strlen(default_prefix
) + strlen(default_suffix
);
313 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
)
314 if ((decl
->u
.flags
.default_value
& decl
->u
.flags
.flags
[i
].mask
) ==
315 decl
->u
.flags
.flags
[i
].value
)
316 len
+= strlen(decl
->u
.flags
.flags
[i
].name
);
318 if (!decl
->help_msg
) {
320 printf("\n%30s", "");
322 printf("%*s", 30 - pos
, "");
326 printf("\n%30s", "");
330 printf("%s", default_prefix
);
332 for (first
= 1, i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
)
333 if ((decl
->u
.flags
.default_value
& decl
->u
.flags
.flags
[i
].mask
) ==
334 decl
->u
.flags
.flags
[i
].value
) {
337 printf("%s", decl
->u
.flags
.flags
[i
].name
);
341 printf("%s", default_suffix
);
344 static void print_flags_help(struct isl_arg
*decl
, const char *prefix
)
349 pos
= print_arg_help(decl
, prefix
, 0);
353 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
) {
359 decl
->u
.flags
.flags
[j
].mask
== decl
->u
.flags
.flags
[i
].mask
;
365 printf("%s", decl
->u
.flags
.flags
[j
].name
);
366 pos
+= strlen(decl
->u
.flags
.flags
[j
].name
);
371 pos
= print_help_msg(decl
, pos
);
372 print_default_flags(decl
, pos
);
377 static void print_bool_help(struct isl_arg
*decl
, const char *prefix
)
380 int no
= decl
->u
.b
.default_value
== 1;
381 pos
= print_arg_help(decl
, prefix
, no
);
382 pos
= print_help_msg(decl
, pos
);
383 if (decl
->offset
!= (size_t) -1)
384 print_default(decl
, no
? "yes" : "no", pos
);
388 static int print_argument_name(struct isl_arg
*decl
, const char *name
, int pos
)
390 printf("%c<%s>", decl
->long_name
? '=' : ' ', name
);
391 return pos
+ 3 + strlen(name
);
394 static void print_int_help(struct isl_arg
*decl
, const char *prefix
)
398 pos
= print_arg_help(decl
, prefix
, 0);
399 pos
= print_argument_name(decl
, decl
->argument_name
, pos
);
400 pos
= print_help_msg(decl
, pos
);
401 snprintf(val
, sizeof(val
), "%d", decl
->u
.i
.default_value
);
402 print_default(decl
, val
, pos
);
406 static void print_long_help(struct isl_arg
*decl
, const char *prefix
)
409 pos
= print_arg_help(decl
, prefix
, 0);
410 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
416 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
420 print_help_msg(decl
, pos
);
424 static void print_ulong_help(struct isl_arg
*decl
, const char *prefix
)
427 pos
= print_arg_help(decl
, prefix
, 0);
430 print_help_msg(decl
, pos
);
434 static void print_str_help(struct isl_arg
*decl
, const char *prefix
)
437 const char *a
= decl
->argument_name
? decl
->argument_name
: "string";
438 pos
= print_arg_help(decl
, prefix
, 0);
439 pos
= print_argument_name(decl
, a
, pos
);
440 pos
= print_help_msg(decl
, pos
);
441 if (decl
->u
.str
.default_value
)
442 print_default(decl
, decl
->u
.str
.default_value
, pos
);
446 static void print_help(struct isl_arg
*arg
, const char *prefix
)
450 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
451 if (arg
[i
].flags
& ISL_ARG_HIDDEN
)
453 switch (arg
[i
].type
) {
455 print_flags_help(&arg
[i
], prefix
);
458 print_choice_help(&arg
[i
], prefix
);
461 print_bool_help(&arg
[i
], prefix
);
464 print_int_help(&arg
[i
], prefix
);
467 print_long_help(&arg
[i
], prefix
);
470 print_ulong_help(&arg
[i
], prefix
);
473 print_str_help(&arg
[i
], prefix
);
476 case isl_arg_version
:
485 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
486 if (arg
[i
].type
!= isl_arg_child
)
488 if (arg
[i
].flags
& ISL_ARG_HIDDEN
)
493 printf(" %s\n", arg
[i
].help_msg
);
494 print_help(arg
[i
].u
.child
.child
, arg
[i
].long_name
);
498 static const char *prog_name(const char *prog
)
502 slash
= strrchr(prog
, '/');
505 if (strncmp(prog
, "lt-", 3) == 0)
511 static int any_version(struct isl_arg
*decl
)
515 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
516 switch (decl
[i
].type
) {
517 case isl_arg_version
:
520 if (any_version(decl
[i
].u
.child
.child
))
531 static void print_help_and_exit(struct isl_arg
*arg
, const char *prog
)
535 printf("Usage: %s [OPTION...]", prog_name(prog
));
537 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
)
538 if (arg
[i
].type
== isl_arg_arg
)
539 printf(" %s", arg
[i
].argument_name
);
543 print_help(arg
, NULL
);
545 if (any_version(arg
))
546 printf(" -V, --version\n");
547 print_bool_help(help_arg
, NULL
);
552 static int match_long_name(struct isl_arg
*decl
,
553 const char *start
, const char *end
)
556 if (end
- start
== strlen(decl
->long_name
) &&
557 !strncmp(start
, decl
->long_name
, end
- start
))
559 } while ((++decl
)->type
== isl_arg_alias
);
564 static const char *skip_dash_dash(struct isl_arg
*decl
, const char *arg
)
566 if (!strncmp(arg
, "--", 2))
568 if ((decl
->flags
& ISL_ARG_SINGLE_DASH
) && arg
[0] == '-')
573 static const char *skip_name(struct isl_arg
*decl
, const char *arg
,
574 const char *prefix
, int need_argument
, int *has_argument
)
580 if (arg
[0] == '-' && arg
[1] && arg
[1] == decl
->short_name
) {
581 if (need_argument
&& !arg
[2])
584 *has_argument
= arg
[2] != '\0';
587 if (!decl
->long_name
)
590 name
= skip_dash_dash(decl
, arg
);
594 equal
= strchr(name
, '=');
595 if (need_argument
&& !equal
)
599 *has_argument
= !!equal
;
600 end
= equal
? equal
: name
+ strlen(name
);
603 size_t prefix_len
= strlen(prefix
);
604 if (strncmp(name
, prefix
, prefix_len
) == 0 &&
605 name
[prefix_len
] == '-')
606 name
+= prefix_len
+ 1;
609 if (!match_long_name(decl
, name
, end
))
612 return equal
? equal
+ 1 : end
;
615 static int parse_choice_option(struct isl_arg
*decl
, char **arg
,
616 const char *prefix
, void *opt
)
622 choice
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
626 if (!has_argument
&& (!arg
[1] || arg
[1][0] == '-')) {
627 unsigned u
= decl
->u
.choice
.default_selected
;
628 if (decl
->u
.choice
.set
)
629 decl
->u
.choice
.set(opt
, u
);
631 *(unsigned *)(((char *)opt
) + decl
->offset
) = u
;
639 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
) {
642 if (strcmp(choice
, decl
->u
.choice
.choice
[i
].name
))
645 u
= decl
->u
.choice
.choice
[i
].value
;
646 if (decl
->u
.choice
.set
)
647 decl
->u
.choice
.set(opt
, u
);
649 *(unsigned *)(((char *)opt
) + decl
->offset
) = u
;
651 return has_argument
? 1 : 2;
657 static int set_flag(struct isl_arg
*decl
, unsigned *val
, const char *flag
,
662 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
) {
663 if (strncmp(flag
, decl
->u
.flags
.flags
[i
].name
, len
))
666 *val
&= ~decl
->u
.flags
.flags
[i
].mask
;
667 *val
|= decl
->u
.flags
.flags
[i
].value
;
675 static int parse_flags_option(struct isl_arg
*decl
, char **arg
,
676 const char *prefix
, void *opt
)
683 flags
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
687 if (!has_argument
&& !arg
[1])
693 val
= *(unsigned *)(((char *)opt
) + decl
->offset
);
695 while ((comma
= strchr(flags
, ',')) != NULL
) {
696 if (!set_flag(decl
, &val
, flags
, comma
- flags
))
700 if (!set_flag(decl
, &val
, flags
, strlen(flags
)))
703 *(unsigned *)(((char *)opt
) + decl
->offset
) = val
;
705 return has_argument
? 1 : 2;
708 static int parse_bool_option(struct isl_arg
*decl
, char **arg
,
709 const char *prefix
, void *opt
)
712 unsigned *p
= (unsigned *)(((char *)opt
) + decl
->offset
);
714 if (skip_name(decl
, arg
[0], prefix
, 0, NULL
)) {
715 if ((decl
->flags
&& ISL_ARG_BOOL_ARG
) && arg
[1]) {
717 int val
= strtol(arg
[1], &endptr
, 0);
718 if (*endptr
== '\0' && (val
== 0 || val
== 1)) {
720 decl
->u
.b
.set(opt
, val
);
721 else if (decl
->offset
!= (size_t) -1)
727 decl
->u
.b
.set(opt
, 1);
728 else if (decl
->offset
!= (size_t) -1)
734 if (!decl
->long_name
)
737 name
= skip_dash_dash(decl
, arg
[0]);
742 size_t prefix_len
= strlen(prefix
);
743 if (strncmp(name
, prefix
, prefix_len
) == 0 &&
744 name
[prefix_len
] == '-') {
745 name
+= prefix_len
+ 1;
750 if (strncmp(name
, "no-", 3))
755 size_t prefix_len
= strlen(prefix
);
756 if (strncmp(name
, prefix
, prefix_len
) == 0 &&
757 name
[prefix_len
] == '-')
758 name
+= prefix_len
+ 1;
761 if (match_long_name(decl
, name
, name
+ strlen(name
))) {
763 decl
->u
.b
.set(opt
, 0);
764 else if (decl
->offset
!= (size_t) -1)
773 static int parse_str_option(struct isl_arg
*decl
, char **arg
,
774 const char *prefix
, void *opt
)
778 char **p
= (char **)(((char *)opt
) + decl
->offset
);
780 s
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
799 static int parse_int_option(struct isl_arg
*decl
, char **arg
,
800 const char *prefix
, void *opt
)
805 int *p
= (int *)(((char *)opt
) + decl
->offset
);
807 val
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
817 int i
= strtol(arg
[1], &endptr
, 0);
818 if (*endptr
== '\0') {
827 static int parse_long_option(struct isl_arg
*decl
, char **arg
,
828 const char *prefix
, void *opt
)
833 long *p
= (long *)(((char *)opt
) + decl
->offset
);
835 val
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
840 long l
= strtol(val
, NULL
, 0);
842 decl
->u
.l
.set(opt
, l
);
849 long l
= strtol(arg
[1], &endptr
, 0);
850 if (*endptr
== '\0') {
852 decl
->u
.l
.set(opt
, l
);
859 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
861 decl
->u
.l
.set(opt
, decl
->u
.l
.default_selected
);
863 *p
= decl
->u
.l
.default_selected
;
870 static int parse_ulong_option(struct isl_arg
*decl
, char **arg
,
871 const char *prefix
, void *opt
)
876 unsigned long *p
= (unsigned long *)(((char *)opt
) + decl
->offset
);
878 val
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
883 *p
= strtoul(val
, NULL
, 0);
888 unsigned long ul
= strtoul(arg
[1], &endptr
, 0);
889 if (*endptr
== '\0') {
898 static int parse_option(struct isl_arg
*decl
, char **arg
,
899 const char *prefix
, void *opt
);
901 static int parse_child_option(struct isl_arg
*decl
, char **arg
, void *opt
)
903 return parse_option(decl
->u
.child
.child
, arg
, decl
->long_name
,
904 *(void **)(((char *)opt
) + decl
->offset
));
907 static int parse_option(struct isl_arg
*decl
, char **arg
,
908 const char *prefix
, void *opt
)
912 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
914 switch (decl
[i
].type
) {
916 parsed
= parse_choice_option(&decl
[i
], arg
, prefix
, opt
);
919 parsed
= parse_flags_option(&decl
[i
], arg
, prefix
, opt
);
922 parsed
= parse_int_option(&decl
[i
], arg
, prefix
, opt
);
925 parsed
= parse_long_option(&decl
[i
], arg
, prefix
, opt
);
928 parsed
= parse_ulong_option(&decl
[i
], arg
, prefix
, opt
);
931 parsed
= parse_bool_option(&decl
[i
], arg
, prefix
, opt
);
934 parsed
= parse_str_option(&decl
[i
], arg
, prefix
, opt
);
937 parsed
= parse_child_option(&decl
[i
], arg
, opt
);
942 case isl_arg_version
:
953 static void print_version(struct isl_arg
*decl
)
957 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
958 switch (decl
[i
].type
) {
959 case isl_arg_version
:
960 decl
[i
].u
.version
.print_version();
963 print_version(decl
[i
].u
.child
.child
);
971 static void print_version_and_exit(struct isl_arg
*decl
)
978 static int drop_argument(int argc
, char **argv
, int drop
, int n
)
980 for (; drop
< argc
; ++drop
)
981 argv
[drop
] = argv
[drop
+ n
];
986 static int n_arg(struct isl_arg
*arg
)
991 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
)
992 if (arg
[i
].type
== isl_arg_arg
)
998 static int next_arg(struct isl_arg
*arg
, int a
)
1000 for (++a
; arg
[a
].type
!= isl_arg_end
; ++a
)
1001 if (arg
[a
].type
== isl_arg_arg
)
1007 int isl_arg_parse(struct isl_arg
*arg
, int argc
, char **argv
, void *opt
,
1017 for (i
= 1; i
< argc
; ++i
) {
1018 if (strcmp(argv
[i
], "--help") == 0)
1019 print_help_and_exit(arg
, argv
[0]);
1022 for (i
= 1; i
< argc
; ++i
) {
1023 if ((strcmp(argv
[i
], "--version") == 0 ||
1024 strcmp(argv
[i
], "-V") == 0) && any_version(arg
))
1025 print_version_and_exit(arg
);
1028 while (argc
> 1 + skip
) {
1030 if (argv
[1 + skip
][0] != '-') {
1031 a
= next_arg(arg
, a
);
1034 p
= (char **)(((char *)opt
)+arg
[a
].offset
);
1036 *p
= strdup(argv
[1 + skip
]);
1037 argc
= drop_argument(argc
, argv
, 1 + skip
, 1);
1039 } else if (ISL_FL_ISSET(flags
, ISL_ARG_ALL
)) {
1040 fprintf(stderr
, "%s: extra argument: %s\n",
1041 prog_name(argv
[0]), argv
[1 + skip
]);
1047 parsed
= parse_option(arg
, &argv
[1 + skip
], NULL
, opt
);
1049 argc
= drop_argument(argc
, argv
, 1 + skip
, parsed
);
1050 else if (ISL_FL_ISSET(flags
, ISL_ARG_ALL
)) {
1051 fprintf(stderr
, "%s: unrecognized option: %s\n",
1052 prog_name(argv
[0]), argv
[1 + skip
]);
1059 fprintf(stderr
, "%s: expecting %d more argument(s)\n",
1060 prog_name(argv
[0]), n
);