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_long(struct isl_arg
*arg
, void *opt
)
56 *(long *)(((char *)opt
) + arg
->offset
) = arg
->u
.l
.default_value
;
59 static void set_default_ulong(struct isl_arg
*arg
, void *opt
)
61 *(unsigned long *)(((char *)opt
) + arg
->offset
) = arg
->u
.ul
.default_value
;
64 static void set_default_str(struct isl_arg
*arg
, void *opt
)
66 const char *str
= NULL
;
67 if (arg
->u
.str
.default_value
)
68 str
= strdup(arg
->u
.str
.default_value
);
69 *(const char **)(((char *)opt
) + arg
->offset
) = str
;
72 void isl_arg_set_defaults(struct isl_arg
*arg
, void *opt
)
76 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
77 switch (arg
[i
].type
) {
79 set_default_choice(&arg
[i
], opt
);
82 set_default_flags(&arg
[i
], opt
);
85 set_default_bool(&arg
[i
], opt
);
88 set_default_child(&arg
[i
], opt
);
91 set_default_user(&arg
[i
], opt
);
94 set_default_long(&arg
[i
], opt
);
97 set_default_ulong(&arg
[i
], opt
);
101 set_default_str(&arg
[i
], opt
);
103 case isl_arg_version
:
110 void isl_arg_free(struct isl_arg
*arg
, void *opt
)
117 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
118 switch (arg
[i
].type
) {
120 isl_arg_free(arg
[i
].u
.child
.child
,
121 *(void **)(((char *)opt
) + arg
[i
].offset
));
125 free(*(char **)(((char *)opt
) + arg
[i
].offset
));
128 if (arg
[i
].u
.user
.clear
)
129 arg
[i
].u
.user
.clear(((char *)opt
) + arg
[i
].offset
);
136 case isl_arg_version
:
145 static int print_arg_help(struct isl_arg
*decl
, const char *prefix
, int no
)
149 if (!decl
->long_name
) {
150 printf(" -%c", decl
->short_name
);
154 if (decl
->short_name
)
155 printf(" -%c, --", decl
->short_name
);
161 printf("%s-", prefix
);
162 len
+= strlen(prefix
) + 1;
168 printf("%s", decl
->long_name
);
169 len
+= strlen(decl
->long_name
);
174 const void *isl_memrchr(const void *s
, int c
, size_t n
)
183 static int print_help_msg(struct isl_arg
*decl
, int pos
)
192 printf("\n%30s", "");
194 printf("%*s", 30 - pos
, "");
199 const char *space
= isl_memrchr(s
, ' ', 45);
203 space
= strchr(s
+ 45, ' ');
207 printf("%.*s", l
, s
);
210 printf("\n%30s", "");
217 static void print_default(struct isl_arg
*decl
, const char *def
, int pos
)
220 const char *default_prefix
= "[default: ";
221 const char *default_suffix
= "]";
224 len
= strlen(default_prefix
) + strlen(def
) + strlen(default_suffix
);
226 if (!decl
->help_msg
) {
228 printf("\n%30s", "");
230 printf("%*s", 30 - pos
, "");
234 printf("\n%30s", "");
238 printf("%s%s%s", default_prefix
, def
, default_suffix
);
241 static void print_default_choice(struct isl_arg
*decl
, int pos
)
244 const char *s
= "none";
246 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
)
247 if (decl
->u
.choice
.choice
[i
].value
== decl
->u
.choice
.default_value
) {
248 s
= decl
->u
.choice
.choice
[i
].name
;
252 print_default(decl
, s
, pos
);
255 static void print_choice_help(struct isl_arg
*decl
, const char *prefix
)
260 pos
= print_arg_help(decl
, prefix
, 0);
264 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
) {
269 printf("%s", decl
->u
.choice
.choice
[i
].name
);
270 pos
+= strlen(decl
->u
.choice
.choice
[i
].name
);
273 pos
= print_help_msg(decl
, pos
);
274 print_default_choice(decl
, pos
);
279 static void print_default_flags(struct isl_arg
*decl
, int pos
)
282 const char *default_prefix
= "[default: ";
283 const char *default_suffix
= "]";
284 int len
= strlen(default_prefix
) + strlen(default_suffix
);
286 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
)
287 if ((decl
->u
.flags
.default_value
& decl
->u
.flags
.flags
[i
].mask
) ==
288 decl
->u
.flags
.flags
[i
].value
)
289 len
+= strlen(decl
->u
.flags
.flags
[i
].name
);
291 if (!decl
->help_msg
) {
293 printf("\n%30s", "");
295 printf("%*s", 30 - pos
, "");
299 printf("\n%30s", "");
303 printf("%s", default_prefix
);
305 for (first
= 1, i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
)
306 if ((decl
->u
.flags
.default_value
& decl
->u
.flags
.flags
[i
].mask
) ==
307 decl
->u
.flags
.flags
[i
].value
) {
310 printf("%s", decl
->u
.flags
.flags
[i
].name
);
314 printf("%s", default_suffix
);
317 static void print_flags_help(struct isl_arg
*decl
, const char *prefix
)
322 pos
= print_arg_help(decl
, prefix
, 0);
326 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
) {
332 decl
->u
.flags
.flags
[j
].mask
== decl
->u
.flags
.flags
[i
].mask
;
338 printf("%s", decl
->u
.flags
.flags
[j
].name
);
339 pos
+= strlen(decl
->u
.flags
.flags
[j
].name
);
344 pos
= print_help_msg(decl
, pos
);
345 print_default_flags(decl
, pos
);
350 static void print_bool_help(struct isl_arg
*decl
, const char *prefix
)
353 int no
= decl
->u
.b
.default_value
== 1;
354 pos
= print_arg_help(decl
, prefix
, no
);
355 pos
= print_help_msg(decl
, pos
);
356 if (decl
->offset
!= (size_t) -1)
357 print_default(decl
, no
? "yes" : "no", pos
);
361 static int print_argument_name(struct isl_arg
*decl
, const char *name
, int pos
)
363 printf("%c<%s>", decl
->long_name
? '=' : ' ', name
);
364 return pos
+ 3 + strlen(name
);
367 static void print_long_help(struct isl_arg
*decl
, const char *prefix
)
370 pos
= print_arg_help(decl
, prefix
, 0);
371 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
377 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
381 print_help_msg(decl
, pos
);
385 static void print_ulong_help(struct isl_arg
*decl
, const char *prefix
)
388 pos
= print_arg_help(decl
, prefix
, 0);
391 print_help_msg(decl
, pos
);
395 static void print_str_help(struct isl_arg
*decl
, const char *prefix
)
398 const char *a
= decl
->argument_name
? decl
->argument_name
: "string";
399 pos
= print_arg_help(decl
, prefix
, 0);
400 pos
= print_argument_name(decl
, a
, pos
);
401 pos
= print_help_msg(decl
, pos
);
402 if (decl
->u
.str
.default_value
)
403 print_default(decl
, decl
->u
.str
.default_value
, pos
);
407 static void print_help(struct isl_arg
*arg
, const char *prefix
)
411 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
412 switch (arg
[i
].type
) {
414 print_flags_help(&arg
[i
], prefix
);
417 print_choice_help(&arg
[i
], prefix
);
420 print_bool_help(&arg
[i
], prefix
);
423 print_long_help(&arg
[i
], prefix
);
426 print_ulong_help(&arg
[i
], prefix
);
429 print_str_help(&arg
[i
], prefix
);
431 case isl_arg_version
:
440 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
441 if (arg
[i
].type
!= isl_arg_child
)
446 printf(" %s\n", arg
[i
].help_msg
);
447 print_help(arg
[i
].u
.child
.child
, arg
[i
].long_name
);
451 static const char *prog_name(const char *prog
)
455 slash
= strrchr(prog
, '/');
458 if (strncmp(prog
, "lt-", 3) == 0)
464 static int any_version(struct isl_arg
*decl
)
468 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
469 switch (decl
[i
].type
) {
470 case isl_arg_version
:
473 if (any_version(decl
[i
].u
.child
.child
))
484 static void print_help_and_exit(struct isl_arg
*arg
, const char *prog
)
488 printf("Usage: %s [OPTION...]", prog_name(prog
));
490 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
)
491 if (arg
[i
].type
== isl_arg_arg
)
492 printf(" %s", arg
[i
].argument_name
);
496 print_help(arg
, NULL
);
498 if (any_version(arg
))
499 printf(" -V, --version\n");
500 print_bool_help(help_arg
, NULL
);
505 static const char *skip_name(struct isl_arg
*decl
, const char *arg
,
506 const char *prefix
, int need_argument
, int *has_argument
)
512 if (arg
[0] == '-' && arg
[1] && arg
[1] == decl
->short_name
) {
513 if (need_argument
&& !arg
[2])
516 *has_argument
= arg
[2] != '\0';
519 if (!decl
->long_name
)
522 if (strncmp(arg
, "--", 2))
526 equal
= strchr(name
, '=');
527 if (need_argument
&& !equal
)
531 *has_argument
= !!equal
;
532 end
= equal
? equal
: name
+ strlen(name
);
535 size_t prefix_len
= strlen(prefix
);
536 if (strncmp(name
, prefix
, prefix_len
) == 0 &&
537 name
[prefix_len
] == '-')
538 name
+= prefix_len
+ 1;
541 if (end
- name
!= strlen(decl
->long_name
) ||
542 strncmp(name
, decl
->long_name
, end
- name
))
545 return equal
? equal
+ 1 : end
;
548 static int parse_choice_option(struct isl_arg
*decl
, char **arg
,
549 const char *prefix
, void *opt
)
555 choice
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
559 if (!has_argument
&& (!arg
[1] || arg
[1][0] == '-')) {
560 unsigned u
= decl
->u
.choice
.default_selected
;
561 if (decl
->u
.choice
.set
)
562 decl
->u
.choice
.set(opt
, u
);
564 *(unsigned *)(((char *)opt
) + decl
->offset
) = u
;
572 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
) {
575 if (strcmp(choice
, decl
->u
.choice
.choice
[i
].name
))
578 u
= decl
->u
.choice
.choice
[i
].value
;
579 if (decl
->u
.choice
.set
)
580 decl
->u
.choice
.set(opt
, u
);
582 *(unsigned *)(((char *)opt
) + decl
->offset
) = u
;
584 return has_argument
? 1 : 2;
590 static int set_flag(struct isl_arg
*decl
, unsigned *val
, const char *flag
,
595 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
) {
596 if (strncmp(flag
, decl
->u
.flags
.flags
[i
].name
, len
))
599 *val
&= ~decl
->u
.flags
.flags
[i
].mask
;
600 *val
|= decl
->u
.flags
.flags
[i
].value
;
608 static int parse_flags_option(struct isl_arg
*decl
, char **arg
,
609 const char *prefix
, void *opt
)
616 flags
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
620 if (!has_argument
&& !arg
[1])
626 val
= *(unsigned *)(((char *)opt
) + decl
->offset
);
628 while ((comma
= strchr(flags
, ',')) != NULL
) {
629 if (!set_flag(decl
, &val
, flags
, comma
- flags
))
633 if (!set_flag(decl
, &val
, flags
, strlen(flags
)))
636 *(unsigned *)(((char *)opt
) + decl
->offset
) = val
;
638 return has_argument
? 1 : 2;
641 static int parse_bool_option(struct isl_arg
*decl
, const char *arg
,
642 const char *prefix
, void *opt
)
644 unsigned *p
= (unsigned *)(((char *)opt
) + decl
->offset
);
646 if (skip_name(decl
, arg
, prefix
, 0, NULL
)) {
648 decl
->u
.b
.set(opt
, 1);
649 else if (decl
->offset
!= (size_t) -1)
655 if (!decl
->long_name
)
658 if (strncmp(arg
, "--", 2))
663 size_t prefix_len
= strlen(prefix
);
664 if (strncmp(arg
, prefix
, prefix_len
) == 0 &&
665 arg
[prefix_len
] == '-') {
666 arg
+= prefix_len
+ 1;
671 if (strncmp(arg
, "no-", 3))
676 size_t prefix_len
= strlen(prefix
);
677 if (strncmp(arg
, prefix
, prefix_len
) == 0 &&
678 arg
[prefix_len
] == '-')
679 arg
+= prefix_len
+ 1;
682 if (!strcmp(arg
, decl
->long_name
)) {
684 decl
->u
.b
.set(opt
, 0);
685 else if (decl
->offset
!= (size_t) -1)
694 static int parse_str_option(struct isl_arg
*decl
, char **arg
,
695 const char *prefix
, void *opt
)
699 char **p
= (char **)(((char *)opt
) + decl
->offset
);
701 s
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
720 static int parse_long_option(struct isl_arg
*decl
, char **arg
,
721 const char *prefix
, void *opt
)
726 long *p
= (long *)(((char *)opt
) + decl
->offset
);
728 val
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
733 long l
= strtol(val
, NULL
, 0);
735 decl
->u
.l
.set(opt
, l
);
742 long l
= strtol(arg
[1], &endptr
, 0);
743 if (*endptr
== '\0') {
745 decl
->u
.l
.set(opt
, l
);
752 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
754 decl
->u
.l
.set(opt
, decl
->u
.l
.default_selected
);
756 *p
= decl
->u
.l
.default_selected
;
763 static int parse_ulong_option(struct isl_arg
*decl
, char **arg
,
764 const char *prefix
, void *opt
)
769 unsigned long *p
= (unsigned long *)(((char *)opt
) + decl
->offset
);
771 val
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
776 *p
= strtoul(val
, NULL
, 0);
781 unsigned long ul
= strtoul(arg
[1], &endptr
, 0);
782 if (*endptr
== '\0') {
791 static int parse_option(struct isl_arg
*decl
, char **arg
,
792 const char *prefix
, void *opt
);
794 static int parse_child_option(struct isl_arg
*decl
, char **arg
, void *opt
)
796 return parse_option(decl
->u
.child
.child
, arg
, decl
->long_name
,
797 *(void **)(((char *)opt
) + decl
->offset
));
800 static int parse_option(struct isl_arg
*decl
, char **arg
,
801 const char *prefix
, void *opt
)
805 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
807 switch (decl
[i
].type
) {
809 parsed
= parse_choice_option(&decl
[i
], arg
, prefix
, opt
);
812 parsed
= parse_flags_option(&decl
[i
], arg
, prefix
, opt
);
815 parsed
= parse_long_option(&decl
[i
], arg
, prefix
, opt
);
818 parsed
= parse_ulong_option(&decl
[i
], arg
, prefix
, opt
);
821 parsed
= parse_bool_option(&decl
[i
], *arg
, prefix
, opt
);
824 parsed
= parse_str_option(&decl
[i
], arg
, prefix
, opt
);
827 parsed
= parse_child_option(&decl
[i
], arg
, opt
);
831 case isl_arg_version
:
842 static void print_version(struct isl_arg
*decl
)
846 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
847 switch (decl
[i
].type
) {
848 case isl_arg_version
:
849 decl
[i
].u
.version
.print_version();
852 print_version(decl
[i
].u
.child
.child
);
860 static void print_version_and_exit(struct isl_arg
*decl
)
867 static int drop_argument(int argc
, char **argv
, int drop
, int n
)
869 for (; drop
< argc
; ++drop
)
870 argv
[drop
] = argv
[drop
+ n
];
875 static int n_arg(struct isl_arg
*arg
)
880 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
)
881 if (arg
[i
].type
== isl_arg_arg
)
887 static int next_arg(struct isl_arg
*arg
, int a
)
889 for (++a
; arg
[a
].type
!= isl_arg_end
; ++a
)
890 if (arg
[a
].type
== isl_arg_arg
)
896 int isl_arg_parse(struct isl_arg
*arg
, int argc
, char **argv
, void *opt
,
906 for (i
= 1; i
< argc
; ++i
) {
907 if (strcmp(argv
[i
], "--help") == 0)
908 print_help_and_exit(arg
, argv
[0]);
911 for (i
= 1; i
< argc
; ++i
) {
912 if ((strcmp(argv
[i
], "--version") == 0 ||
913 strcmp(argv
[i
], "-V") == 0) && any_version(arg
))
914 print_version_and_exit(arg
);
917 while (argc
> 1 + skip
) {
919 if (argv
[1 + skip
][0] != '-') {
920 a
= next_arg(arg
, a
);
923 p
= (char **)(((char *)opt
)+arg
[a
].offset
);
925 *p
= strdup(argv
[1 + skip
]);
926 argc
= drop_argument(argc
, argv
, 1 + skip
, 1);
928 } else if (ISL_FL_ISSET(flags
, ISL_ARG_ALL
)) {
929 fprintf(stderr
, "%s: extra argument: %s\n",
930 prog_name(argv
[0]), argv
[1 + skip
]);
936 parsed
= parse_option(arg
, &argv
[1 + skip
], NULL
, opt
);
938 argc
= drop_argument(argc
, argv
, 1 + skip
, parsed
);
939 else if (ISL_FL_ISSET(flags
, ISL_ARG_ALL
)) {
940 fprintf(stderr
, "%s: unrecognized option: %s\n",
941 prog_name(argv
[0]), argv
[1 + skip
]);
948 fprintf(stderr
, "%s: expecting %d more argument(s)\n",
949 prog_name(argv
[0]), n
);