brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.2 KiB · 8a9e26d Raw
1313 lines · c
1/*2 * Copyright 2008-2009 Katholieke Universiteit Leuven3 *4 * Use of this software is governed by the MIT license5 *6 * Written by Sven Verdoolaege, K.U.Leuven, Departement7 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium8 */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 18static struct isl_arg help_arg[] = {19ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")20{ isl_arg_end }21};22 23static 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 30static void set_default_flags(struct isl_arg *arg, void *opt)31{32	*(unsigned *)(((char *)opt) + arg->offset) = arg->u.flags.default_value;33}34 35static 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 42static 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 57static void set_default_user(struct isl_arg *arg, void *opt)58{59	arg->u.user.init(((char *)opt) + arg->offset);60}61 62static void set_default_int(struct isl_arg *arg, void *opt)63{64	*(int *)(((char *)opt) + arg->offset) = arg->u.i.default_value;65}66 67static void set_default_long(struct isl_arg *arg, void *opt)68{69	*(long *)(((char *)opt) + arg->offset) = arg->u.l.default_value;70}71 72static 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 77static 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 85static 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 91void 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 137static void free_args(struct isl_arg *arg, void *opt);138 139static 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	else144		isl_args_free(arg->u.child.child,145			    *(void **)(((char *)opt) + arg->offset));146}147 148static 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 159static 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 165static 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 199void 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 */215struct 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 updated222 * number of prefixes.223 */224static 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 */244static void drop_prefix(struct isl_prefixes *prefixes, int first)245{246	prefixes->n = first;247}248 249/* Print the prefixes in "prefixes".250 */251static 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 prefixes269 * and return the updated pointer.  Additionally, update *first to270 * the index after the last prefix found.271 */272static 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 290static 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 333const 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 342static 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	else350		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 372static 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 380static 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		else392			printf("%*s", 30 - pos, "");393	} else {394		if (pos + len >= 48)395			printf("\n%30s", "");396		else397			printf(" ");398	}399	printf("%s%s%s", default_prefix, def, default_suffix);400}401 402static 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 418static 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 443static 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		else461			printf("%*s", 30 - pos, "");462	} else {463		if (pos + len >= 48)464			printf("\n%30s", "");465		else466			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 482static 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 516static 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 529static 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 535static 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 549static 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 569static 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 580static 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 594static 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 605static 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		else674			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 682static 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 695static 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 715static 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 745static 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 757static 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 766static 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 803static 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 845static 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 863static 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 896static 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 951static 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 977static 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 992static 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 1015static 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 1043static 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 1083static 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 1111static int parse_option(struct isl_arg *decl, char **arg,1112	struct isl_prefixes *prefixes, void *opt);1113 1114static 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	else1123		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 1132static 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 1189static 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 1207static void print_version_and_exit(struct isl_arg *decl)1208{1209	print_version(decl);1210 1211	exit(0);1212}1213 1214static 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 1222static 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 1234static 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" is1244 * equal to "--help" or "-h" and if so call print_help_and_exit.1245 */1246static 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 1256int 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			} else1289				++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		} else1302			++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