929 lines · 20.0 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> */ #include <ctype.h>#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <getopt.h>#include <sys/time.h>#include <errno.h> #include "lkc.h" static void conf(struct menu *menu);static void check_conf(struct menu *menu); enum input_mode {	oldaskconfig,	syncconfig,	oldconfig,	allnoconfig,	allyesconfig,	allmodconfig,	alldefconfig,	randconfig,	defconfig,	savedefconfig,	listnewconfig,	helpnewconfig,	olddefconfig,	yes2modconfig,	mod2yesconfig,};static enum input_mode input_mode = oldaskconfig;static int input_mode_opt;static int indent = 1;static int tty_stdio;static int sync_kconfig;static int conf_cnt;static char line[PATH_MAX];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;} /* Helper function to facilitate fgets() by Jean Sacren. */static void xfgets(char *str, int size, FILE *in){	if (!fgets(str, size, in))		fprintf(stderr, "\nError in reading or end of file.\n"); 	if (!tty_stdio)		printf("%s", str);} static void set_randconfig_seed(void){	unsigned int seed;	char *env;	bool seed_set = false; 	env = getenv("KCONFIG_SEED");	if (env && *env) {		char *endp; 		seed = strtol(env, &endp, 0);		if (*endp == '\0')			seed_set = true;	} 	if (!seed_set) {		struct timeval now; 		/*		 * Use microseconds derived seed, compensate for systems where it may		 * be zero.		 */		gettimeofday(&now, NULL);		seed = (now.tv_sec + 1) * (now.tv_usec + 1);	} 	printf("KCONFIG_SEED=0x%X\n", seed);	srand(seed);} static bool randomize_choice_values(struct symbol *csym){	struct property *prop;	struct symbol *sym;	struct expr *e;	int cnt, def; 	/*	 * If choice is mod then we may have more items selected	 * and if no then no-one.	 * In both cases stop.	 */	if (csym->curr.tri != yes)		return false; 	prop = sym_get_choice_prop(csym); 	/* count entries in choice block */	cnt = 0;	expr_list_for_each_sym(prop->expr, e, sym)		cnt++; 	/*	 * find a random value and set it to yes,	 * set the rest to no so we have only one set	 */	def = rand() % cnt; 	cnt = 0;	expr_list_for_each_sym(prop->expr, e, sym) {		if (def == cnt++) {			sym->def[S_DEF_USER].tri = yes;			csym->def[S_DEF_USER].val = sym;		} else {			sym->def[S_DEF_USER].tri = no;		}		sym->flags |= SYMBOL_DEF_USER;		/* clear VALID to get value calculated */		sym->flags &= ~SYMBOL_VALID;	}	csym->flags |= SYMBOL_DEF_USER;	/* clear VALID to get value calculated */	csym->flags &= ~SYMBOL_VALID; 	return true;} enum conf_def_mode {	def_default,	def_yes,	def_mod,	def_y2m,	def_m2y,	def_no,	def_random}; static bool conf_set_all_new_symbols(enum conf_def_mode mode){	struct symbol *sym, *csym;	int i, cnt;	/*	 * can't go as the default in switch-case below, otherwise gcc whines	 * about -Wmaybe-uninitialized	 */	int pby = 50; /* probability of bool     = y */	int pty = 33; /* probability of tristate = y */	int ptm = 33; /* probability of tristate = m */	bool has_changed = false; 	if (mode == def_random) {		int n, p[3];		char *env = getenv("KCONFIG_PROBABILITY"); 		n = 0;		while (env && *env) {			char *endp;			int tmp = strtol(env, &endp, 10); 			if (tmp >= 0 && tmp <= 100) {				p[n++] = tmp;			} else {				errno = ERANGE;				perror("KCONFIG_PROBABILITY");				exit(1);			}			env = (*endp == ':') ? endp + 1 : endp;			if (n >= 3)				break;		}		switch (n) {		case 1:			pby = p[0];			ptm = pby / 2;			pty = pby - ptm;			break;		case 2:			pty = p[0];			ptm = p[1];			pby = pty + ptm;			break;		case 3:			pby = p[0];			pty = p[1];			ptm = p[2];			break;		} 		if (pty + ptm > 100) {			errno = ERANGE;			perror("KCONFIG_PROBABILITY");			exit(1);		}	} 	for_all_symbols(i, sym) {		if (sym_has_value(sym) || sym->flags & SYMBOL_VALID)			continue;		switch (sym_get_type(sym)) {		case S_BOOLEAN:		case S_TRISTATE:			has_changed = true;			switch (mode) {			case def_yes:				sym->def[S_DEF_USER].tri = yes;				break;			case def_mod:				sym->def[S_DEF_USER].tri = mod;				break;			case def_no:				sym->def[S_DEF_USER].tri = no;				break;			case def_random:				sym->def[S_DEF_USER].tri = no;				cnt = rand() % 100;				if (sym->type == S_TRISTATE) {					if (cnt < pty)						sym->def[S_DEF_USER].tri = yes;					else if (cnt < pty + ptm)						sym->def[S_DEF_USER].tri = mod;				} else if (cnt < pby)					sym->def[S_DEF_USER].tri = yes;				break;			default:				continue;			}			if (!(sym_is_choice(sym) && mode == def_random))				sym->flags |= SYMBOL_DEF_USER;			break;		default:			break;		} 	} 	sym_clear_all_valid(); 	/*	 * We have different type of choice blocks.	 * If curr.tri equals to mod then we can select several	 * choice symbols in one block.	 * In this case we do nothing.	 * If curr.tri equals yes then only one symbol can be	 * selected in a choice block and we set it to yes,	 * and the rest to no.	 */	if (mode != def_random) {		for_all_symbols(i, csym) {			if ((sym_is_choice(csym) && !sym_has_value(csym)) ||			    sym_is_choice_value(csym))				csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;		}	} 	for_all_symbols(i, csym) {		if (sym_has_value(csym) || !sym_is_choice(csym))			continue; 		sym_calc_value(csym);		if (mode == def_random)			has_changed |= randomize_choice_values(csym);		else {			set_all_choice_values(csym);			has_changed = true;		}	} 	return has_changed;} static void conf_rewrite_mod_or_yes(enum conf_def_mode mode){	struct symbol *sym;	int i;	tristate old_val = (mode == def_y2m) ? yes : mod;	tristate new_val = (mode == def_y2m) ? mod : yes; 	for_all_symbols(i, sym) {		if (sym_get_type(sym) == S_TRISTATE &&		    sym->def[S_DEF_USER].tri == old_val)			sym->def[S_DEF_USER].tri = new_val;	}	sym_clear_all_valid();} static int conf_askvalue(struct symbol *sym, const char *def){	if (!sym_has_value(sym))		printf("(NEW) "); 	line[0] = '\n';	line[1] = 0; 	if (!sym_is_changeable(sym)) {		printf("%s\n", def);		line[0] = '\n';		line[1] = 0;		return 0;	} 	switch (input_mode) {	case oldconfig:	case syncconfig:		if (sym_has_value(sym)) {			printf("%s\n", def);			return 0;		}		/* fall through */	default:		fflush(stdout);		xfgets(line, sizeof(line), stdin);		break;	} 	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 (def)			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");		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_changeable(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, '>');

Lines 1–500 of 929.