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
);
104 case isl_arg_version
:
111 void isl_arg_free(struct isl_arg
*arg
, void *opt
)
118 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
119 switch (arg
[i
].type
) {
121 isl_arg_free(arg
[i
].u
.child
.child
,
122 *(void **)(((char *)opt
) + arg
[i
].offset
));
126 free(*(char **)(((char *)opt
) + arg
[i
].offset
));
129 if (arg
[i
].u
.user
.clear
)
130 arg
[i
].u
.user
.clear(((char *)opt
) + arg
[i
].offset
);
138 case isl_arg_version
:
147 static int print_arg_help(struct isl_arg
*decl
, const char *prefix
, int no
)
151 if (!decl
->long_name
) {
152 printf(" -%c", decl
->short_name
);
156 if (decl
->short_name
)
157 printf(" -%c, --", decl
->short_name
);
163 printf("%s-", prefix
);
164 len
+= strlen(prefix
) + 1;
170 printf("%s", decl
->long_name
);
171 len
+= strlen(decl
->long_name
);
173 while ((++decl
)->type
== isl_arg_alias
) {
180 printf("%s", decl
->long_name
);
181 len
+= strlen(decl
->long_name
);
187 const void *isl_memrchr(const void *s
, int c
, size_t n
)
196 static int print_help_msg(struct isl_arg
*decl
, int pos
)
205 printf("\n%30s", "");
207 printf("%*s", 30 - pos
, "");
212 const char *space
= isl_memrchr(s
, ' ', 45);
216 space
= strchr(s
+ 45, ' ');
220 printf("%.*s", l
, s
);
223 printf("\n%30s", "");
230 static void print_default(struct isl_arg
*decl
, const char *def
, int pos
)
233 const char *default_prefix
= "[default: ";
234 const char *default_suffix
= "]";
237 len
= strlen(default_prefix
) + strlen(def
) + strlen(default_suffix
);
239 if (!decl
->help_msg
) {
241 printf("\n%30s", "");
243 printf("%*s", 30 - pos
, "");
247 printf("\n%30s", "");
251 printf("%s%s%s", default_prefix
, def
, default_suffix
);
254 static void print_default_choice(struct isl_arg
*decl
, int pos
)
257 const char *s
= "none";
259 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
)
260 if (decl
->u
.choice
.choice
[i
].value
== decl
->u
.choice
.default_value
) {
261 s
= decl
->u
.choice
.choice
[i
].name
;
265 print_default(decl
, s
, pos
);
268 static void print_choice_help(struct isl_arg
*decl
, const char *prefix
)
273 pos
= print_arg_help(decl
, prefix
, 0);
277 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
) {
282 printf("%s", decl
->u
.choice
.choice
[i
].name
);
283 pos
+= strlen(decl
->u
.choice
.choice
[i
].name
);
286 pos
= print_help_msg(decl
, pos
);
287 print_default_choice(decl
, pos
);
292 static void print_default_flags(struct isl_arg
*decl
, int pos
)
295 const char *default_prefix
= "[default: ";
296 const char *default_suffix
= "]";
297 int len
= strlen(default_prefix
) + strlen(default_suffix
);
299 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
)
300 if ((decl
->u
.flags
.default_value
& decl
->u
.flags
.flags
[i
].mask
) ==
301 decl
->u
.flags
.flags
[i
].value
)
302 len
+= strlen(decl
->u
.flags
.flags
[i
].name
);
304 if (!decl
->help_msg
) {
306 printf("\n%30s", "");
308 printf("%*s", 30 - pos
, "");
312 printf("\n%30s", "");
316 printf("%s", default_prefix
);
318 for (first
= 1, i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
)
319 if ((decl
->u
.flags
.default_value
& decl
->u
.flags
.flags
[i
].mask
) ==
320 decl
->u
.flags
.flags
[i
].value
) {
323 printf("%s", decl
->u
.flags
.flags
[i
].name
);
327 printf("%s", default_suffix
);
330 static void print_flags_help(struct isl_arg
*decl
, const char *prefix
)
335 pos
= print_arg_help(decl
, prefix
, 0);
339 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
) {
345 decl
->u
.flags
.flags
[j
].mask
== decl
->u
.flags
.flags
[i
].mask
;
351 printf("%s", decl
->u
.flags
.flags
[j
].name
);
352 pos
+= strlen(decl
->u
.flags
.flags
[j
].name
);
357 pos
= print_help_msg(decl
, pos
);
358 print_default_flags(decl
, pos
);
363 static void print_bool_help(struct isl_arg
*decl
, const char *prefix
)
366 int no
= decl
->u
.b
.default_value
== 1;
367 pos
= print_arg_help(decl
, prefix
, no
);
368 pos
= print_help_msg(decl
, pos
);
369 if (decl
->offset
!= (size_t) -1)
370 print_default(decl
, no
? "yes" : "no", pos
);
374 static int print_argument_name(struct isl_arg
*decl
, const char *name
, int pos
)
376 printf("%c<%s>", decl
->long_name
? '=' : ' ', name
);
377 return pos
+ 3 + strlen(name
);
380 static void print_long_help(struct isl_arg
*decl
, const char *prefix
)
383 pos
= print_arg_help(decl
, prefix
, 0);
384 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
390 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
394 print_help_msg(decl
, pos
);
398 static void print_ulong_help(struct isl_arg
*decl
, const char *prefix
)
401 pos
= print_arg_help(decl
, prefix
, 0);
404 print_help_msg(decl
, pos
);
408 static void print_str_help(struct isl_arg
*decl
, const char *prefix
)
411 const char *a
= decl
->argument_name
? decl
->argument_name
: "string";
412 pos
= print_arg_help(decl
, prefix
, 0);
413 pos
= print_argument_name(decl
, a
, pos
);
414 pos
= print_help_msg(decl
, pos
);
415 if (decl
->u
.str
.default_value
)
416 print_default(decl
, decl
->u
.str
.default_value
, pos
);
420 static void print_help(struct isl_arg
*arg
, const char *prefix
)
424 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
425 switch (arg
[i
].type
) {
427 print_flags_help(&arg
[i
], prefix
);
430 print_choice_help(&arg
[i
], prefix
);
433 print_bool_help(&arg
[i
], prefix
);
436 print_long_help(&arg
[i
], prefix
);
439 print_ulong_help(&arg
[i
], prefix
);
442 print_str_help(&arg
[i
], prefix
);
445 case isl_arg_version
:
454 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
) {
455 if (arg
[i
].type
!= isl_arg_child
)
460 printf(" %s\n", arg
[i
].help_msg
);
461 print_help(arg
[i
].u
.child
.child
, arg
[i
].long_name
);
465 static const char *prog_name(const char *prog
)
469 slash
= strrchr(prog
, '/');
472 if (strncmp(prog
, "lt-", 3) == 0)
478 static int any_version(struct isl_arg
*decl
)
482 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
483 switch (decl
[i
].type
) {
484 case isl_arg_version
:
487 if (any_version(decl
[i
].u
.child
.child
))
498 static void print_help_and_exit(struct isl_arg
*arg
, const char *prog
)
502 printf("Usage: %s [OPTION...]", prog_name(prog
));
504 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
)
505 if (arg
[i
].type
== isl_arg_arg
)
506 printf(" %s", arg
[i
].argument_name
);
510 print_help(arg
, NULL
);
512 if (any_version(arg
))
513 printf(" -V, --version\n");
514 print_bool_help(help_arg
, NULL
);
519 static int match_long_name(struct isl_arg
*decl
,
520 const char *start
, const char *end
)
523 if (end
- start
== strlen(decl
->long_name
) &&
524 !strncmp(start
, decl
->long_name
, end
- start
))
526 } while ((++decl
)->type
== isl_arg_alias
);
531 static const char *skip_name(struct isl_arg
*decl
, const char *arg
,
532 const char *prefix
, int need_argument
, int *has_argument
)
538 if (arg
[0] == '-' && arg
[1] && arg
[1] == decl
->short_name
) {
539 if (need_argument
&& !arg
[2])
542 *has_argument
= arg
[2] != '\0';
545 if (!decl
->long_name
)
548 if (strncmp(arg
, "--", 2))
552 equal
= strchr(name
, '=');
553 if (need_argument
&& !equal
)
557 *has_argument
= !!equal
;
558 end
= equal
? equal
: name
+ strlen(name
);
561 size_t prefix_len
= strlen(prefix
);
562 if (strncmp(name
, prefix
, prefix_len
) == 0 &&
563 name
[prefix_len
] == '-')
564 name
+= prefix_len
+ 1;
567 if (!match_long_name(decl
, name
, end
))
570 return equal
? equal
+ 1 : end
;
573 static int parse_choice_option(struct isl_arg
*decl
, char **arg
,
574 const char *prefix
, void *opt
)
580 choice
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
584 if (!has_argument
&& (!arg
[1] || arg
[1][0] == '-')) {
585 unsigned u
= decl
->u
.choice
.default_selected
;
586 if (decl
->u
.choice
.set
)
587 decl
->u
.choice
.set(opt
, u
);
589 *(unsigned *)(((char *)opt
) + decl
->offset
) = u
;
597 for (i
= 0; decl
->u
.choice
.choice
[i
].name
; ++i
) {
600 if (strcmp(choice
, decl
->u
.choice
.choice
[i
].name
))
603 u
= decl
->u
.choice
.choice
[i
].value
;
604 if (decl
->u
.choice
.set
)
605 decl
->u
.choice
.set(opt
, u
);
607 *(unsigned *)(((char *)opt
) + decl
->offset
) = u
;
609 return has_argument
? 1 : 2;
615 static int set_flag(struct isl_arg
*decl
, unsigned *val
, const char *flag
,
620 for (i
= 0; decl
->u
.flags
.flags
[i
].name
; ++i
) {
621 if (strncmp(flag
, decl
->u
.flags
.flags
[i
].name
, len
))
624 *val
&= ~decl
->u
.flags
.flags
[i
].mask
;
625 *val
|= decl
->u
.flags
.flags
[i
].value
;
633 static int parse_flags_option(struct isl_arg
*decl
, char **arg
,
634 const char *prefix
, void *opt
)
641 flags
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
645 if (!has_argument
&& !arg
[1])
651 val
= *(unsigned *)(((char *)opt
) + decl
->offset
);
653 while ((comma
= strchr(flags
, ',')) != NULL
) {
654 if (!set_flag(decl
, &val
, flags
, comma
- flags
))
658 if (!set_flag(decl
, &val
, flags
, strlen(flags
)))
661 *(unsigned *)(((char *)opt
) + decl
->offset
) = val
;
663 return has_argument
? 1 : 2;
666 static int parse_bool_option(struct isl_arg
*decl
, const char *arg
,
667 const char *prefix
, void *opt
)
669 unsigned *p
= (unsigned *)(((char *)opt
) + decl
->offset
);
671 if (skip_name(decl
, arg
, prefix
, 0, NULL
)) {
673 decl
->u
.b
.set(opt
, 1);
674 else if (decl
->offset
!= (size_t) -1)
680 if (!decl
->long_name
)
683 if (strncmp(arg
, "--", 2))
688 size_t prefix_len
= strlen(prefix
);
689 if (strncmp(arg
, prefix
, prefix_len
) == 0 &&
690 arg
[prefix_len
] == '-') {
691 arg
+= prefix_len
+ 1;
696 if (strncmp(arg
, "no-", 3))
701 size_t prefix_len
= strlen(prefix
);
702 if (strncmp(arg
, prefix
, prefix_len
) == 0 &&
703 arg
[prefix_len
] == '-')
704 arg
+= prefix_len
+ 1;
707 if (match_long_name(decl
, arg
, arg
+ strlen(arg
))) {
709 decl
->u
.b
.set(opt
, 0);
710 else if (decl
->offset
!= (size_t) -1)
719 static int parse_str_option(struct isl_arg
*decl
, char **arg
,
720 const char *prefix
, void *opt
)
724 char **p
= (char **)(((char *)opt
) + decl
->offset
);
726 s
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
745 static int parse_long_option(struct isl_arg
*decl
, char **arg
,
746 const char *prefix
, void *opt
)
751 long *p
= (long *)(((char *)opt
) + decl
->offset
);
753 val
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
758 long l
= strtol(val
, NULL
, 0);
760 decl
->u
.l
.set(opt
, l
);
767 long l
= strtol(arg
[1], &endptr
, 0);
768 if (*endptr
== '\0') {
770 decl
->u
.l
.set(opt
, l
);
777 if (decl
->u
.l
.default_value
!= decl
->u
.l
.default_selected
) {
779 decl
->u
.l
.set(opt
, decl
->u
.l
.default_selected
);
781 *p
= decl
->u
.l
.default_selected
;
788 static int parse_ulong_option(struct isl_arg
*decl
, char **arg
,
789 const char *prefix
, void *opt
)
794 unsigned long *p
= (unsigned long *)(((char *)opt
) + decl
->offset
);
796 val
= skip_name(decl
, arg
[0], prefix
, 0, &has_argument
);
801 *p
= strtoul(val
, NULL
, 0);
806 unsigned long ul
= strtoul(arg
[1], &endptr
, 0);
807 if (*endptr
== '\0') {
816 static int parse_option(struct isl_arg
*decl
, char **arg
,
817 const char *prefix
, void *opt
);
819 static int parse_child_option(struct isl_arg
*decl
, char **arg
, void *opt
)
821 return parse_option(decl
->u
.child
.child
, arg
, decl
->long_name
,
822 *(void **)(((char *)opt
) + decl
->offset
));
825 static int parse_option(struct isl_arg
*decl
, char **arg
,
826 const char *prefix
, void *opt
)
830 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
832 switch (decl
[i
].type
) {
834 parsed
= parse_choice_option(&decl
[i
], arg
, prefix
, opt
);
837 parsed
= parse_flags_option(&decl
[i
], arg
, prefix
, opt
);
840 parsed
= parse_long_option(&decl
[i
], arg
, prefix
, opt
);
843 parsed
= parse_ulong_option(&decl
[i
], arg
, prefix
, opt
);
846 parsed
= parse_bool_option(&decl
[i
], *arg
, prefix
, opt
);
849 parsed
= parse_str_option(&decl
[i
], arg
, prefix
, opt
);
852 parsed
= parse_child_option(&decl
[i
], arg
, opt
);
857 case isl_arg_version
:
868 static void print_version(struct isl_arg
*decl
)
872 for (i
= 0; decl
[i
].type
!= isl_arg_end
; ++i
) {
873 switch (decl
[i
].type
) {
874 case isl_arg_version
:
875 decl
[i
].u
.version
.print_version();
878 print_version(decl
[i
].u
.child
.child
);
886 static void print_version_and_exit(struct isl_arg
*decl
)
893 static int drop_argument(int argc
, char **argv
, int drop
, int n
)
895 for (; drop
< argc
; ++drop
)
896 argv
[drop
] = argv
[drop
+ n
];
901 static int n_arg(struct isl_arg
*arg
)
906 for (i
= 0; arg
[i
].type
!= isl_arg_end
; ++i
)
907 if (arg
[i
].type
== isl_arg_arg
)
913 static int next_arg(struct isl_arg
*arg
, int a
)
915 for (++a
; arg
[a
].type
!= isl_arg_end
; ++a
)
916 if (arg
[a
].type
== isl_arg_arg
)
922 int isl_arg_parse(struct isl_arg
*arg
, int argc
, char **argv
, void *opt
,
932 for (i
= 1; i
< argc
; ++i
) {
933 if (strcmp(argv
[i
], "--help") == 0)
934 print_help_and_exit(arg
, argv
[0]);
937 for (i
= 1; i
< argc
; ++i
) {
938 if ((strcmp(argv
[i
], "--version") == 0 ||
939 strcmp(argv
[i
], "-V") == 0) && any_version(arg
))
940 print_version_and_exit(arg
);
943 while (argc
> 1 + skip
) {
945 if (argv
[1 + skip
][0] != '-') {
946 a
= next_arg(arg
, a
);
949 p
= (char **)(((char *)opt
)+arg
[a
].offset
);
951 *p
= strdup(argv
[1 + skip
]);
952 argc
= drop_argument(argc
, argv
, 1 + skip
, 1);
954 } else if (ISL_FL_ISSET(flags
, ISL_ARG_ALL
)) {
955 fprintf(stderr
, "%s: extra argument: %s\n",
956 prog_name(argv
[0]), argv
[1 + skip
]);
962 parsed
= parse_option(arg
, &argv
[1 + skip
], NULL
, opt
);
964 argc
= drop_argument(argc
, argv
, 1 + skip
, parsed
);
965 else if (ISL_FL_ISSET(flags
, ISL_ARG_ALL
)) {
966 fprintf(stderr
, "%s: unrecognized option: %s\n",
967 prog_name(argv
[0]), argv
[1 + skip
]);
974 fprintf(stderr
, "%s: expecting %d more argument(s)\n",
975 prog_name(argv
[0]), n
);