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