869 lines · 18.5 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 "internal.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,	mod2noconfig,};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);} /** * randomize_choice_values - randomize choice block * * @choice: menu entry for the choice */static void randomize_choice_values(struct menu *choice){	struct menu *menu;	int x;	int cnt = 0; 	/*	 * First, count the number of symbols to randomize. If sym_has_value()	 * is true, it was specified by KCONFIG_ALLCONFIG. It needs to be	 * respected.	 */	menu_for_each_sub_entry(menu, choice) {		struct symbol *sym = menu->sym; 		if (sym && !sym_has_value(sym))			cnt++;	} 	while (cnt > 0) {		x = rand() % cnt; 		menu_for_each_sub_entry(menu, choice) {			struct symbol *sym = menu->sym; 			if (sym && !sym_has_value(sym))				x--; 			if (x < 0) {				sym->def[S_DEF_USER].tri = yes;				sym->flags |= SYMBOL_DEF_USER;				/*				 * Move the selected item to the _tail_ because				 * this needs to have a lower priority than the				 * user input from KCONFIG_ALLCONFIG.				 */				list_move_tail(&sym->choice_link,					       &choice->choice_members); 				break;			}		}		cnt--;	}} enum conf_def_mode {	def_default,	def_yes,	def_mod,	def_no,	def_random}; static void conf_set_all_new_symbols(enum conf_def_mode mode){	struct menu *menu;	int 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 */ 	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);		}	} 	menu_for_each_entry(menu) {		struct symbol *sym = menu->sym;		tristate val; 		if (!sym || !menu->prompt || sym_has_value(sym) ||		    (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) ||		    sym_is_choice_value(sym))			continue; 		if (sym_is_choice(sym)) {			if (mode == def_random)				randomize_choice_values(menu);			continue;		} 		switch (mode) {		case def_yes:			val = yes;			break;		case def_mod:			val = mod;			break;		case def_no:			val = no;			break;		case def_random:			val = no;			cnt = rand() % 100;			if (sym->type == S_TRISTATE) {				if (cnt < pty)					val = yes;				else if (cnt < pty + ptm)					val = mod;			} else if (cnt < pby) {				val = yes;			}			break;		default:			continue;		}		sym->def[S_DEF_USER].tri = val;		sym->flags |= SYMBOL_DEF_USER;	} 	sym_clear_all_valid();} static void conf_rewrite_tristates(tristate old_val, tristate new_val){	struct symbol *sym; 	for_all_symbols(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 void conf_choice(struct menu *menu){	struct symbol *def_sym;	struct menu *child;	bool is_new = false; 	while (1) {		int cnt, def; 		printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));		def_sym = sym_calc_choice(menu);		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 (%s)", cnt, menu_get_prompt(child),			       child->sym->name);			if (!sym_has_value(child->sym)) {				is_new = true;				printf(" (NEW)");			}			printf("\n");		}		printf("%*schoice", indent - 1, "");		if (cnt == 1) {			printf("[1]: 1\n");			goto conf_childs;		}		printf("[1-%d?]: ", cnt);		switch (input_mode) {		case oldconfig:		case syncconfig:			if (!is_new) {				cnt = def;				printf("%d\n", cnt);				break;			}			/* fall through */		case oldaskconfig:			fflush(stdout);			xfgets(line, sizeof(line), 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] == '?') {

Lines 1–500 of 869.