kconfig/conf.c
author "Yann E. MORIN" <yann.morin.1998@free.fr>
Thu Jan 10 00:27:13 2013 +0100 (2013-01-10)
changeset 3159 fb71cad4b085
parent 2448 a103abae1560
permissions -rw-r--r--
arch/arm: OABI is no more, switch to only EABI

Well, leave the prompt as an OBSOLETE thing, scheduled to
be removed soon.

As an indication OABI lives its last days, gcc-4.8 will no
longer recognise non-EABI targets.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
     1 /*
     2  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
     3  * Released under the terms of the GNU GPL v2.0.
     4  */
     5 
     6 #include <locale.h>
     7 #include <ctype.h>
     8 #include <stdio.h>
     9 #include <stdlib.h>
    10 #include <string.h>
    11 #include <time.h>
    12 #include <unistd.h>
    13 #include <getopt.h>
    14 #include <sys/stat.h>
    15 #include <sys/time.h>
    16 
    17 #define LKC_DIRECT_LINK
    18 #include "lkc.h"
    19 
    20 static void conf(struct menu *menu);
    21 static void check_conf(struct menu *menu);
    22 
    23 enum input_mode {
    24 	oldaskconfig,
    25 	silentoldconfig,
    26 	oldconfig,
    27 	allnoconfig,
    28 	allyesconfig,
    29 	allmodconfig,
    30 	alldefconfig,
    31 	randconfig,
    32 	defconfig,
    33 	savedefconfig,
    34 	listnewconfig,
    35 	oldnoconfig,
    36 } input_mode = oldaskconfig;
    37 
    38 char *defconfig_file;
    39 
    40 static int indent = 1;
    41 static int valid_stdin = 1;
    42 static int sync_kconfig;
    43 static int conf_cnt;
    44 static char line[128];
    45 static struct menu *rootEntry;
    46 
    47 static void print_help(struct menu *menu)
    48 {
    49 	struct gstr help = str_new();
    50 
    51 	menu_get_ext_help(menu, &help);
    52 
    53 	printf("\n%s\n", str_get(&help));
    54 	str_free(&help);
    55 }
    56 
    57 static void strip(char *str)
    58 {
    59 	char *p = str;
    60 	int l;
    61 
    62 	while ((isspace(*p)))
    63 		p++;
    64 	l = strlen(p);
    65 	if (p != str)
    66 		memmove(str, p, l + 1);
    67 	if (!l)
    68 		return;
    69 	p = str + l - 1;
    70 	while ((isspace(*p)))
    71 		*p-- = 0;
    72 }
    73 
    74 static void check_stdin(void)
    75 {
    76 	if (!valid_stdin) {
    77 		/* For crosstool-NG, we don't care if stdin/stdout got redirected.
    78 		 * In this case, just printf a cariage return, for pretty output.
    79 		 */
    80 		printf("\n");
    81 	}
    82 }
    83 
    84 static int conf_askvalue(struct symbol *sym, const char *def)
    85 {
    86 	enum symbol_type type = sym_get_type(sym);
    87 
    88 	if (!sym_has_value(sym))
    89 		printf(_("(NEW) "));
    90 
    91 	line[0] = '\n';
    92 	line[1] = 0;
    93 
    94 	if (!sym_is_changable(sym)) {
    95 		printf("%s\n", def);
    96 		line[0] = '\n';
    97 		line[1] = 0;
    98 		return 0;
    99 	}
   100 
   101 	switch (input_mode) {
   102 	case oldconfig:
   103 	case silentoldconfig:
   104 		if (sym_has_value(sym)) {
   105 			printf("%s\n", def);
   106 			return 0;
   107 		}
   108 		check_stdin();
   109 	case oldaskconfig:
   110 		fflush(stdout);
   111 		xfgets(line, 128, stdin);
   112 		return 1;
   113 	default:
   114 		break;
   115 	}
   116 
   117 	switch (type) {
   118 	case S_INT:
   119 	case S_HEX:
   120 	case S_STRING:
   121 		printf("%s\n", def);
   122 		return 1;
   123 	default:
   124 		;
   125 	}
   126 	printf("%s", line);
   127 	return 1;
   128 }
   129 
   130 static int conf_string(struct menu *menu)
   131 {
   132 	struct symbol *sym = menu->sym;
   133 	const char *def;
   134 
   135 	while (1) {
   136 		printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
   137 		printf("(%s) ", sym->name);
   138 		def = sym_get_string_value(sym);
   139 		if (sym_get_string_value(sym))
   140 			printf("[%s] ", def);
   141 		if (!conf_askvalue(sym, def))
   142 			return 0;
   143 		switch (line[0]) {
   144 		case '\n':
   145 			break;
   146 		case '?':
   147 			/* print help */
   148 			if (line[1] == '\n') {
   149 				print_help(menu);
   150 				def = NULL;
   151 				break;
   152 			}
   153 		default:
   154 			line[strlen(line)-1] = 0;
   155 			def = line;
   156 		}
   157 		if (def && sym_set_string_value(sym, def))
   158 			return 0;
   159 	}
   160 }
   161 
   162 static int conf_sym(struct menu *menu)
   163 {
   164 	struct symbol *sym = menu->sym;
   165 	tristate oldval, newval;
   166 
   167 	while (1) {
   168 		printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
   169 		if (sym->name)
   170 			printf("(%s) ", sym->name);
   171 		putchar('[');
   172 		oldval = sym_get_tristate_value(sym);
   173 		switch (oldval) {
   174 		case no:
   175 			putchar('N');
   176 			break;
   177 		case mod:
   178 			putchar('M');
   179 			break;
   180 		case yes:
   181 			putchar('Y');
   182 			break;
   183 		}
   184 		if (oldval != no && sym_tristate_within_range(sym, no))
   185 			printf("/n");
   186 		if (oldval != mod && sym_tristate_within_range(sym, mod))
   187 			printf("/m");
   188 		if (oldval != yes && sym_tristate_within_range(sym, yes))
   189 			printf("/y");
   190 		if (menu_has_help(menu))
   191 			printf("/?");
   192 		printf("] ");
   193 		if (!conf_askvalue(sym, sym_get_string_value(sym)))
   194 			return 0;
   195 		strip(line);
   196 
   197 		switch (line[0]) {
   198 		case 'n':
   199 		case 'N':
   200 			newval = no;
   201 			if (!line[1] || !strcmp(&line[1], "o"))
   202 				break;
   203 			continue;
   204 		case 'm':
   205 		case 'M':
   206 			newval = mod;
   207 			if (!line[1])
   208 				break;
   209 			continue;
   210 		case 'y':
   211 		case 'Y':
   212 			newval = yes;
   213 			if (!line[1] || !strcmp(&line[1], "es"))
   214 				break;
   215 			continue;
   216 		case 0:
   217 			newval = oldval;
   218 			break;
   219 		case '?':
   220 			goto help;
   221 		default:
   222 			continue;
   223 		}
   224 		if (sym_set_tristate_value(sym, newval))
   225 			return 0;
   226 help:
   227 		print_help(menu);
   228 	}
   229 }
   230 
   231 static int conf_choice(struct menu *menu)
   232 {
   233 	struct symbol *sym, *def_sym;
   234 	struct menu *child;
   235 	bool is_new;
   236 
   237 	sym = menu->sym;
   238 	is_new = !sym_has_value(sym);
   239 	if (sym_is_changable(sym)) {
   240 		conf_sym(menu);
   241 		sym_calc_value(sym);
   242 		switch (sym_get_tristate_value(sym)) {
   243 		case no:
   244 			return 1;
   245 		case mod:
   246 			return 0;
   247 		case yes:
   248 			break;
   249 		}
   250 	} else {
   251 		switch (sym_get_tristate_value(sym)) {
   252 		case no:
   253 			return 1;
   254 		case mod:
   255 			printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
   256 			return 0;
   257 		case yes:
   258 			break;
   259 		}
   260 	}
   261 
   262 	while (1) {
   263 		int cnt, def;
   264 
   265 		printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
   266 		def_sym = sym_get_choice_value(sym);
   267 		cnt = def = 0;
   268 		line[0] = 0;
   269 		for (child = menu->list; child; child = child->next) {
   270 			if (!menu_is_visible(child))
   271 				continue;
   272 			if (!child->sym) {
   273 				printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
   274 				continue;
   275 			}
   276 			cnt++;
   277 			if (child->sym == def_sym) {
   278 				def = cnt;
   279 				printf("%*c", indent, '>');
   280 			} else
   281 				printf("%*c", indent, ' ');
   282 			printf(" %d. %s", cnt, _(menu_get_prompt(child)));
   283 			if (child->sym->name)
   284 				printf(" (%s)", child->sym->name);
   285 			if (!sym_has_value(child->sym))
   286 				printf(_(" (NEW)"));
   287 			printf("\n");
   288 		}
   289 		printf(_("%*schoice"), indent - 1, "");
   290 		if (cnt == 1) {
   291 			printf("[1]: 1\n");
   292 			goto conf_childs;
   293 		}
   294 		printf("[1-%d", cnt);
   295 		if (menu_has_help(menu))
   296 			printf("?");
   297 		printf("]: ");
   298 		switch (input_mode) {
   299 		case oldconfig:
   300 		case silentoldconfig:
   301 			if (!is_new) {
   302 				cnt = def;
   303 				printf("%d\n", cnt);
   304 				break;
   305 			}
   306 			check_stdin();
   307 		case oldaskconfig:
   308 			fflush(stdout);
   309 			xfgets(line, 128, stdin);
   310 			strip(line);
   311 			if (line[0] == '?') {
   312 				print_help(menu);
   313 				continue;
   314 			}
   315 			if (!line[0])
   316 				cnt = def;
   317 			else if (isdigit(line[0]))
   318 				cnt = atoi(line);
   319 			else
   320 				continue;
   321 			break;
   322 		default:
   323 			break;
   324 		}
   325 
   326 	conf_childs:
   327 		for (child = menu->list; child; child = child->next) {
   328 			if (!child->sym || !menu_is_visible(child))
   329 				continue;
   330 			if (!--cnt)
   331 				break;
   332 		}
   333 		if (!child)
   334 			continue;
   335 		if (line[0] && line[strlen(line) - 1] == '?') {
   336 			print_help(child);
   337 			continue;
   338 		}
   339 		sym_set_choice_value(sym, child->sym);
   340 		for (child = child->list; child; child = child->next) {
   341 			indent += 2;
   342 			conf(child);
   343 			indent -= 2;
   344 		}
   345 		return 1;
   346 	}
   347 }
   348 
   349 static void conf(struct menu *menu)
   350 {
   351 	struct symbol *sym;
   352 	struct property *prop;
   353 	struct menu *child;
   354 
   355 	if (!menu_is_visible(menu))
   356 		return;
   357 
   358 	sym = menu->sym;
   359 	prop = menu->prompt;
   360 	if (prop) {
   361 		const char *prompt;
   362 
   363 		switch (prop->type) {
   364 		case P_MENU:
   365 			if ((input_mode == silentoldconfig ||
   366 			     input_mode == listnewconfig ||
   367 			     input_mode == oldnoconfig) &&
   368 			    rootEntry != menu) {
   369 				check_conf(menu);
   370 				return;
   371 			}
   372 		case P_COMMENT:
   373 			prompt = menu_get_prompt(menu);
   374 			if (prompt)
   375 				printf("%*c\n%*c %s\n%*c\n",
   376 					indent, '*',
   377 					indent, '*', _(prompt),
   378 					indent, '*');
   379 		default:
   380 			;
   381 		}
   382 	}
   383 
   384 	if (!sym)
   385 		goto conf_childs;
   386 
   387 	if (sym_is_choice(sym)) {
   388 		conf_choice(menu);
   389 		if (sym->curr.tri != mod)
   390 			return;
   391 		goto conf_childs;
   392 	}
   393 
   394 	switch (sym->type) {
   395 	case S_INT:
   396 	case S_HEX:
   397 	case S_STRING:
   398 		conf_string(menu);
   399 		break;
   400 	default:
   401 		conf_sym(menu);
   402 		break;
   403 	}
   404 
   405 conf_childs:
   406 	if (sym)
   407 		indent += 2;
   408 	for (child = menu->list; child; child = child->next)
   409 		conf(child);
   410 	if (sym)
   411 		indent -= 2;
   412 }
   413 
   414 static void check_conf(struct menu *menu)
   415 {
   416 	struct symbol *sym;
   417 	struct menu *child;
   418 
   419 	if (!menu_is_visible(menu))
   420 		return;
   421 
   422 	sym = menu->sym;
   423 	if (sym && !sym_has_value(sym)) {
   424 		if (sym_is_changable(sym) ||
   425 		    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
   426 			if (input_mode == listnewconfig) {
   427 				if (sym->name && !sym_is_choice_value(sym)) {
   428 					printf("%s%s\n", CONFIG_, sym->name);
   429 				}
   430 			} else if (input_mode != oldnoconfig) {
   431 				if (!conf_cnt++)
   432 					printf(_("*\n* Restart config...\n*\n"));
   433 				rootEntry = menu_get_parent_menu(menu);
   434 				conf(rootEntry);
   435 			}
   436 		}
   437 	}
   438 
   439 	for (child = menu->list; child; child = child->next)
   440 		check_conf(child);
   441 }
   442 
   443 static struct option long_opts[] = {
   444 	{"oldaskconfig",    no_argument,       NULL, oldaskconfig},
   445 	{"oldconfig",       no_argument,       NULL, oldconfig},
   446 	{"silentoldconfig", no_argument,       NULL, silentoldconfig},
   447 	{"defconfig",       optional_argument, NULL, defconfig},
   448 	{"savedefconfig",   required_argument, NULL, savedefconfig},
   449 	{"allnoconfig",     no_argument,       NULL, allnoconfig},
   450 	{"allyesconfig",    no_argument,       NULL, allyesconfig},
   451 	{"allmodconfig",    no_argument,       NULL, allmodconfig},
   452 	{"alldefconfig",    no_argument,       NULL, alldefconfig},
   453 	{"randconfig",      no_argument,       NULL, randconfig},
   454 	{"listnewconfig",   no_argument,       NULL, listnewconfig},
   455 	{"oldnoconfig",     no_argument,       NULL, oldnoconfig},
   456 	{NULL, 0, NULL, 0}
   457 };
   458 
   459 int main(int ac, char **av)
   460 {
   461 	int opt;
   462 	const char *name;
   463 	struct stat tmpstat;
   464 
   465 	setlocale(LC_ALL, "");
   466 	bindtextdomain(PACKAGE, LOCALEDIR);
   467 	textdomain(PACKAGE);
   468 
   469 	while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
   470 		input_mode = (enum input_mode)opt;
   471 		switch (opt) {
   472 		case silentoldconfig:
   473 			sync_kconfig = 1;
   474 			break;
   475 		case defconfig:
   476 		case savedefconfig:
   477 			defconfig_file = optarg;
   478 			break;
   479 		case randconfig:
   480 		{
   481 			struct timeval now;
   482 			unsigned int seed;
   483 
   484 			/*
   485 			 * Use microseconds derived seed,
   486 			 * compensate for systems where it may be zero
   487 			 */
   488 			gettimeofday(&now, NULL);
   489 
   490 			seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
   491 			srand(seed);
   492 			break;
   493 		}
   494 		case '?':
   495 			fprintf(stderr, _("See README for usage info\n"));
   496 			exit(1);
   497 			break;
   498 		}
   499 	}
   500 	if (ac == optind) {
   501 		printf(_("%s: Kconfig file missing\n"), av[0]);
   502 		exit(1);
   503 	}
   504 	name = av[optind];
   505 	conf_parse(name);
   506 	//zconfdump(stdout);
   507 	if (sync_kconfig) {
   508 		name = conf_get_configname();
   509 		if (stat(name, &tmpstat)) {
   510 			fprintf(stderr, _("***\n"
   511 				"*** Configuration file \"%s\" not found!\n"
   512 				"***\n"
   513 				"*** Please configure with \"menuconfig\", or use a\n"
   514 				"*** pre-existing sample (see list with \"list-samples\").\n"
   515 				"***\n"), name);
   516 			exit(1);
   517 		}
   518 	}
   519 
   520 	switch (input_mode) {
   521 	case defconfig:
   522 		if (!defconfig_file)
   523 			defconfig_file = conf_get_default_confname();
   524 		if (conf_read(defconfig_file)) {
   525 			printf(_("***\n"
   526 				"*** Can't find default configuration \"%s\"!\n"
   527 				"***\n"), defconfig_file);
   528 			exit(1);
   529 		}
   530 		break;
   531 	case savedefconfig:
   532 	case silentoldconfig:
   533 	case oldaskconfig:
   534 	case oldconfig:
   535 	case listnewconfig:
   536 	case oldnoconfig:
   537 		conf_read(NULL);
   538 		break;
   539 	case allnoconfig:
   540 	case allyesconfig:
   541 	case allmodconfig:
   542 	case alldefconfig:
   543 	case randconfig:
   544 		name = getenv("KCONFIG_ALLCONFIG");
   545 		if (name && !stat(name, &tmpstat)) {
   546 			conf_read_simple(name, S_DEF_USER);
   547 			break;
   548 		}
   549 		switch (input_mode) {
   550 		case allnoconfig:	name = "allno.config"; break;
   551 		case allyesconfig:	name = "allyes.config"; break;
   552 		case allmodconfig:	name = "allmod.config"; break;
   553 		case alldefconfig:	name = "alldef.config"; break;
   554 		case randconfig:	name = "allrandom.config"; break;
   555 		default: break;
   556 		}
   557 		if (!stat(name, &tmpstat))
   558 			conf_read_simple(name, S_DEF_USER);
   559 		else if (!stat("all.config", &tmpstat))
   560 			conf_read_simple("all.config", S_DEF_USER);
   561 		break;
   562 	default:
   563 		break;
   564 	}
   565 
   566 	if (sync_kconfig) {
   567 		if (conf_get_changed()) {
   568 			name = getenv("KCONFIG_NOSILENTUPDATE");
   569 			if (name && *name) {
   570 				fprintf(stderr,
   571 					_("\n*** The configuration requires explicit update.\n\n"));
   572 				return 1;
   573 			}
   574 		}
   575 		valid_stdin = isatty(0) && isatty(1) && isatty(2);
   576 	}
   577 
   578 	switch (input_mode) {
   579 	case allnoconfig:
   580 		conf_set_all_new_symbols(def_no);
   581 		break;
   582 	case allyesconfig:
   583 		conf_set_all_new_symbols(def_yes);
   584 		break;
   585 	case allmodconfig:
   586 		conf_set_all_new_symbols(def_mod);
   587 		break;
   588 	case alldefconfig:
   589 		conf_set_all_new_symbols(def_default);
   590 		break;
   591 	case randconfig:
   592 		conf_set_all_new_symbols(def_random);
   593 		break;
   594 	case defconfig:
   595 		conf_set_all_new_symbols(def_default);
   596 		break;
   597 	case savedefconfig:
   598 		break;
   599 	case oldaskconfig:
   600 		rootEntry = &rootmenu;
   601 		conf(&rootmenu);
   602 		input_mode = silentoldconfig;
   603 		/* fall through */
   604 	case oldconfig:
   605 	case listnewconfig:
   606 	case oldnoconfig:
   607 	case silentoldconfig:
   608 		/* Update until a loop caused no more changes */
   609 		do {
   610 			conf_cnt = 0;
   611 			check_conf(&rootmenu);
   612 		} while (conf_cnt &&
   613 			 (input_mode != listnewconfig &&
   614 			  input_mode != oldnoconfig));
   615 		break;
   616 	}
   617 
   618 	if (sync_kconfig) {
   619 		/* silentoldconfig is used during the build so we shall update autoconf.
   620 		 * All other commands are only used to generate a config.
   621 		 */
   622 		if (conf_get_changed() && conf_write(NULL)) {
   623 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
   624 			exit(1);
   625 		}
   626 		/* In crosstool-NG, we do not use the autoconf stuff */
   627 	} else if (input_mode == savedefconfig) {
   628 		if (conf_write_defconfig(defconfig_file)) {
   629 			fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
   630 			        defconfig_file);
   631 			return 1;
   632 		}
   633 	} else if (input_mode != listnewconfig) {
   634 		if (conf_write(NULL)) {
   635 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
   636 			exit(1);
   637 		}
   638 	}
   639 	return 0;
   640 }
   641 /*
   642  * Helper function to facilitate fgets() by Jean Sacren.
   643  */
   644 void xfgets(str, size, in)
   645 	char *str;
   646 	int size;
   647 	FILE *in;
   648 {
   649 	if (fgets(str, size, in) == NULL)
   650 		fprintf(stderr, "\nError in reading or end of file.\n");
   651 }