aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 17:12:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-05 17:12:07 -0400
commite4d6152b520184be87aa65cb7035bf87acd27c14 (patch)
tree4395b636552a5d475b7e64f0522d77ae01eba0da
parentda9e82b3b8989fc09e2a4c45b9da604ba2b4c46d (diff)
parent7a996d3ab150bb0e1b71fa182f70199a703efdd1 (diff)
Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6
* 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6: (26 commits) kconfig: add savedefconfig kconfig: code refactoring in confdata.c kconfig: refactor code in symbol.c kconfig: add alldefconfig kconfig: print more info when we see a recursive dependency kconfig: save location of config symbols kconfig: change nonint_oldconfig to listnewconfig kconfig: rename loose_nonint_oldconfig => oldnoconfig kconfig: use long options in conf kconfig: fix MODULES-related bug in case of no .config kconfig: make randconfig fair for booleans kconfig: Don't write invisible choice values kbuild: Warn on selecting symbols with unmet direct dependencies scripts:conf.c Fix warning: variable 'type' set but not used menuconfig: truncate list items menuconfig: fix to center checklist correctly in a corner case xconfig: add support to show hidden options which have prompts xconfig: remove unused function xconfig: clean up gconfig: fix null pointer warning ...
-rw-r--r--Documentation/kbuild/kconfig.txt2
-rw-r--r--scripts/kconfig/Makefile77
-rw-r--r--scripts/kconfig/conf.c181
-rw-r--r--scripts/kconfig/confdata.c221
-rw-r--r--scripts/kconfig/expr.c2
-rw-r--r--scripts/kconfig/expr.h3
-rw-r--r--scripts/kconfig/gconf.c7
-rw-r--r--scripts/kconfig/lkc.h2
-rw-r--r--scripts/kconfig/lkc_proto.h1
-rw-r--r--scripts/kconfig/lxdialog/checklist.c10
-rw-r--r--scripts/kconfig/mconf.c2
-rw-r--r--scripts/kconfig/menu.c27
-rw-r--r--scripts/kconfig/qconf.cc106
-rw-r--r--scripts/kconfig/qconf.h17
-rw-r--r--scripts/kconfig/symbol.c292
15 files changed, 667 insertions, 283 deletions
diff --git a/Documentation/kbuild/kconfig.txt b/Documentation/kbuild/kconfig.txt
index b2cb16ebcb16..cca46b1a0f6c 100644
--- a/Documentation/kbuild/kconfig.txt
+++ b/Documentation/kbuild/kconfig.txt
@@ -65,7 +65,7 @@ also use the environment variable KCONFIG_ALLCONFIG as a flag or a
65filename that contains config symbols that the user requires to be 65filename that contains config symbols that the user requires to be
66set to a specific value. If KCONFIG_ALLCONFIG is used without a 66set to a specific value. If KCONFIG_ALLCONFIG is used without a
67filename, "make *config" checks for a file named 67filename, "make *config" checks for a file named
68"all{yes/mod/no/random}.config" (corresponding to the *config command 68"all{yes/mod/no/def/random}.config" (corresponding to the *config command
69that was used) for symbol values that are to be forced. If this file 69that was used) for symbol values that are to be forced. If this file
70is not found, it checks for a file named "all.config" to contain forced 70is not found, it checks for a file named "all.config" to contain forced
71values. 71values.
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 7ea649da1940..de934def410f 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -21,17 +21,17 @@ menuconfig: $(obj)/mconf
21 $< $(Kconfig) 21 $< $(Kconfig)
22 22
23config: $(obj)/conf 23config: $(obj)/conf
24 $< $(Kconfig) 24 $< --oldaskconfig $(Kconfig)
25 25
26nconfig: $(obj)/nconf 26nconfig: $(obj)/nconf
27 $< $(Kconfig) 27 $< $(Kconfig)
28 28
29oldconfig: $(obj)/conf 29oldconfig: $(obj)/conf
30 $< -o $(Kconfig) 30 $< --$@ $(Kconfig)
31 31
32silentoldconfig: $(obj)/conf 32silentoldconfig: $(obj)/conf
33 $(Q)mkdir -p include/generated 33 $(Q)mkdir -p include/generated
34 $< -s $(Kconfig) 34 $< --$@ $(Kconfig)
35 35
36# if no path is given, then use src directory to find file 36# if no path is given, then use src directory to find file
37ifdef LSMOD 37ifdef LSMOD
@@ -44,15 +44,15 @@ endif
44localmodconfig: $(obj)/streamline_config.pl $(obj)/conf 44localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
45 $(Q)mkdir -p include/generated 45 $(Q)mkdir -p include/generated
46 $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config 46 $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config
47 $(Q)if [ -f .config ]; then \ 47 $(Q)if [ -f .config ]; then \
48 cmp -s .tmp.config .config || \ 48 cmp -s .tmp.config .config || \
49 (mv -f .config .config.old.1; \ 49 (mv -f .config .config.old.1; \
50 mv -f .tmp.config .config; \ 50 mv -f .tmp.config .config; \
51 $(obj)/conf -s $(Kconfig); \ 51 $(obj)/conf --silentoldconfig $(Kconfig); \
52 mv -f .config.old.1 .config.old) \ 52 mv -f .config.old.1 .config.old) \
53 else \ 53 else \
54 mv -f .tmp.config .config; \ 54 mv -f .tmp.config .config; \
55 $(obj)/conf -s $(Kconfig); \ 55 $(obj)/conf --silentoldconfig $(Kconfig); \
56 fi 56 fi
57 $(Q)rm -f .tmp.config 57 $(Q)rm -f .tmp.config
58 58
@@ -60,15 +60,15 @@ localyesconfig: $(obj)/streamline_config.pl $(obj)/conf
60 $(Q)mkdir -p include/generated 60 $(Q)mkdir -p include/generated
61 $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config 61 $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config
62 $(Q)sed -i s/=m/=y/ .tmp.config 62 $(Q)sed -i s/=m/=y/ .tmp.config
63 $(Q)if [ -f .config ]; then \ 63 $(Q)if [ -f .config ]; then \
64 cmp -s .tmp.config .config || \ 64 cmp -s .tmp.config .config || \
65 (mv -f .config .config.old.1; \ 65 (mv -f .config .config.old.1; \
66 mv -f .tmp.config .config; \ 66 mv -f .tmp.config .config; \
67 $(obj)/conf -s $(Kconfig); \ 67 $(obj)/conf --silentoldconfig $(Kconfig); \
68 mv -f .config.old.1 .config.old) \ 68 mv -f .config.old.1 .config.old) \
69 else \ 69 else \
70 mv -f .tmp.config .config; \ 70 mv -f .tmp.config .config; \
71 $(obj)/conf -s $(Kconfig); \ 71 $(obj)/conf --silentoldconfig $(Kconfig); \
72 fi 72 fi
73 $(Q)rm -f .tmp.config 73 $(Q)rm -f .tmp.config
74 74
@@ -95,30 +95,29 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
95 $(Q)rm -f arch/um/Kconfig.arch 95 $(Q)rm -f arch/um/Kconfig.arch
96 $(Q)rm -f $(obj)/config.pot 96 $(Q)rm -f $(obj)/config.pot
97 97
98PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig 98PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
99 99
100randconfig: $(obj)/conf 100allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
101 $< -r $(Kconfig) 101 $< --$@ $(Kconfig)
102 102
103allyesconfig: $(obj)/conf 103PHONY += listnewconfig oldnoconfig savedefconfig defconfig
104 $< -y $(Kconfig)
105 104
106allnoconfig: $(obj)/conf 105listnewconfig oldnoconfig: $(obj)/conf
107 $< -n $(Kconfig) 106 $< --$@ $(Kconfig)
108 107
109allmodconfig: $(obj)/conf 108savedefconfig: $(obj)/conf
110 $< -m $(Kconfig) 109 $< --$@=defconfig $(Kconfig)
111 110
112defconfig: $(obj)/conf 111defconfig: $(obj)/conf
113ifeq ($(KBUILD_DEFCONFIG),) 112ifeq ($(KBUILD_DEFCONFIG),)
114 $< -d $(Kconfig) 113 $< --defconfig $(Kconfig)
115else 114else
116 @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" 115 @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
117 $(Q)$< -D arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) 116 $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
118endif 117endif
119 118
120%_defconfig: $(obj)/conf 119%_defconfig: $(obj)/conf
121 $(Q)$< -D arch/$(SRCARCH)/configs/$@ $(Kconfig) 120 $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
122 121
123# Help text used by make help 122# Help text used by make help
124help: 123help:
@@ -131,11 +130,15 @@ help:
131 @echo ' localmodconfig - Update current config disabling modules not loaded' 130 @echo ' localmodconfig - Update current config disabling modules not loaded'
132 @echo ' localyesconfig - Update current config converting local mods to core' 131 @echo ' localyesconfig - Update current config converting local mods to core'
133 @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps' 132 @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps'
134 @echo ' randconfig - New config with random answer to all options' 133 @echo ' defconfig - New config with default from ARCH supplied defconfig'
135 @echo ' defconfig - New config with default answer to all options' 134 @echo ' savedefconfig - Save current config as ./defconfig (minimal config)'
136 @echo ' allmodconfig - New config selecting modules when possible'
137 @echo ' allyesconfig - New config where all options are accepted with yes'
138 @echo ' allnoconfig - New config where all options are answered with no' 135 @echo ' allnoconfig - New config where all options are answered with no'
136 @echo ' allyesconfig - New config where all options are accepted with yes'
137 @echo ' allmodconfig - New config selecting modules when possible'
138 @echo ' alldefconfig - New config with all symbols set to default'
139 @echo ' randconfig - New config with random answer to all options'
140 @echo ' listnewconfig - List new options'
141 @echo ' oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)'
139 142
140# lxdialog stuff 143# lxdialog stuff
141check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh 144check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 9960d1c303f8..010600ef58c0 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -10,6 +10,7 @@
10#include <string.h> 10#include <string.h>
11#include <time.h> 11#include <time.h>
12#include <unistd.h> 12#include <unistd.h>
13#include <getopt.h>
13#include <sys/stat.h> 14#include <sys/stat.h>
14#include <sys/time.h> 15#include <sys/time.h>
15 16
@@ -19,16 +20,21 @@
19static void conf(struct menu *menu); 20static void conf(struct menu *menu);
20static void check_conf(struct menu *menu); 21static void check_conf(struct menu *menu);
21 22
22enum { 23enum input_mode {
23 ask_all, 24 oldaskconfig,
24 ask_new, 25 silentoldconfig,
25 ask_silent, 26 oldconfig,
26 set_default, 27 allnoconfig,
27 set_yes, 28 allyesconfig,
28 set_mod, 29 allmodconfig,
29 set_no, 30 alldefconfig,
30 set_random 31 randconfig,
31} input_mode = ask_all; 32 defconfig,
33 savedefconfig,
34 listnewconfig,
35 oldnoconfig,
36} input_mode = oldaskconfig;
37
32char *defconfig_file; 38char *defconfig_file;
33 39
34static int indent = 1; 40static int indent = 1;
@@ -93,14 +99,14 @@ static int conf_askvalue(struct symbol *sym, const char *def)
93 } 99 }
94 100
95 switch (input_mode) { 101 switch (input_mode) {
96 case ask_new: 102 case oldconfig:
97 case ask_silent: 103 case silentoldconfig:
98 if (sym_has_value(sym)) { 104 if (sym_has_value(sym)) {
99 printf("%s\n", def); 105 printf("%s\n", def);
100 return 0; 106 return 0;
101 } 107 }
102 check_stdin(); 108 check_stdin();
103 case ask_all: 109 case oldaskconfig:
104 fflush(stdout); 110 fflush(stdout);
105 fgets(line, 128, stdin); 111 fgets(line, 128, stdin);
106 return 1; 112 return 1;
@@ -156,14 +162,12 @@ static int conf_string(struct menu *menu)
156static int conf_sym(struct menu *menu) 162static int conf_sym(struct menu *menu)
157{ 163{
158 struct symbol *sym = menu->sym; 164 struct symbol *sym = menu->sym;
159 int type;
160 tristate oldval, newval; 165 tristate oldval, newval;
161 166
162 while (1) { 167 while (1) {
163 printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); 168 printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
164 if (sym->name) 169 if (sym->name)
165 printf("(%s) ", sym->name); 170 printf("(%s) ", sym->name);
166 type = sym_get_type(sym);
167 putchar('['); 171 putchar('[');
168 oldval = sym_get_tristate_value(sym); 172 oldval = sym_get_tristate_value(sym);
169 switch (oldval) { 173 switch (oldval) {
@@ -228,11 +232,9 @@ static int conf_choice(struct menu *menu)
228{ 232{
229 struct symbol *sym, *def_sym; 233 struct symbol *sym, *def_sym;
230 struct menu *child; 234 struct menu *child;
231 int type;
232 bool is_new; 235 bool is_new;
233 236
234 sym = menu->sym; 237 sym = menu->sym;
235 type = sym_get_type(sym);
236 is_new = !sym_has_value(sym); 238 is_new = !sym_has_value(sym);
237 if (sym_is_changable(sym)) { 239 if (sym_is_changable(sym)) {
238 conf_sym(menu); 240 conf_sym(menu);
@@ -294,15 +296,15 @@ static int conf_choice(struct menu *menu)
294 printf("?"); 296 printf("?");
295 printf("]: "); 297 printf("]: ");
296 switch (input_mode) { 298 switch (input_mode) {
297 case ask_new: 299 case oldconfig:
298 case ask_silent: 300 case silentoldconfig:
299 if (!is_new) { 301 if (!is_new) {
300 cnt = def; 302 cnt = def;
301 printf("%d\n", cnt); 303 printf("%d\n", cnt);
302 break; 304 break;
303 } 305 }
304 check_stdin(); 306 check_stdin();
305 case ask_all: 307 case oldaskconfig:
306 fflush(stdout); 308 fflush(stdout);
307 fgets(line, 128, stdin); 309 fgets(line, 128, stdin);
308 strip(line); 310 strip(line);
@@ -360,7 +362,10 @@ static void conf(struct menu *menu)
360 362
361 switch (prop->type) { 363 switch (prop->type) {
362 case P_MENU: 364 case P_MENU:
363 if (input_mode == ask_silent && rootEntry != menu) { 365 if ((input_mode == silentoldconfig ||
366 input_mode == listnewconfig ||
367 input_mode == oldnoconfig) &&
368 rootEntry != menu) {
364 check_conf(menu); 369 check_conf(menu);
365 return; 370 return;
366 } 371 }
@@ -418,10 +423,16 @@ static void check_conf(struct menu *menu)
418 if (sym && !sym_has_value(sym)) { 423 if (sym && !sym_has_value(sym)) {
419 if (sym_is_changable(sym) || 424 if (sym_is_changable(sym) ||
420 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { 425 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
421 if (!conf_cnt++) 426 if (input_mode == listnewconfig) {
422 printf(_("*\n* Restart config...\n*\n")); 427 if (sym->name && !sym_is_choice_value(sym)) {
423 rootEntry = menu_get_parent_menu(menu); 428 printf("CONFIG_%s\n", sym->name);
424 conf(rootEntry); 429 }
430 } else {
431 if (!conf_cnt++)
432 printf(_("*\n* Restart config...\n*\n"));
433 rootEntry = menu_get_parent_menu(menu);
434 conf(rootEntry);
435 }
425 } 436 }
426 } 437 }
427 438
@@ -429,6 +440,22 @@ static void check_conf(struct menu *menu)
429 check_conf(child); 440 check_conf(child);
430} 441}
431 442
443static 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
432int main(int ac, char **av) 459int main(int ac, char **av)
433{ 460{
434 int opt; 461 int opt;
@@ -439,32 +466,17 @@ int main(int ac, char **av)
439 bindtextdomain(PACKAGE, LOCALEDIR); 466 bindtextdomain(PACKAGE, LOCALEDIR);
440 textdomain(PACKAGE); 467 textdomain(PACKAGE);
441 468
442 while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) { 469 while ((opt = getopt_long_only(ac, av, "", long_opts, NULL)) != -1) {
470 input_mode = (enum input_mode)opt;
443 switch (opt) { 471 switch (opt) {
444 case 'o': 472 case silentoldconfig:
445 input_mode = ask_silent;
446 break;
447 case 's':
448 input_mode = ask_silent;
449 sync_kconfig = 1; 473 sync_kconfig = 1;
450 break; 474 break;
451 case 'd': 475 case defconfig:
452 input_mode = set_default; 476 case savedefconfig:
453 break;
454 case 'D':
455 input_mode = set_default;
456 defconfig_file = optarg; 477 defconfig_file = optarg;
457 break; 478 break;
458 case 'n': 479 case randconfig:
459 input_mode = set_no;
460 break;
461 case 'm':
462 input_mode = set_mod;
463 break;
464 case 'y':
465 input_mode = set_yes;
466 break;
467 case 'r':
468 { 480 {
469 struct timeval now; 481 struct timeval now;
470 unsigned int seed; 482 unsigned int seed;
@@ -477,17 +489,12 @@ int main(int ac, char **av)
477 489
478 seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); 490 seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
479 srand(seed); 491 srand(seed);
480
481 input_mode = set_random;
482 break; 492 break;
483 } 493 }
484 case 'h': 494 case '?':
485 printf(_("See README for usage info\n"));
486 exit(0);
487 break;
488 default:
489 fprintf(stderr, _("See README for usage info\n")); 495 fprintf(stderr, _("See README for usage info\n"));
490 exit(1); 496 exit(1);
497 break;
491 } 498 }
492 } 499 }
493 if (ac == optind) { 500 if (ac == optind) {
@@ -512,7 +519,7 @@ int main(int ac, char **av)
512 } 519 }
513 520
514 switch (input_mode) { 521 switch (input_mode) {
515 case set_default: 522 case defconfig:
516 if (!defconfig_file) 523 if (!defconfig_file)
517 defconfig_file = conf_get_default_confname(); 524 defconfig_file = conf_get_default_confname();
518 if (conf_read(defconfig_file)) { 525 if (conf_read(defconfig_file)) {
@@ -522,25 +529,32 @@ int main(int ac, char **av)
522 exit(1); 529 exit(1);
523 } 530 }
524 break; 531 break;
525 case ask_silent: 532 case savedefconfig:
526 case ask_all: 533 conf_read(NULL);
527 case ask_new: 534 break;
535 case silentoldconfig:
536 case oldaskconfig:
537 case oldconfig:
538 case listnewconfig:
539 case oldnoconfig:
528 conf_read(NULL); 540 conf_read(NULL);
529 break; 541 break;
530 case set_no: 542 case allnoconfig:
531 case set_mod: 543 case allyesconfig:
532 case set_yes: 544 case allmodconfig:
533 case set_random: 545 case alldefconfig:
546 case randconfig:
534 name = getenv("KCONFIG_ALLCONFIG"); 547 name = getenv("KCONFIG_ALLCONFIG");
535 if (name && !stat(name, &tmpstat)) { 548 if (name && !stat(name, &tmpstat)) {
536 conf_read_simple(name, S_DEF_USER); 549 conf_read_simple(name, S_DEF_USER);
537 break; 550 break;
538 } 551 }
539 switch (input_mode) { 552 switch (input_mode) {
540 case set_no: name = "allno.config"; break; 553 case allnoconfig: name = "allno.config"; break;
541 case set_mod: name = "allmod.config"; break; 554 case allyesconfig: name = "allyes.config"; break;
542 case set_yes: name = "allyes.config"; break; 555 case allmodconfig: name = "allmod.config"; break;
543 case set_random: name = "allrandom.config"; break; 556 case alldefconfig: name = "alldef.config"; break;
557 case randconfig: name = "allrandom.config"; break;
544 default: break; 558 default: break;
545 } 559 }
546 if (!stat(name, &tmpstat)) 560 if (!stat(name, &tmpstat))
@@ -565,33 +579,42 @@ int main(int ac, char **av)
565 } 579 }
566 580
567 switch (input_mode) { 581 switch (input_mode) {
568 case set_no: 582 case allnoconfig:
569 conf_set_all_new_symbols(def_no); 583 conf_set_all_new_symbols(def_no);
570 break; 584 break;
571 case set_yes: 585 case allyesconfig:
572 conf_set_all_new_symbols(def_yes); 586 conf_set_all_new_symbols(def_yes);
573 break; 587 break;
574 case set_mod: 588 case allmodconfig:
575 conf_set_all_new_symbols(def_mod); 589 conf_set_all_new_symbols(def_mod);
576 break; 590 break;
577 case set_random: 591 case alldefconfig:
592 conf_set_all_new_symbols(def_default);
593 break;
594 case randconfig:
578 conf_set_all_new_symbols(def_random); 595 conf_set_all_new_symbols(def_random);
579 break; 596 break;
580 case set_default: 597 case defconfig:
581 conf_set_all_new_symbols(def_default); 598 conf_set_all_new_symbols(def_default);
582 break; 599 break;
583 case ask_new: 600 case savedefconfig:
584 case ask_all: 601 break;
602 case oldconfig:
603 case oldaskconfig:
585 rootEntry = &rootmenu; 604 rootEntry = &rootmenu;
586 conf(&rootmenu); 605 conf(&rootmenu);
587 input_mode = ask_silent; 606 input_mode = silentoldconfig;
588 /* fall through */ 607 /* fall through */
589 case ask_silent: 608 case listnewconfig:
609 case oldnoconfig:
610 case silentoldconfig:
590 /* Update until a loop caused no more changes */ 611 /* Update until a loop caused no more changes */
591 do { 612 do {
592 conf_cnt = 0; 613 conf_cnt = 0;
593 check_conf(&rootmenu); 614 check_conf(&rootmenu);
594 } while (conf_cnt); 615 } while (conf_cnt &&
616 (input_mode != listnewconfig &&
617 input_mode != oldnoconfig));
595 break; 618 break;
596 } 619 }
597 620
@@ -607,7 +630,13 @@ int main(int ac, char **av)
607 fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n")); 630 fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n"));
608 return 1; 631 return 1;
609 } 632 }
610 } else { 633 } else if (input_mode == savedefconfig) {
634 if (conf_write_defconfig(defconfig_file)) {
635 fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
636 defconfig_file);
637 return 1;
638 }
639 } else if (input_mode != listnewconfig) {
611 if (conf_write(NULL)) { 640 if (conf_write(NULL)) {
612 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); 641 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
613 exit(1); 642 exit(1);
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index c4dec80cfd8e..f81f263b64f2 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -170,8 +170,11 @@ int conf_read_simple(const char *name, int def)
170 if (in) 170 if (in)
171 goto load; 171 goto load;
172 sym_add_change_count(1); 172 sym_add_change_count(1);
173 if (!sym_defconfig_list) 173 if (!sym_defconfig_list) {
174 if (modules_sym)
175 sym_calc_value(modules_sym);
174 return 1; 176 return 1;
177 }
175 178
176 for_all_defaults(sym_defconfig_list, prop) { 179 for_all_defaults(sym_defconfig_list, prop) {
177 if (expr_calc_value(prop->visible.expr) == no || 180 if (expr_calc_value(prop->visible.expr) == no ||
@@ -396,15 +399,149 @@ int conf_read(const char *name)
396 return 0; 399 return 0;
397} 400}
398 401
402/* Write a S_STRING */
403static void conf_write_string(bool headerfile, const char *name,
404 const char *str, FILE *out)
405{
406 int l;
407 if (headerfile)
408 fprintf(out, "#define CONFIG_%s \"", name);
409 else
410 fprintf(out, "CONFIG_%s=\"", name);
411
412 while (1) {
413 l = strcspn(str, "\"\\");
414 if (l) {
415 fwrite(str, l, 1, out);
416 str += l;
417 }
418 if (!*str)
419 break;
420 fprintf(out, "\\%c", *str++);
421 }
422 fputs("\"\n", out);
423}
424
425static void conf_write_symbol(struct symbol *sym, enum symbol_type type,
426 FILE *out, bool write_no)
427{
428 const char *str;
429
430 switch (type) {
431 case S_BOOLEAN:
432 case S_TRISTATE:
433 switch (sym_get_tristate_value(sym)) {
434 case no:
435 if (write_no)
436 fprintf(out, "# CONFIG_%s is not set\n", sym->name);
437 break;
438 case mod:
439 fprintf(out, "CONFIG_%s=m\n", sym->name);
440 break;
441 case yes:
442 fprintf(out, "CONFIG_%s=y\n", sym->name);
443 break;
444 }
445 break;
446 case S_STRING:
447 conf_write_string(false, sym->name, sym_get_string_value(sym), out);
448 break;
449 case S_HEX:
450 case S_INT:
451 str = sym_get_string_value(sym);
452 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
453 break;
454 case S_OTHER:
455 case S_UNKNOWN:
456 break;
457 }
458}
459
460/*
461 * Write out a minimal config.
462 * All values that has default values are skipped as this is redundant.
463 */
464int conf_write_defconfig(const char *filename)
465{
466 struct symbol *sym;
467 struct menu *menu;
468 FILE *out;
469
470 out = fopen(filename, "w");
471 if (!out)
472 return 1;
473
474 sym_clear_all_valid();
475
476 /* Traverse all menus to find all relevant symbols */
477 menu = rootmenu.list;
478
479 while (menu != NULL)
480 {
481 sym = menu->sym;
482 if (sym == NULL) {
483 if (!menu_is_visible(menu))
484 goto next_menu;
485 } else if (!sym_is_choice(sym)) {
486 sym_calc_value(sym);
487 if (!(sym->flags & SYMBOL_WRITE))
488 goto next_menu;
489 sym->flags &= ~SYMBOL_WRITE;
490 /* If we cannot change the symbol - skip */
491 if (!sym_is_changable(sym))
492 goto next_menu;
493 /* If symbol equals to default value - skip */
494 if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
495 goto next_menu;
496
497 /*
498 * If symbol is a choice value and equals to the
499 * default for a choice - skip.
500 * But only if value equal to "y".
501 */
502 if (sym_is_choice_value(sym)) {
503 struct symbol *cs;
504 struct symbol *ds;
505
506 cs = prop_get_symbol(sym_get_choice_prop(sym));
507 ds = sym_choice_default(cs);
508 if (sym == ds) {
509 if ((sym->type == S_BOOLEAN ||
510 sym->type == S_TRISTATE) &&
511 sym_get_tristate_value(sym) == yes)
512 goto next_menu;
513 }
514 }
515 conf_write_symbol(sym, sym->type, out, true);
516 }
517next_menu:
518 if (menu->list != NULL) {
519 menu = menu->list;
520 }
521 else if (menu->next != NULL) {
522 menu = menu->next;
523 } else {
524 while ((menu = menu->parent)) {
525 if (menu->next != NULL) {
526 menu = menu->next;
527 break;
528 }
529 }
530 }
531 }
532 fclose(out);
533 return 0;
534}
535
399int conf_write(const char *name) 536int conf_write(const char *name)
400{ 537{
401 FILE *out; 538 FILE *out;
402 struct symbol *sym; 539 struct symbol *sym;
403 struct menu *menu; 540 struct menu *menu;
404 const char *basename; 541 const char *basename;
405 char dirname[128], tmpname[128], newname[128];
406 int type, l;
407 const char *str; 542 const char *str;
543 char dirname[128], tmpname[128], newname[128];
544 enum symbol_type type;
408 time_t now; 545 time_t now;
409 int use_timestamp = 1; 546 int use_timestamp = 1;
410 char *env; 547 char *env;
@@ -484,50 +621,11 @@ int conf_write(const char *name)
484 if (modules_sym->curr.tri == no) 621 if (modules_sym->curr.tri == no)
485 type = S_BOOLEAN; 622 type = S_BOOLEAN;
486 } 623 }
487 switch (type) { 624 /* Write config symbol to file */
488 case S_BOOLEAN: 625 conf_write_symbol(sym, type, out, true);
489 case S_TRISTATE:
490 switch (sym_get_tristate_value(sym)) {
491 case no:
492 fprintf(out, "# CONFIG_%s is not set\n", sym->name);
493 break;
494 case mod:
495 fprintf(out, "CONFIG_%s=m\n", sym->name);
496 break;
497 case yes:
498 fprintf(out, "CONFIG_%s=y\n", sym->name);
499 break;
500 }
501 break;
502 case S_STRING:
503 str = sym_get_string_value(sym);
504 fprintf(out, "CONFIG_%s=\"", sym->name);
505 while (1) {
506 l = strcspn(str, "\"\\");
507 if (l) {
508 fwrite(str, l, 1, out);
509 str += l;
510 }
511 if (!*str)
512 break;
513 fprintf(out, "\\%c", *str++);
514 }
515 fputs("\"\n", out);
516 break;
517 case S_HEX:
518 str = sym_get_string_value(sym);
519 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
520 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
521 break;
522 }
523 case S_INT:
524 str = sym_get_string_value(sym);
525 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
526 break;
527 }
528 } 626 }
529 627
530 next: 628next:
531 if (menu->list) { 629 if (menu->list) {
532 menu = menu->list; 630 menu = menu->list;
533 continue; 631 continue;
@@ -679,7 +777,7 @@ int conf_write_autoconf(void)
679 const char *name; 777 const char *name;
680 FILE *out, *tristate, *out_h; 778 FILE *out, *tristate, *out_h;
681 time_t now; 779 time_t now;
682 int i, l; 780 int i;
683 781
684 sym_clear_all_valid(); 782 sym_clear_all_valid();
685 783
@@ -729,6 +827,11 @@ int conf_write_autoconf(void)
729 sym_calc_value(sym); 827 sym_calc_value(sym);
730 if (!(sym->flags & SYMBOL_WRITE) || !sym->name) 828 if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
731 continue; 829 continue;
830
831 /* write symbol to config file */
832 conf_write_symbol(sym, sym->type, out, false);
833
834 /* update autoconf and tristate files */
732 switch (sym->type) { 835 switch (sym->type) {
733 case S_BOOLEAN: 836 case S_BOOLEAN:
734 case S_TRISTATE: 837 case S_TRISTATE:
@@ -736,12 +839,10 @@ int conf_write_autoconf(void)
736 case no: 839 case no:
737 break; 840 break;
738 case mod: 841 case mod:
739 fprintf(out, "CONFIG_%s=m\n", sym->name);
740 fprintf(tristate, "CONFIG_%s=M\n", sym->name); 842 fprintf(tristate, "CONFIG_%s=M\n", sym->name);
741 fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); 843 fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
742 break; 844 break;
743 case yes: 845 case yes:
744 fprintf(out, "CONFIG_%s=y\n", sym->name);
745 if (sym->type == S_TRISTATE) 846 if (sym->type == S_TRISTATE)
746 fprintf(tristate, "CONFIG_%s=Y\n", 847 fprintf(tristate, "CONFIG_%s=Y\n",
747 sym->name); 848 sym->name);
@@ -750,35 +851,16 @@ int conf_write_autoconf(void)
750 } 851 }
751 break; 852 break;
752 case S_STRING: 853 case S_STRING:
753 str = sym_get_string_value(sym); 854 conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);
754 fprintf(out, "CONFIG_%s=\"", sym->name);
755 fprintf(out_h, "#define CONFIG_%s \"", sym->name);
756 while (1) {
757 l = strcspn(str, "\"\\");
758 if (l) {
759 fwrite(str, l, 1, out);
760 fwrite(str, l, 1, out_h);
761 str += l;
762 }
763 if (!*str)
764 break;
765 fprintf(out, "\\%c", *str);
766 fprintf(out_h, "\\%c", *str);
767 str++;
768 }
769 fputs("\"\n", out);
770 fputs("\"\n", out_h);
771 break; 855 break;
772 case S_HEX: 856 case S_HEX:
773 str = sym_get_string_value(sym); 857 str = sym_get_string_value(sym);
774 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { 858 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
775 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
776 fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); 859 fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
777 break; 860 break;
778 } 861 }
779 case S_INT: 862 case S_INT:
780 str = sym_get_string_value(sym); 863 str = sym_get_string_value(sym);
781 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
782 fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); 864 fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
783 break; 865 break;
784 default: 866 default:
@@ -862,7 +944,8 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
862 sym->def[S_DEF_USER].tri = no; 944 sym->def[S_DEF_USER].tri = no;
863 break; 945 break;
864 case def_random: 946 case def_random:
865 sym->def[S_DEF_USER].tri = (tristate)(rand() % 3); 947 cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
948 sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
866 break; 949 break;
867 default: 950 default:
868 continue; 951 continue;
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index d83f2322893a..8f18e37892cb 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -1121,7 +1121,7 @@ static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *s
1121 } 1121 }
1122 1122
1123 str_append(gs, str); 1123 str_append(gs, str);
1124 if (sym) 1124 if (sym && sym->type != S_UNKNOWN)
1125 str_printf(gs, " [=%s]", sym_str); 1125 str_printf(gs, " [=%s]", sym_str);
1126} 1126}
1127 1127
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 891cd9ce9ba2..6ee2e4fb1481 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -83,6 +83,7 @@ struct symbol {
83 tristate visible; 83 tristate visible;
84 int flags; 84 int flags;
85 struct property *prop; 85 struct property *prop;
86 struct expr_value dir_dep;
86 struct expr_value rev_dep; 87 struct expr_value rev_dep;
87}; 88};
88 89
@@ -131,6 +132,7 @@ enum prop_type {
131 P_SELECT, /* select BAR */ 132 P_SELECT, /* select BAR */
132 P_RANGE, /* range 7..100 (for a symbol) */ 133 P_RANGE, /* range 7..100 (for a symbol) */
133 P_ENV, /* value from environment variable */ 134 P_ENV, /* value from environment variable */
135 P_SYMBOL, /* where a symbol is defined */
134}; 136};
135 137
136struct property { 138struct property {
@@ -163,6 +165,7 @@ struct menu {
163 struct symbol *sym; 165 struct symbol *sym;
164 struct property *prompt; 166 struct property *prompt;
165 struct expr *dep; 167 struct expr *dep;
168 struct expr *dir_dep;
166 unsigned int flags; 169 unsigned int flags;
167 char *help; 170 char *help;
168 struct file *file; 171 struct file *file;
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index bef10411837f..d66988265f89 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -1114,7 +1114,7 @@ static gchar **fill_row(struct menu *menu)
1114 1114
1115 row[COL_OPTION] = 1115 row[COL_OPTION] =
1116 g_strdup_printf("%s %s", _(menu_get_prompt(menu)), 1116 g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
1117 sym && sym_has_value(sym) ? "(NEW)" : ""); 1117 sym && !sym_has_value(sym) ? "(NEW)" : "");
1118 1118
1119 if (opt_mode == OPT_ALL && !menu_is_visible(menu)) 1119 if (opt_mode == OPT_ALL && !menu_is_visible(menu))
1120 row[COL_COLOR] = g_strdup("DarkGray"); 1120 row[COL_COLOR] = g_strdup("DarkGray");
@@ -1343,7 +1343,8 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
1343#endif 1343#endif
1344 1344
1345 if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) || 1345 if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
1346 (opt_mode == OPT_PROMPT && !menu_has_prompt(child1))) { 1346 (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
1347 (opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
1347 1348
1348 /* remove node */ 1349 /* remove node */
1349 if (gtktree_iter_find_node(dst, menu1) != NULL) { 1350 if (gtktree_iter_find_node(dst, menu1) != NULL) {
@@ -1425,7 +1426,7 @@ static void display_tree(struct menu *menu)
1425 1426
1426 if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) || 1427 if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
1427 (opt_mode == OPT_PROMPT && menu_has_prompt(child)) || 1428 (opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
1428 (opt_mode == OPT_ALL)) 1429 (opt_mode == OPT_ALL && menu_get_prompt(child)))
1429 place_node(child, fill_row(child)); 1430 place_node(child, fill_row(child));
1430#ifdef DEBUG 1431#ifdef DEBUG
1431 printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); 1432 printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index ce6549cdaccf..76db065ed72c 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -126,6 +126,8 @@ void sym_init(void);
126void sym_clear_all_valid(void); 126void sym_clear_all_valid(void);
127void sym_set_all_changed(void); 127void sym_set_all_changed(void);
128void sym_set_changed(struct symbol *sym); 128void sym_set_changed(struct symbol *sym);
129struct symbol *sym_choice_default(struct symbol *sym);
130const char *sym_get_string_default(struct symbol *sym);
129struct symbol *sym_check_deps(struct symbol *sym); 131struct symbol *sym_check_deps(struct symbol *sym);
130struct property *prop_alloc(enum prop_type type, struct symbol *sym); 132struct property *prop_alloc(enum prop_type type, struct symbol *sym);
131struct symbol *prop_get_symbol(struct property *prop); 133struct symbol *prop_get_symbol(struct property *prop);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 7cadcad8233b..9a948c9ce44e 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -3,6 +3,7 @@
3P(conf_parse,void,(const char *name)); 3P(conf_parse,void,(const char *name));
4P(conf_read,int,(const char *name)); 4P(conf_read,int,(const char *name));
5P(conf_read_simple,int,(const char *name, int)); 5P(conf_read_simple,int,(const char *name, int));
6P(conf_write_defconfig,int,(const char *name));
6P(conf_write,int,(const char *name)); 7P(conf_write,int,(const char *name));
7P(conf_write_autoconf,int,(void)); 8P(conf_write_autoconf,int,(void));
8P(conf_get_changed,bool,(void)); 9P(conf_get_changed,bool,(void));
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index bcc6f19c3a35..a2eb80fbc896 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -31,6 +31,10 @@ static int list_width, check_x, item_x;
31static void print_item(WINDOW * win, int choice, int selected) 31static void print_item(WINDOW * win, int choice, int selected)
32{ 32{
33 int i; 33 int i;
34 char *list_item = malloc(list_width + 1);
35
36 strncpy(list_item, item_str(), list_width - item_x);
37 list_item[list_width - item_x] = '\0';
34 38
35 /* Clear 'residue' of last item */ 39 /* Clear 'residue' of last item */
36 wattrset(win, dlg.menubox.atr); 40 wattrset(win, dlg.menubox.atr);
@@ -45,13 +49,14 @@ static void print_item(WINDOW * win, int choice, int selected)
45 wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); 49 wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
46 50
47 wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); 51 wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
48 mvwaddch(win, choice, item_x, item_str()[0]); 52 mvwaddch(win, choice, item_x, list_item[0]);
49 wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); 53 wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
50 waddstr(win, (char *)item_str() + 1); 54 waddstr(win, list_item + 1);
51 if (selected) { 55 if (selected) {
52 wmove(win, choice, check_x + 1); 56 wmove(win, choice, check_x + 1);
53 wrefresh(win); 57 wrefresh(win);
54 } 58 }
59 free(list_item);
55} 60}
56 61
57/* 62/*
@@ -175,6 +180,7 @@ do_resize:
175 check_x = 0; 180 check_x = 0;
176 item_foreach() 181 item_foreach()
177 check_x = MAX(check_x, strlen(item_str()) + 4); 182 check_x = MAX(check_x, strlen(item_str()) + 4);
183 check_x = MIN(check_x, list_width);
178 184
179 check_x = (list_width - check_x) / 2; 185 check_x = (list_width - check_x) / 2;
180 item_x = check_x + 4; 186 item_x = check_x + 4;
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 2c83d3234d30..d2f6e056c058 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -74,7 +74,7 @@ static const char mconf_readme[] = N_(
74"\n" 74"\n"
75" Shortcut: Press <H> or <?>.\n" 75" Shortcut: Press <H> or <?>.\n"
76"\n" 76"\n"
77"o To show hidden options, press <Z>.\n" 77"o To toggle the display of hidden options, press <Z>.\n"
78"\n" 78"\n"
79"\n" 79"\n"
80"Radiolists (Choice lists)\n" 80"Radiolists (Choice lists)\n"
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 203632cc30bd..4fb590247f33 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -58,6 +58,8 @@ void menu_add_entry(struct symbol *sym)
58 *last_entry_ptr = menu; 58 *last_entry_ptr = menu;
59 last_entry_ptr = &menu->next; 59 last_entry_ptr = &menu->next;
60 current_entry = menu; 60 current_entry = menu;
61 if (sym)
62 menu_add_symbol(P_SYMBOL, sym, NULL);
61} 63}
62 64
63void menu_end_entry(void) 65void menu_end_entry(void)
@@ -105,6 +107,7 @@ static struct expr *menu_check_dep(struct expr *e)
105void menu_add_dep(struct expr *dep) 107void menu_add_dep(struct expr *dep)
106{ 108{
107 current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); 109 current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
110 current_entry->dir_dep = current_entry->dep;
108} 111}
109 112
110void menu_set_type(int type) 113void menu_set_type(int type)
@@ -288,6 +291,10 @@ void menu_finalize(struct menu *parent)
288 for (menu = parent->list; menu; menu = menu->next) 291 for (menu = parent->list; menu; menu = menu->next)
289 menu_finalize(menu); 292 menu_finalize(menu);
290 } else if (sym) { 293 } else if (sym) {
294 /* ignore inherited dependencies for dir_dep */
295 sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep));
296 sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr);
297
291 basedep = parent->prompt ? parent->prompt->visible.expr : NULL; 298 basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
292 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); 299 basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
293 basedep = expr_eliminate_dups(expr_transform(basedep)); 300 basedep = expr_eliminate_dups(expr_transform(basedep));
@@ -419,9 +426,13 @@ bool menu_is_visible(struct menu *menu)
419 if (!sym || sym_get_tristate_value(menu->sym) == no) 426 if (!sym || sym_get_tristate_value(menu->sym) == no)
420 return false; 427 return false;
421 428
422 for (child = menu->list; child; child = child->next) 429 for (child = menu->list; child; child = child->next) {
423 if (menu_is_visible(child)) 430 if (menu_is_visible(child)) {
431 if (sym)
432 sym->flags |= SYMBOL_DEF_USER;
424 return true; 433 return true;
434 }
435 }
425 436
426 return false; 437 return false;
427} 438}
@@ -501,9 +512,19 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
501 bool hit; 512 bool hit;
502 struct property *prop; 513 struct property *prop;
503 514
504 if (sym && sym->name) 515 if (sym && sym->name) {
505 str_printf(r, "Symbol: %s [=%s]\n", sym->name, 516 str_printf(r, "Symbol: %s [=%s]\n", sym->name,
506 sym_get_string_value(sym)); 517 sym_get_string_value(sym));
518 str_printf(r, "Type : %s\n", sym_type_name(sym->type));
519 if (sym->type == S_INT || sym->type == S_HEX) {
520 prop = sym_get_range_prop(sym);
521 if (prop) {
522 str_printf(r, "Range : ");
523 expr_gstr_print(prop->expr, r);
524 str_append(r, "\n");
525 }
526 }
527 }
507 for_all_prompts(sym, prop) 528 for_all_prompts(sym, prop)
508 get_prompt_str(r, prop); 529 get_prompt_str(r, prop);
509 hit = false; 530 hit = false;
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 00c51507cfcc..820df2d1217b 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -58,11 +58,10 @@ QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
58{ 58{
59 QValueList<int> result; 59 QValueList<int> result;
60 QStringList entryList = readListEntry(key, ok); 60 QStringList entryList = readListEntry(key, ok);
61 if (ok) { 61 QStringList::Iterator it;
62 QStringList::Iterator it; 62
63 for (it = entryList.begin(); it != entryList.end(); ++it) 63 for (it = entryList.begin(); it != entryList.end(); ++it)
64 result.push_back((*it).toInt()); 64 result.push_back((*it).toInt());
65 }
66 65
67 return result; 66 return result;
68} 67}
@@ -149,7 +148,7 @@ void ConfigItem::updateMenu(void)
149 case S_TRISTATE: 148 case S_TRISTATE:
150 char ch; 149 char ch;
151 150
152 if (!sym_is_changable(sym) && !list->showAll) { 151 if (!sym_is_changable(sym) && list->optMode == normalOpt) {
153 setPixmap(promptColIdx, 0); 152 setPixmap(promptColIdx, 0);
154 setText(noColIdx, QString::null); 153 setText(noColIdx, QString::null);
155 setText(modColIdx, QString::null); 154 setText(modColIdx, QString::null);
@@ -320,7 +319,7 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
320 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), 319 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
321 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), 320 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
322 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), 321 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
323 showAll(false), showName(false), showRange(false), showData(false), 322 showName(false), showRange(false), showData(false), optMode(normalOpt),
324 rootEntry(0), headerPopup(0) 323 rootEntry(0), headerPopup(0)
325{ 324{
326 int i; 325 int i;
@@ -337,10 +336,10 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
337 336
338 if (name) { 337 if (name) {
339 configSettings->beginGroup(name); 338 configSettings->beginGroup(name);
340 showAll = configSettings->readBoolEntry("/showAll", false);
341 showName = configSettings->readBoolEntry("/showName", false); 339 showName = configSettings->readBoolEntry("/showName", false);
342 showRange = configSettings->readBoolEntry("/showRange", false); 340 showRange = configSettings->readBoolEntry("/showRange", false);
343 showData = configSettings->readBoolEntry("/showData", false); 341 showData = configSettings->readBoolEntry("/showData", false);
342 optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false);
344 configSettings->endGroup(); 343 configSettings->endGroup();
345 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); 344 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
346 } 345 }
@@ -352,6 +351,17 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
352 reinit(); 351 reinit();
353} 352}
354 353
354bool ConfigList::menuSkip(struct menu *menu)
355{
356 if (optMode == normalOpt && menu_is_visible(menu))
357 return false;
358 if (optMode == promptOpt && menu_has_prompt(menu))
359 return false;
360 if (optMode == allOpt)
361 return false;
362 return true;
363}
364
355void ConfigList::reinit(void) 365void ConfigList::reinit(void)
356{ 366{
357 removeColumn(dataColIdx); 367 removeColumn(dataColIdx);
@@ -380,7 +390,7 @@ void ConfigList::saveSettings(void)
380 configSettings->writeEntry("/showName", showName); 390 configSettings->writeEntry("/showName", showName);
381 configSettings->writeEntry("/showRange", showRange); 391 configSettings->writeEntry("/showRange", showRange);
382 configSettings->writeEntry("/showData", showData); 392 configSettings->writeEntry("/showData", showData);
383 configSettings->writeEntry("/showAll", showAll); 393 configSettings->writeEntry("/optionMode", (int)optMode);
384 configSettings->endGroup(); 394 configSettings->endGroup();
385 } 395 }
386} 396}
@@ -606,7 +616,7 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
606 } 616 }
607 617
608 visible = menu_is_visible(child); 618 visible = menu_is_visible(child);
609 if (showAll || visible) { 619 if (!menuSkip(child)) {
610 if (!child->sym && !child->list && !child->prompt) 620 if (!child->sym && !child->list && !child->prompt)
611 continue; 621 continue;
612 if (!item || item->menu != child) 622 if (!item || item->menu != child)
@@ -835,7 +845,10 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
835 e->ignore(); 845 e->ignore();
836} 846}
837 847
838ConfigView* ConfigView::viewList; 848ConfigView*ConfigView::viewList;
849QAction *ConfigView::showNormalAction;
850QAction *ConfigView::showAllAction;
851QAction *ConfigView::showPromptAction;
839 852
840ConfigView::ConfigView(QWidget* parent, const char *name) 853ConfigView::ConfigView(QWidget* parent, const char *name)
841 : Parent(parent, name) 854 : Parent(parent, name)
@@ -860,13 +873,16 @@ ConfigView::~ConfigView(void)
860 } 873 }
861} 874}
862 875
863void ConfigView::setShowAll(bool b) 876void ConfigView::setOptionMode(QAction *act)
864{ 877{
865 if (list->showAll != b) { 878 if (act == showNormalAction)
866 list->showAll = b; 879 list->optMode = normalOpt;
867 list->updateListAll(); 880 else if (act == showAllAction)
868 emit showAllChanged(b); 881 list->optMode = allOpt;
869 } 882 else
883 list->optMode = promptOpt;
884
885 list->updateListAll();
870} 886}
871 887
872void ConfigView::setShowName(bool b) 888void ConfigView::setShowName(bool b)
@@ -964,34 +980,6 @@ void ConfigInfoView::setInfo(struct menu *m)
964 menuInfo(); 980 menuInfo();
965} 981}
966 982
967void ConfigInfoView::setSource(const QString& name)
968{
969 const char *p = name.latin1();
970
971 menu = NULL;
972 sym = NULL;
973
974 switch (p[0]) {
975 case 'm':
976 struct menu *m;
977
978 if (sscanf(p, "m%p", &m) == 1 && menu != m) {
979 menu = m;
980 menuInfo();
981 emit menuSelected(menu);
982 }
983 break;
984 case 's':
985 struct symbol *s;
986
987 if (sscanf(p, "s%p", &s) == 1 && sym != s) {
988 sym = s;
989 symbolInfo();
990 }
991 break;
992 }
993}
994
995void ConfigInfoView::symbolInfo(void) 983void ConfigInfoView::symbolInfo(void)
996{ 984{
997 QString str; 985 QString str;
@@ -1349,11 +1337,24 @@ ConfigMainWindow::ConfigMainWindow(void)
1349 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); 1337 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
1350 connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); 1338 connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
1351 showDataAction->setOn(configList->showData); 1339 showDataAction->setOn(configList->showData);
1352 QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this); 1340
1353 showAllAction->setToggleAction(TRUE); 1341 QActionGroup *optGroup = new QActionGroup(this);
1354 connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool))); 1342 optGroup->setExclusive(TRUE);
1355 connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool))); 1343 connect(optGroup, SIGNAL(selected(QAction *)), configView,
1356 showAllAction->setOn(configList->showAll); 1344 SLOT(setOptionMode(QAction *)));
1345 connect(optGroup, SIGNAL(selected(QAction *)), menuView,
1346 SLOT(setOptionMode(QAction *)));
1347
1348 configView->showNormalAction = new QAction(NULL, _("Show Normal Options"), 0, optGroup);
1349 configView->showAllAction = new QAction(NULL, _("Show All Options"), 0, optGroup);
1350 configView->showPromptAction = new QAction(NULL, _("Show Prompt Options"), 0, optGroup);
1351 configView->showNormalAction->setToggleAction(TRUE);
1352 configView->showNormalAction->setOn(configList->optMode == normalOpt);
1353 configView->showAllAction->setToggleAction(TRUE);
1354 configView->showAllAction->setOn(configList->optMode == allOpt);
1355 configView->showPromptAction->setToggleAction(TRUE);
1356 configView->showPromptAction->setOn(configList->optMode == promptOpt);
1357
1357 QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this); 1358 QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this);
1358 showDebugAction->setToggleAction(TRUE); 1359 showDebugAction->setToggleAction(TRUE);
1359 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); 1360 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
@@ -1396,7 +1397,8 @@ ConfigMainWindow::ConfigMainWindow(void)
1396 showRangeAction->addTo(optionMenu); 1397 showRangeAction->addTo(optionMenu);
1397 showDataAction->addTo(optionMenu); 1398 showDataAction->addTo(optionMenu);
1398 optionMenu->insertSeparator(); 1399 optionMenu->insertSeparator();
1399 showAllAction->addTo(optionMenu); 1400 optGroup->addTo(optionMenu);
1401 optionMenu->insertSeparator();
1400 showDebugAction->addTo(optionMenu); 1402 showDebugAction->addTo(optionMenu);
1401 1403
1402 // create help menu 1404 // create help menu
@@ -1491,7 +1493,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
1491 ConfigList* list = NULL; 1493 ConfigList* list = NULL;
1492 ConfigItem* item; 1494 ConfigItem* item;
1493 1495
1494 if (!menu_is_visible(menu) && !configView->showAll()) 1496 if (configList->menuSkip(menu))
1495 return; 1497 return;
1496 1498
1497 switch (configList->mode) { 1499 switch (configList->mode) {
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index b3b5657b6b35..636a74b23bf9 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -44,6 +44,9 @@ enum colIdx {
44enum listMode { 44enum listMode {
45 singleMode, menuMode, symbolMode, fullMode, listMode 45 singleMode, menuMode, symbolMode, fullMode, listMode
46}; 46};
47enum optionMode {
48 normalOpt = 0, allOpt, promptOpt
49};
47 50
48class ConfigList : public QListView { 51class ConfigList : public QListView {
49 Q_OBJECT 52 Q_OBJECT
@@ -115,6 +118,8 @@ public:
115 void setAllOpen(bool open); 118 void setAllOpen(bool open);
116 void setParentMenu(void); 119 void setParentMenu(void);
117 120
121 bool menuSkip(struct menu *);
122
118 template <class P> 123 template <class P>
119 void updateMenuList(P*, struct menu*); 124 void updateMenuList(P*, struct menu*);
120 125
@@ -124,8 +129,9 @@ public:
124 QPixmap choiceYesPix, choiceNoPix; 129 QPixmap choiceYesPix, choiceNoPix;
125 QPixmap menuPix, menuInvPix, menuBackPix, voidPix; 130 QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
126 131
127 bool showAll, showName, showRange, showData; 132 bool showName, showRange, showData;
128 enum listMode mode; 133 enum listMode mode;
134 enum optionMode optMode;
129 struct menu *rootEntry; 135 struct menu *rootEntry;
130 QColorGroup disabledColorGroup; 136 QColorGroup disabledColorGroup;
131 QColorGroup inactivedColorGroup; 137 QColorGroup inactivedColorGroup;
@@ -222,17 +228,15 @@ public:
222 static void updateList(ConfigItem* item); 228 static void updateList(ConfigItem* item);
223 static void updateListAll(void); 229 static void updateListAll(void);
224 230
225 bool showAll(void) const { return list->showAll; }
226 bool showName(void) const { return list->showName; } 231 bool showName(void) const { return list->showName; }
227 bool showRange(void) const { return list->showRange; } 232 bool showRange(void) const { return list->showRange; }
228 bool showData(void) const { return list->showData; } 233 bool showData(void) const { return list->showData; }
229public slots: 234public slots:
230 void setShowAll(bool);
231 void setShowName(bool); 235 void setShowName(bool);
232 void setShowRange(bool); 236 void setShowRange(bool);
233 void setShowData(bool); 237 void setShowData(bool);
238 void setOptionMode(QAction *);
234signals: 239signals:
235 void showAllChanged(bool);
236 void showNameChanged(bool); 240 void showNameChanged(bool);
237 void showRangeChanged(bool); 241 void showRangeChanged(bool);
238 void showDataChanged(bool); 242 void showDataChanged(bool);
@@ -242,6 +246,10 @@ public:
242 246
243 static ConfigView* viewList; 247 static ConfigView* viewList;
244 ConfigView* nextView; 248 ConfigView* nextView;
249
250 static QAction *showNormalAction;
251 static QAction *showAllAction;
252 static QAction *showPromptAction;
245}; 253};
246 254
247class ConfigInfoView : public QTextBrowser { 255class ConfigInfoView : public QTextBrowser {
@@ -254,7 +262,6 @@ public:
254public slots: 262public slots:
255 void setInfo(struct menu *menu); 263 void setInfo(struct menu *menu);
256 void saveSettings(void); 264 void saveSettings(void);
257 void setSource(const QString& name);
258 void setShowDebug(bool); 265 void setShowDebug(bool);
259 266
260signals: 267signals:
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 2e7a048e0cfc..e95718fea355 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -205,6 +205,16 @@ static void sym_calc_visibility(struct symbol *sym)
205 } 205 }
206 if (sym_is_choice_value(sym)) 206 if (sym_is_choice_value(sym))
207 return; 207 return;
208 /* defaulting to "yes" if no explicit "depends on" are given */
209 tri = yes;
210 if (sym->dir_dep.expr)
211 tri = expr_calc_value(sym->dir_dep.expr);
212 if (tri == mod)
213 tri = yes;
214 if (sym->dir_dep.tri != tri) {
215 sym->dir_dep.tri = tri;
216 sym_set_changed(sym);
217 }
208 tri = no; 218 tri = no;
209 if (sym->rev_dep.expr) 219 if (sym->rev_dep.expr)
210 tri = expr_calc_value(sym->rev_dep.expr); 220 tri = expr_calc_value(sym->rev_dep.expr);
@@ -216,44 +226,63 @@ static void sym_calc_visibility(struct symbol *sym)
216 } 226 }
217} 227}
218 228
219static struct symbol *sym_calc_choice(struct symbol *sym) 229/*
230 * Find the default symbol for a choice.
231 * First try the default values for the choice symbol
232 * Next locate the first visible choice value
233 * Return NULL if none was found
234 */
235struct symbol *sym_choice_default(struct symbol *sym)
220{ 236{
221 struct symbol *def_sym; 237 struct symbol *def_sym;
222 struct property *prop; 238 struct property *prop;
223 struct expr *e; 239 struct expr *e;
224 240
225 /* is the user choice visible? */
226 def_sym = sym->def[S_DEF_USER].val;
227 if (def_sym) {
228 sym_calc_visibility(def_sym);
229 if (def_sym->visible != no)
230 return def_sym;
231 }
232
233 /* any of the defaults visible? */ 241 /* any of the defaults visible? */
234 for_all_defaults(sym, prop) { 242 for_all_defaults(sym, prop) {
235 prop->visible.tri = expr_calc_value(prop->visible.expr); 243 prop->visible.tri = expr_calc_value(prop->visible.expr);
236 if (prop->visible.tri == no) 244 if (prop->visible.tri == no)
237 continue; 245 continue;
238 def_sym = prop_get_symbol(prop); 246 def_sym = prop_get_symbol(prop);
239 sym_calc_visibility(def_sym);
240 if (def_sym->visible != no) 247 if (def_sym->visible != no)
241 return def_sym; 248 return def_sym;
242 } 249 }
243 250
244 /* just get the first visible value */ 251 /* just get the first visible value */
245 prop = sym_get_choice_prop(sym); 252 prop = sym_get_choice_prop(sym);
246 expr_list_for_each_sym(prop->expr, e, def_sym) { 253 expr_list_for_each_sym(prop->expr, e, def_sym)
247 sym_calc_visibility(def_sym);
248 if (def_sym->visible != no) 254 if (def_sym->visible != no)
249 return def_sym; 255 return def_sym;
250 }
251 256
252 /* no choice? reset tristate value */ 257 /* failed to locate any defaults */
253 sym->curr.tri = no;
254 return NULL; 258 return NULL;
255} 259}
256 260
261static struct symbol *sym_calc_choice(struct symbol *sym)
262{
263 struct symbol *def_sym;
264 struct property *prop;
265 struct expr *e;
266
267 /* first calculate all choice values' visibilities */
268 prop = sym_get_choice_prop(sym);
269 expr_list_for_each_sym(prop->expr, e, def_sym)
270 sym_calc_visibility(def_sym);
271
272 /* is the user choice visible? */
273 def_sym = sym->def[S_DEF_USER].val;
274 if (def_sym && def_sym->visible != no)
275 return def_sym;
276
277 def_sym = sym_choice_default(sym);
278
279 if (def_sym == NULL)
280 /* no choice? reset tristate value */
281 sym->curr.tri = no;
282
283 return def_sym;
284}
285
257void sym_calc_value(struct symbol *sym) 286void sym_calc_value(struct symbol *sym)
258{ 287{
259 struct symbol_value newval, oldval; 288 struct symbol_value newval, oldval;
@@ -321,6 +350,14 @@ void sym_calc_value(struct symbol *sym)
321 } 350 }
322 } 351 }
323 calc_newval: 352 calc_newval:
353 if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
354 fprintf(stderr, "warning: (");
355 expr_fprint(sym->rev_dep.expr, stderr);
356 fprintf(stderr, ") selects %s which has unmet direct dependencies (",
357 sym->name);
358 expr_fprint(sym->dir_dep.expr, stderr);
359 fprintf(stderr, ")\n");
360 }
324 newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); 361 newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
325 } 362 }
326 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) 363 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
@@ -365,12 +402,13 @@ void sym_calc_value(struct symbol *sym)
365 402
366 if (sym_is_choice(sym)) { 403 if (sym_is_choice(sym)) {
367 struct symbol *choice_sym; 404 struct symbol *choice_sym;
368 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
369 405
370 prop = sym_get_choice_prop(sym); 406 prop = sym_get_choice_prop(sym);
371 expr_list_for_each_sym(prop->expr, e, choice_sym) { 407 expr_list_for_each_sym(prop->expr, e, choice_sym) {
372 choice_sym->flags |= flags; 408 if ((sym->flags & SYMBOL_WRITE) &&
373 if (flags & SYMBOL_CHANGED) 409 choice_sym->visible != no)
410 choice_sym->flags |= SYMBOL_WRITE;
411 if (sym->flags & SYMBOL_CHANGED)
374 sym_set_changed(choice_sym); 412 sym_set_changed(choice_sym);
375 } 413 }
376 } 414 }
@@ -623,6 +661,80 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
623 return true; 661 return true;
624} 662}
625 663
664/*
665 * Find the default value associated to a symbol.
666 * For tristate symbol handle the modules=n case
667 * in which case "m" becomes "y".
668 * If the symbol does not have any default then fallback
669 * to the fixed default values.
670 */
671const char *sym_get_string_default(struct symbol *sym)
672{
673 struct property *prop;
674 struct symbol *ds;
675 const char *str;
676 tristate val;
677
678 sym_calc_visibility(sym);
679 sym_calc_value(modules_sym);
680 val = symbol_no.curr.tri;
681 str = symbol_empty.curr.val;
682
683 /* If symbol has a default value look it up */
684 prop = sym_get_default_prop(sym);
685 if (prop != NULL) {
686 switch (sym->type) {
687 case S_BOOLEAN:
688 case S_TRISTATE:
689 /* The visibility imay limit the value from yes => mod */
690 val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
691 break;
692 default:
693 /*
694 * The following fails to handle the situation
695 * where a default value is further limited by
696 * the valid range.
697 */
698 ds = prop_get_symbol(prop);
699 if (ds != NULL) {
700 sym_calc_value(ds);
701 str = (const char *)ds->curr.val;
702 }
703 }
704 }
705
706 /* Handle select statements */
707 val = EXPR_OR(val, sym->rev_dep.tri);
708
709 /* transpose mod to yes if modules are not enabled */
710 if (val == mod)
711 if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
712 val = yes;
713
714 /* transpose mod to yes if type is bool */
715 if (sym->type == S_BOOLEAN && val == mod)
716 val = yes;
717
718 switch (sym->type) {
719 case S_BOOLEAN:
720 case S_TRISTATE:
721 switch (val) {
722 case no: return "n";
723 case mod: return "m";
724 case yes: return "y";
725 }
726 case S_INT:
727 case S_HEX:
728 return str;
729 case S_STRING:
730 return str;
731 case S_OTHER:
732 case S_UNKNOWN:
733 break;
734 }
735 return "";
736}
737
626const char *sym_get_string_value(struct symbol *sym) 738const char *sym_get_string_value(struct symbol *sym)
627{ 739{
628 tristate val; 740 tristate val;
@@ -765,6 +877,110 @@ struct symbol **sym_re_search(const char *pattern)
765 return sym_arr; 877 return sym_arr;
766} 878}
767 879
880/*
881 * When we check for recursive dependencies we use a stack to save
882 * current state so we can print out relevant info to user.
883 * The entries are located on the call stack so no need to free memory.
884 * Note inser() remove() must always match to properly clear the stack.
885 */
886static struct dep_stack {
887 struct dep_stack *prev, *next;
888 struct symbol *sym;
889 struct property *prop;
890 struct expr *expr;
891} *check_top;
892
893static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
894{
895 memset(stack, 0, sizeof(*stack));
896 if (check_top)
897 check_top->next = stack;
898 stack->prev = check_top;
899 stack->sym = sym;
900 check_top = stack;
901}
902
903static void dep_stack_remove(void)
904{
905 check_top = check_top->prev;
906 if (check_top)
907 check_top->next = NULL;
908}
909
910/*
911 * Called when we have detected a recursive dependency.
912 * check_top point to the top of the stact so we use
913 * the ->prev pointer to locate the bottom of the stack.
914 */
915static void sym_check_print_recursive(struct symbol *last_sym)
916{
917 struct dep_stack *stack;
918 struct symbol *sym, *next_sym;
919 struct menu *menu = NULL;
920 struct property *prop;
921 struct dep_stack cv_stack;
922
923 if (sym_is_choice_value(last_sym)) {
924 dep_stack_insert(&cv_stack, last_sym);
925 last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
926 }
927
928 for (stack = check_top; stack != NULL; stack = stack->prev)
929 if (stack->sym == last_sym)
930 break;
931 if (!stack) {
932 fprintf(stderr, "unexpected recursive dependency error\n");
933 return;
934 }
935
936 for (; stack; stack = stack->next) {
937 sym = stack->sym;
938 next_sym = stack->next ? stack->next->sym : last_sym;
939 prop = stack->prop;
940
941 /* for choice values find the menu entry (used below) */
942 if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
943 for (prop = sym->prop; prop; prop = prop->next) {
944 menu = prop->menu;
945 if (prop->menu)
946 break;
947 }
948 }
949 if (stack->sym == last_sym)
950 fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
951 prop->file->name, prop->lineno);
952 if (stack->expr) {
953 fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
954 prop->file->name, prop->lineno,
955 sym->name ? sym->name : "<choice>",
956 prop_get_type_name(prop->type),
957 next_sym->name ? next_sym->name : "<choice>");
958 } else if (stack->prop) {
959 fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
960 prop->file->name, prop->lineno,
961 sym->name ? sym->name : "<choice>",
962 next_sym->name ? next_sym->name : "<choice>");
963 } else if (sym_is_choice(sym)) {
964 fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
965 menu->file->name, menu->lineno,
966 sym->name ? sym->name : "<choice>",
967 next_sym->name ? next_sym->name : "<choice>");
968 } else if (sym_is_choice_value(sym)) {
969 fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
970 menu->file->name, menu->lineno,
971 sym->name ? sym->name : "<choice>",
972 next_sym->name ? next_sym->name : "<choice>");
973 } else {
974 fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
975 prop->file->name, prop->lineno,
976 sym->name ? sym->name : "<choice>",
977 next_sym->name ? next_sym->name : "<choice>");
978 }
979 }
980
981 if (check_top == &cv_stack)
982 dep_stack_remove();
983}
768 984
769static struct symbol *sym_check_expr_deps(struct expr *e) 985static struct symbol *sym_check_expr_deps(struct expr *e)
770{ 986{
@@ -801,24 +1017,33 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
801{ 1017{
802 struct symbol *sym2; 1018 struct symbol *sym2;
803 struct property *prop; 1019 struct property *prop;
1020 struct dep_stack stack;
1021
1022 dep_stack_insert(&stack, sym);
804 1023
805 sym2 = sym_check_expr_deps(sym->rev_dep.expr); 1024 sym2 = sym_check_expr_deps(sym->rev_dep.expr);
806 if (sym2) 1025 if (sym2)
807 return sym2; 1026 goto out;
808 1027
809 for (prop = sym->prop; prop; prop = prop->next) { 1028 for (prop = sym->prop; prop; prop = prop->next) {
810 if (prop->type == P_CHOICE || prop->type == P_SELECT) 1029 if (prop->type == P_CHOICE || prop->type == P_SELECT)
811 continue; 1030 continue;
1031 stack.prop = prop;
812 sym2 = sym_check_expr_deps(prop->visible.expr); 1032 sym2 = sym_check_expr_deps(prop->visible.expr);
813 if (sym2) 1033 if (sym2)
814 break; 1034 break;
815 if (prop->type != P_DEFAULT || sym_is_choice(sym)) 1035 if (prop->type != P_DEFAULT || sym_is_choice(sym))
816 continue; 1036 continue;
1037 stack.expr = prop->expr;
817 sym2 = sym_check_expr_deps(prop->expr); 1038 sym2 = sym_check_expr_deps(prop->expr);
818 if (sym2) 1039 if (sym2)
819 break; 1040 break;
1041 stack.expr = NULL;
820 } 1042 }
821 1043
1044out:
1045 dep_stack_remove();
1046
822 return sym2; 1047 return sym2;
823} 1048}
824 1049
@@ -827,6 +1052,9 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
827 struct symbol *sym, *sym2; 1052 struct symbol *sym, *sym2;
828 struct property *prop; 1053 struct property *prop;
829 struct expr *e; 1054 struct expr *e;
1055 struct dep_stack stack;
1056
1057 dep_stack_insert(&stack, choice);
830 1058
831 prop = sym_get_choice_prop(choice); 1059 prop = sym_get_choice_prop(choice);
832 expr_list_for_each_sym(prop->expr, e, sym) 1060 expr_list_for_each_sym(prop->expr, e, sym)
@@ -840,10 +1068,8 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
840 1068
841 expr_list_for_each_sym(prop->expr, e, sym) { 1069 expr_list_for_each_sym(prop->expr, e, sym) {
842 sym2 = sym_check_sym_deps(sym); 1070 sym2 = sym_check_sym_deps(sym);
843 if (sym2) { 1071 if (sym2)
844 fprintf(stderr, " -> %s", sym->name);
845 break; 1072 break;
846 }
847 } 1073 }
848out: 1074out:
849 expr_list_for_each_sym(prop->expr, e, sym) 1075 expr_list_for_each_sym(prop->expr, e, sym)
@@ -853,6 +1079,8 @@ out:
853 prop_get_symbol(sym_get_choice_prop(sym2)) == choice) 1079 prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
854 sym2 = choice; 1080 sym2 = choice;
855 1081
1082 dep_stack_remove();
1083
856 return sym2; 1084 return sym2;
857} 1085}
858 1086
@@ -862,18 +1090,20 @@ struct symbol *sym_check_deps(struct symbol *sym)
862 struct property *prop; 1090 struct property *prop;
863 1091
864 if (sym->flags & SYMBOL_CHECK) { 1092 if (sym->flags & SYMBOL_CHECK) {
865 fprintf(stderr, "%s:%d:error: found recursive dependency: %s", 1093 sym_check_print_recursive(sym);
866 sym->prop->file->name, sym->prop->lineno,
867 sym->name ? sym->name : "<choice>");
868 return sym; 1094 return sym;
869 } 1095 }
870 if (sym->flags & SYMBOL_CHECKED) 1096 if (sym->flags & SYMBOL_CHECKED)
871 return NULL; 1097 return NULL;
872 1098
873 if (sym_is_choice_value(sym)) { 1099 if (sym_is_choice_value(sym)) {
1100 struct dep_stack stack;
1101
874 /* for choice groups start the check with main choice symbol */ 1102 /* for choice groups start the check with main choice symbol */
1103 dep_stack_insert(&stack, sym);
875 prop = sym_get_choice_prop(sym); 1104 prop = sym_get_choice_prop(sym);
876 sym2 = sym_check_deps(prop_get_symbol(prop)); 1105 sym2 = sym_check_deps(prop_get_symbol(prop));
1106 dep_stack_remove();
877 } else if (sym_is_choice(sym)) { 1107 } else if (sym_is_choice(sym)) {
878 sym2 = sym_check_choice_deps(sym); 1108 sym2 = sym_check_choice_deps(sym);
879 } else { 1109 } else {
@@ -882,14 +1112,8 @@ struct symbol *sym_check_deps(struct symbol *sym)
882 sym->flags &= ~SYMBOL_CHECK; 1112 sym->flags &= ~SYMBOL_CHECK;
883 } 1113 }
884 1114
885 if (sym2) { 1115 if (sym2 && sym2 == sym)
886 fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>"); 1116 sym2 = NULL;
887 if (sym2 == sym) {
888 fprintf(stderr, "\n");
889 zconfnerrs++;
890 sym2 = NULL;
891 }
892 }
893 1117
894 return sym2; 1118 return sym2;
895} 1119}
@@ -943,6 +1167,8 @@ const char *prop_get_type_name(enum prop_type type)
943 return "select"; 1167 return "select";
944 case P_RANGE: 1168 case P_RANGE:
945 return "range"; 1169 return "range";
1170 case P_SYMBOL:
1171 return "symbol";
946 case P_UNKNOWN: 1172 case P_UNKNOWN:
947 break; 1173 break;
948 } 1174 }