| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754 | /* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> * Released under the terms of the GNU GPL v2.0. */#include <locale.h>#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <getopt.h>#include <sys/stat.h>#include <sys/time.h>#include <errno.h>#include "lkc.h"static void conf(struct menu *menu);static void check_conf(struct menu *menu);static void xfgets(char *str, int size, FILE *in);enum input_mode {	oldaskconfig,	silentoldconfig,	oldconfig,	allnoconfig,	allyesconfig,	allmodconfig,	alldefconfig,	randconfig,	defconfig,	savedefconfig,	listnewconfig,	olddefconfig,} input_mode = oldaskconfig;static int indent = 1;static int tty_stdio;static int valid_stdin = 1;static int sync_kconfig;static int conf_cnt;static char line[128];static struct menu *rootEntry;static void print_help(struct menu *menu){	struct gstr help = str_new();	menu_get_ext_help(menu, &help);	printf("\n%s\n", str_get(&help));	str_free(&help);}static void strip(char *str){	char *p = str;	int l;	while ((isspace(*p)))		p++;	l = strlen(p);	if (p != str)		memmove(str, p, l + 1);	if (!l)		return;	p = str + l - 1;	while ((isspace(*p)))		*p-- = 0;}static void check_stdin(void){	if (!valid_stdin) {		printf(_("aborted!\n\n"));		printf(_("Console input/output is redirected. "));		printf(_("Run 'make oldconfig' to update configuration.\n\n"));		exit(1);	}}static int conf_askvalue(struct symbol *sym, const char *def){	enum symbol_type type = sym_get_type(sym);	if (!sym_has_value(sym))		printf(_("(NEW) "));	line[0] = '\n';	line[1] = 0;	if (!sym_is_changable(sym)) {		printf("%s\n", def);		line[0] = '\n';		line[1] = 0;		return 0;	}	switch (input_mode) {	case oldconfig:	case silentoldconfig:		if (sym_has_value(sym)) {			printf("%s\n", def);			return 0;		}		check_stdin();		/* fall through */	case oldaskconfig:		fflush(stdout);		xfgets(line, 128, stdin);		if (!tty_stdio)			printf("\n");		return 1;	default:		break;	}	switch (type) {	case S_INT:	case S_HEX:	case S_STRING:		printf("%s\n", def);		return 1;	default:		;	}	printf("%s", line);	return 1;}static int conf_string(struct menu *menu){	struct symbol *sym = menu->sym;	const char *def;	while (1) {		printf("%*s%s ", indent - 1, "", _(menu->prompt->text));		printf("(%s) ", sym->name);		def = sym_get_string_value(sym);		if (sym_get_string_value(sym))			printf("[%s] ", def);		if (!conf_askvalue(sym, def))			return 0;		switch (line[0]) {		case '\n':			break;		case '?':			/* print help */			if (line[1] == '\n') {				print_help(menu);				def = NULL;				break;			}			/* fall through */		default:			line[strlen(line)-1] = 0;			def = line;		}		if (def && sym_set_string_value(sym, def))			return 0;	}}static int conf_sym(struct menu *menu){	struct symbol *sym = menu->sym;	tristate oldval, newval;	while (1) {		printf("%*s%s ", indent - 1, "", _(menu->prompt->text));		if (sym->name)			printf("(%s) ", sym->name);		putchar('[');		oldval = sym_get_tristate_value(sym);		switch (oldval) {		case no:			putchar('N');			break;		case mod:			putchar('M');			break;		case yes:			putchar('Y');			break;		}		if (oldval != no && sym_tristate_within_range(sym, no))			printf("/n");		if (oldval != mod && sym_tristate_within_range(sym, mod))			printf("/m");		if (oldval != yes && sym_tristate_within_range(sym, yes))			printf("/y");		if (menu_has_help(menu))			printf("/?");		printf("] ");		if (!conf_askvalue(sym, sym_get_string_value(sym)))			return 0;		strip(line);		switch (line[0]) {		case 'n':		case 'N':			newval = no;			if (!line[1] || !strcmp(&line[1], "o"))				break;			continue;		case 'm':		case 'M':			newval = mod;			if (!line[1])				break;			continue;		case 'y':		case 'Y':			newval = yes;			if (!line[1] || !strcmp(&line[1], "es"))				break;			continue;		case 0:			newval = oldval;			break;		case '?':			goto help;		default:			continue;		}		if (sym_set_tristate_value(sym, newval))			return 0;help:		print_help(menu);	}}static int conf_choice(struct menu *menu){	struct symbol *sym, *def_sym;	struct menu *child;	bool is_new;	sym = menu->sym;	is_new = !sym_has_value(sym);	if (sym_is_changable(sym)) {		conf_sym(menu);		sym_calc_value(sym);		switch (sym_get_tristate_value(sym)) {		case no:			return 1;		case mod:			return 0;		case yes:			break;		}	} else {		switch (sym_get_tristate_value(sym)) {		case no:			return 1;		case mod:			printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));			return 0;		case yes:			break;		}	}	while (1) {		int cnt, def;		printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));		def_sym = sym_get_choice_value(sym);		cnt = def = 0;		line[0] = 0;		for (child = menu->list; child; child = child->next) {			if (!menu_is_visible(child))				continue;			if (!child->sym) {				printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));				continue;			}			cnt++;			if (child->sym == def_sym) {				def = cnt;				printf("%*c", indent, '>');			} else				printf("%*c", indent, ' ');			printf(" %d. %s", cnt, _(menu_get_prompt(child)));			if (child->sym->name)				printf(" (%s)", child->sym->name);			if (!sym_has_value(child->sym))				printf(_(" (NEW)"));			printf("\n");		}		printf(_("%*schoice"), indent - 1, "");		if (cnt == 1) {			printf("[1]: 1\n");			goto conf_childs;		}		printf("[1-%d", cnt);		if (menu_has_help(menu))			printf("?");		printf("]: ");		switch (input_mode) {		case oldconfig:		case silentoldconfig:			if (!is_new) {				cnt = def;				printf("%d\n", cnt);				break;			}			check_stdin();			/* fall through */		case oldaskconfig:			fflush(stdout);			xfgets(line, 128, stdin);			strip(line);			if (line[0] == '?') {				print_help(menu);				continue;			}			if (!line[0])				cnt = def;			else if (isdigit(line[0]))				cnt = atoi(line);			else				continue;			break;		default:			break;		}	conf_childs:		for (child = menu->list; child; child = child->next) {			if (!child->sym || !menu_is_visible(child))				continue;			if (!--cnt)				break;		}		if (!child)			continue;		if (line[0] && line[strlen(line) - 1] == '?') {			print_help(child);			continue;		}		sym_set_choice_value(sym, child->sym);		for (child = child->list; child; child = child->next) {			indent += 2;			conf(child);			indent -= 2;		}		return 1;	}}static void conf(struct menu *menu){	struct symbol *sym;	struct property *prop;	struct menu *child;	if (!menu_is_visible(menu))		return;	sym = menu->sym;	prop = menu->prompt;	if (prop) {		const char *prompt;		switch (prop->type) {		case P_MENU:			if ((input_mode == silentoldconfig ||			     input_mode == listnewconfig ||			     input_mode == olddefconfig) &&			    rootEntry != menu) {				check_conf(menu);				return;			}			/* fall through */		case P_COMMENT:			prompt = menu_get_prompt(menu);			if (prompt)				printf("%*c\n%*c %s\n%*c\n",					indent, '*',					indent, '*', _(prompt),					indent, '*');		default:			;		}	}	if (!sym)		goto conf_childs;	if (sym_is_choice(sym)) {		conf_choice(menu);		if (sym->curr.tri != mod)			return;		goto conf_childs;	}	switch (sym->type) {	case S_INT:	case S_HEX:	case S_STRING:		conf_string(menu);		break;	default:		conf_sym(menu);		break;	}conf_childs:	if (sym)		indent += 2;	for (child = menu->list; child; child = child->next)		conf(child);	if (sym)		indent -= 2;}static void check_conf(struct menu *menu){	struct symbol *sym;	struct menu *child;	if (!menu_is_visible(menu))		return;	sym = menu->sym;	if (sym && !sym_has_value(sym)) {		if (sym_is_changable(sym) ||		    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {			if (input_mode == listnewconfig) {				if (sym->name && !sym_is_choice_value(sym)) {					printf("%s%s\n", CONFIG_, sym->name);				}			} else if (input_mode != olddefconfig) {				if (!conf_cnt++)					printf(_("*\n* Restart config...\n*\n"));				rootEntry = menu_get_parent_menu(menu);				conf(rootEntry);			}		}	}	for (child = menu->list; child; child = child->next)		check_conf(child);}#if 00 // || !defined __UCLIBC__ || \	(defined UCLIBC_HAS_GETOPT_LONG || defined UCLIBC_HAS_GNU_GETOPT)static struct option long_opts[] = {	{"oldaskconfig",    no_argument,       NULL, oldaskconfig},	{"oldconfig",       no_argument,       NULL, oldconfig},	{"silentoldconfig", no_argument,       NULL, silentoldconfig},	{"defconfig",       optional_argument, NULL, defconfig},	{"savedefconfig",   required_argument, NULL, savedefconfig},	{"allnoconfig",     no_argument,       NULL, allnoconfig},	{"allyesconfig",    no_argument,       NULL, allyesconfig},	{"allmodconfig",    no_argument,       NULL, allmodconfig},	{"alldefconfig",    no_argument,       NULL, alldefconfig},	{"randconfig",      no_argument,       NULL, randconfig},	{"listnewconfig",   no_argument,       NULL, listnewconfig},	{"olddefconfig",    no_argument,       NULL, olddefconfig},	/*	 * oldnoconfig is an alias of olddefconfig, because people already	 * are dependent on its behavior(sets new symbols to their default	 * value but not 'n') with the counter-intuitive name.	 */	{"oldnoconfig",     no_argument,       NULL, olddefconfig},	{NULL, 0, NULL, 0}};static void conf_usage(const char *progname){	printf("Usage: %s [option] <kconfig-file>\n", progname);	printf("[option] is _one_ of the following:\n");	printf("  --listnewconfig         List new options\n");	printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n");	printf("  --oldconfig             Update a configuration using a provided .config as base\n");	printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");	printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");	printf("  --oldnoconfig           An alias of olddefconfig\n");	printf("  --defconfig <file>      New config with default defined in <file>\n");	printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");	printf("  --allnoconfig           New config where all options are answered with no\n");	printf("  --allyesconfig          New config where all options are answered with yes\n");	printf("  --allmodconfig          New config where all options are answered with mod\n");	printf("  --alldefconfig          New config with all symbols set to default\n");	printf("  --randconfig            New config with random answer to all options\n");}#elsestatic void conf_usage(const char *progname){	printf("Usage: %s [option] <kconfig-file>\n", progname);	printf("[option] is _one_ of the following:\n");	printf("  -a, --oldaskconfig          Start a new configuration using a line-oriented program\n");	printf("  -s, --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");	printf("  -o, --oldconfig             Update a configuration using a provided .config as base\n");	printf("  -n, --allnoconfig           New config where all options are answered with no\n");	printf("  -y, --allyesconfig          New config where all options are answered with yes\n");	printf("  -m, --allmodconfig          New config where all options are answered with mod\n");	printf("  -A, --alldefconfig          New config with all symbols set to default\n");	printf("  -r, --randconfig            New config with random answer to all options\n");	printf("  -D, --defconfig <file>      New config with default defined in <file>\n");	printf("  -S, --savedefconfig <file>  Save the minimal current configuration to <file>\n");	printf("  -l, --listnewconfig         List new options\n");	printf("  -d, --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");	printf("  --oldnoconfig           An alias of olddefconfig\n");}#endifint main(int ac, char **av){	const char *progname = av[0];	int opt;	const char *name, *defconfig_file = NULL /* gcc uninit */;	struct stat tmpstat;	setlocale(LC_ALL, "");	bindtextdomain(PACKAGE, LOCALEDIR);	textdomain(PACKAGE);	tty_stdio = isatty(0) && isatty(1) && isatty(2);#if 00// !defined __UCLIBC__ || \	(defined UCLIBC_HAS_GETOPT_LONG || defined UCLIBC_HAS_GNU_GETOPT)	while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1)#else	char *gch = "asonymArDSld";	while ((opt = getopt(ac, av, "asonymArD:S:ldh")) != -1)#endif	{		char *x = memchr(gch, opt, strlen(gch));		if (x == NULL)			opt = '?';		else			opt = x - gch;		input_mode = (enum input_mode)opt;		switch (opt) {		case silentoldconfig:			sync_kconfig = 1;			break;		case defconfig:		case savedefconfig:			defconfig_file = optarg;			break;		case randconfig:		{			struct timeval now;			unsigned int seed;			char *seed_env;			/*			 * Use microseconds derived seed,			 * compensate for systems where it may be zero			 */			gettimeofday(&now, NULL);			seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));			seed_env = getenv("KCONFIG_SEED");			if( seed_env && *seed_env ) {				char *endp;				int tmp = (int)strtol(seed_env, &endp, 0);				if (*endp == '\0') {					seed = tmp;				}			}			fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );			srand(seed);			break;		}		case oldaskconfig:		case oldconfig:		case allnoconfig:		case allyesconfig:		case allmodconfig:		case alldefconfig:		case listnewconfig:		case olddefconfig:			break;		case '?':			conf_usage(progname);			exit(1);			break;		}	}	if (ac == optind) {		printf(_("%s: Kconfig file missing\n"), av[0]);		conf_usage(progname);		exit(1);	}	name = av[optind];	conf_parse(name);	//zconfdump(stdout);	if (sync_kconfig) {		name = conf_get_configname();		if (stat(name, &tmpstat)) {			fprintf(stderr, _("***\n"				"*** Configuration file \"%s\" not found!\n"				"***\n"				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"				"*** \"make menuconfig\" or \"make xconfig\").\n"				"***\n"), name);			exit(1);		}	}	switch (input_mode) {	case defconfig:		if (!defconfig_file)			defconfig_file = conf_get_default_confname();		if (conf_read(defconfig_file)) {			printf(_("***\n"				"*** Can't find default configuration \"%s\"!\n"				"***\n"), defconfig_file);			exit(1);		}		break;	case savedefconfig:	case silentoldconfig:	case oldaskconfig:	case oldconfig:	case listnewconfig:	case olddefconfig:		conf_read(NULL);		break;	case allnoconfig:	case allyesconfig:	case allmodconfig:	case alldefconfig:	case randconfig:		name = getenv("KCONFIG_ALLCONFIG");		if (!name)			break;		if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {			if (conf_read_simple(name, S_DEF_USER)) {				fprintf(stderr,					_("*** Can't read seed configuration \"%s\"!\n"),					name);				exit(1);			}			break;		}		switch (input_mode) {		case allnoconfig:	name = "allno.config"; break;		case allyesconfig:	name = "allyes.config"; break;		case allmodconfig:	name = "allmod.config"; break;		case alldefconfig:	name = "alldef.config"; break;		case randconfig:	name = "allrandom.config"; break;		default: break;		}		if (conf_read_simple(name, S_DEF_USER) &&		    conf_read_simple("all.config", S_DEF_USER)) {			fprintf(stderr,				_("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),				name);			exit(1);		}		break;	default:		break;	}	if (sync_kconfig) {		if (conf_get_changed()) {			name = getenv("KCONFIG_NOSILENTUPDATE");			if (name && *name) {				fprintf(stderr,					_("\n*** The configuration requires explicit update.\n\n"));				return 1;			}		}		valid_stdin = tty_stdio;	}	switch (input_mode) {	case allnoconfig:		conf_set_all_new_symbols(def_no);		break;	case allyesconfig:		conf_set_all_new_symbols(def_yes);		break;	case allmodconfig:		conf_set_all_new_symbols(def_mod);		break;	case alldefconfig:		conf_set_all_new_symbols(def_default);		break;	case randconfig:		/* Really nothing to do in this loop */		while (conf_set_all_new_symbols(def_random)) ;		break;	case defconfig:		conf_set_all_new_symbols(def_default);		break;	case savedefconfig:		break;	case oldaskconfig:		rootEntry = &rootmenu;		conf(&rootmenu);		input_mode = silentoldconfig;		/* fall through */	case oldconfig:	case listnewconfig:	case olddefconfig:	case silentoldconfig:		/* Update until a loop caused no more changes */		do {			conf_cnt = 0;			check_conf(&rootmenu);		} while (conf_cnt &&			 (input_mode != listnewconfig &&			  input_mode != olddefconfig));		break;	}	if (sync_kconfig) {		/* silentoldconfig is used during the build so we shall update autoconf.		 * All other commands are only used to generate a config.		 */		if (conf_get_changed() && conf_write(NULL)) {			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));			exit(1);		}		if (conf_write_autoconf()) {			fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));			return 1;		}	} else if (input_mode == savedefconfig) {		if (conf_write_defconfig(defconfig_file)) {			fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),			        defconfig_file);			return 1;		}	} else if (input_mode != listnewconfig) {		if (conf_write(NULL)) {			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));			exit(1);		}	}	return 0;}/* * Helper function to facilitate fgets() by Jean Sacren. */void xfgets(char *str, int size, FILE *in){	if (fgets(str, size, in) == NULL)		fprintf(stderr, "\nError in reading or end of file.\n");}
 |