kconfig/conf.c
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
parent 2448 a103abae1560
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

Signed-off-by: "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
     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 }