kconfig/conf.c
author Arnaud Lacombe <lacombar@gmail.com>
Tue Aug 03 06:17:51 2010 +0200 (2010-08-03)
changeset 2064 f5ebe8c429dc
parent 943 1cca90ce0481
child 2448 a103abae1560
permissions -rw-r--r--
libc/uClibc: add uClibc 0.9.30.3

This version has been released a couple of month ago, but it never reached
crosstool-ng tree. This may be linked to the fact that the current 0.9.30.2,
once patched, has nothing much different from 0.9.30.3, released.

I'm not including any patch with this upgrade, on purpose.

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