diff options
Diffstat (limited to 'scripts/kconfig')
38 files changed, 3295 insertions, 1878 deletions
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore index 624f6502e03..be603c4fef6 100644 --- a/scripts/kconfig/.gitignore +++ b/scripts/kconfig/.gitignore @@ -2,12 +2,11 @@ # Generated files # config* -lex.*.c +*.lex.c *.tab.c *.tab.h zconf.hash.c *.moc -lkc_defs.h gconf.glade.h *.pot *.mo diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 368ae306aee..9c4d2412fb7 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -11,6 +11,9 @@ else Kconfig := Kconfig endif +# We need this, in case the user has it in its environment +unexport CONFIG_ + xconfig: $(obj)/qconf $< $(Kconfig) @@ -30,20 +33,12 @@ oldconfig: $(obj)/conf $< --$@ $(Kconfig) silentoldconfig: $(obj)/conf - $(Q)mkdir -p include/generated + $(Q)mkdir -p include/config include/generated $< --$@ $(Kconfig) -# if no path is given, then use src directory to find file -ifdef LSMOD -LSMOD_F := $(LSMOD) -ifeq ($(findstring /,$(LSMOD)),) - LSMOD_F := $(objtree)/$(LSMOD) -endif -endif - -localmodconfig: $(obj)/streamline_config.pl $(obj)/conf - $(Q)mkdir -p include/generated - $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config +localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf + $(Q)mkdir -p include/config include/generated + $(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config $(Q)if [ -f .config ]; then \ cmp -s .tmp.config .config || \ (mv -f .config .config.old.1; \ @@ -56,43 +51,27 @@ localmodconfig: $(obj)/streamline_config.pl $(obj)/conf fi $(Q)rm -f .tmp.config -localyesconfig: $(obj)/streamline_config.pl $(obj)/conf - $(Q)mkdir -p include/generated - $(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config - $(Q)sed -i s/=m/=y/ .tmp.config - $(Q)if [ -f .config ]; then \ - cmp -s .tmp.config .config || \ - (mv -f .config .config.old.1; \ - mv -f .tmp.config .config; \ - $(obj)/conf --silentoldconfig $(Kconfig); \ - mv -f .config.old.1 .config.old) \ - else \ - mv -f .tmp.config .config; \ - $(obj)/conf --silentoldconfig $(Kconfig); \ - fi - $(Q)rm -f .tmp.config - # Create new linux.pot file # Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files -# The symlink is used to repair a deficiency in arch/um update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h - $(Q)echo " GEN config" - $(Q)xgettext --default-domain=linux \ - --add-comments --keyword=_ --keyword=N_ \ - --from-code=UTF-8 \ - --files-from=scripts/kconfig/POTFILES.in \ + $(Q)echo " GEN config.pot" + $(Q)xgettext --default-domain=linux \ + --add-comments --keyword=_ --keyword=N_ \ + --from-code=UTF-8 \ + --files-from=$(srctree)/scripts/kconfig/POTFILES.in \ + --directory=$(srctree) --directory=$(objtree) \ --output $(obj)/config.pot $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot - $(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch - $(Q)(for i in `ls arch/*/Kconfig`; \ + $(Q)(for i in `ls $(srctree)/arch/*/Kconfig \ + $(srctree)/arch/*/um/Kconfig`; \ do \ - echo " GEN $$i"; \ + echo " GEN $$i"; \ $(obj)/kxgettext $$i \ >> $(obj)/config.pot; \ done ) + $(Q)echo " GEN linux.pot" $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ --output $(obj)/linux.pot - $(Q)rm -f arch/um/Kconfig.arch $(Q)rm -f $(obj)/config.pot PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig @@ -100,11 +79,17 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf $< --$@ $(Kconfig) -PHONY += listnewconfig oldnoconfig savedefconfig defconfig +PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig -listnewconfig oldnoconfig: $(obj)/conf +listnewconfig olddefconfig: $(obj)/conf $< --$@ $(Kconfig) +# oldnoconfig is an alias of olddefconfig, because people already are dependent +# on its behavior(sets new symbols to their default value but not 'n') with the +# counter-intuitive name. +oldnoconfig: $(obj)/conf + $< --olddefconfig $(Kconfig) + savedefconfig: $(obj)/conf $< --$@=defconfig $(Kconfig) @@ -138,7 +123,7 @@ help: @echo ' alldefconfig - New config with all symbols set to default' @echo ' randconfig - New config with random answer to all options' @echo ' listnewconfig - List new options' - @echo ' oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)' + @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value' # lxdialog stuff check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh @@ -168,8 +153,11 @@ conf-objs := conf.o zconf.tab.o mconf-objs := mconf.o zconf.tab.o $(lxdialog) nconf-objs := nconf.o zconf.tab.o nconf.gui.o kxgettext-objs := kxgettext.o zconf.tab.o +qconf-cxxobjs := qconf.o +qconf-objs := zconf.tab.o +gconf-objs := gconf.o zconf.tab.o -hostprogs-y := conf qconf gconf kxgettext +hostprogs-y := conf ifeq ($(MAKECMDGOALS),nconfig) hostprogs-y += nconf @@ -179,6 +167,10 @@ ifeq ($(MAKECMDGOALS),menuconfig) hostprogs-y += mconf endif +ifeq ($(MAKECMDGOALS),update-po-config) + hostprogs-y += kxgettext +endif + ifeq ($(MAKECMDGOALS),xconfig) qconf-target := 1 endif @@ -188,16 +180,15 @@ endif ifeq ($(qconf-target),1) -qconf-cxxobjs := qconf.o -qconf-objs := kconfig_load.o zconf.tab.o + hostprogs-y += qconf endif ifeq ($(gconf-target),1) -gconf-objs := gconf.o kconfig_load.o zconf.tab.o + hostprogs-y += gconf endif -clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ - .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h +clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck +clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h clean-files += mconf qconf gconf nconf clean-files += config.pot linux.pot @@ -213,19 +204,24 @@ always := dochecklxdialog HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) # generated files seem to need this to find local include files -HOSTCFLAGS_lex.zconf.o := -I$(src) +HOSTCFLAGS_zconf.lex.o := -I$(src) HOSTCFLAGS_zconf.tab.o := -I$(src) -HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl -HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK +LEX_PREFIX_zconf := zconf +YACC_PREFIX_zconf := zconf -HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` -ldl +HOSTLOADLIBES_qconf = $(KC_QT_LIBS) +HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) + +HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ - -D LKC_DIRECT_LINK + -Wno-missing-prototypes HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) -HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses +HOSTLOADLIBES_nconf = $(shell \ + pkg-config --libs menu panel ncurses 2>/dev/null \ + || echo "-lmenu -lpanel -lncurses" ) $(obj)/qconf.o: $(obj)/.tmp_qtcheck ifeq ($(qconf-target),1) @@ -249,12 +245,12 @@ $(obj)/.tmp_qtcheck: if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ done; \ if [ -z "$$dir" ]; then \ - echo "*"; \ - echo "* Unable to find any QT installation. Please make sure that"; \ - echo "* the QT4 or QT3 development package is correctly installed and"; \ - echo "* either qmake can be found or install pkg-config or set"; \ - echo "* the QTDIR environment variable to the correct location."; \ - echo "*"; \ + echo >&2 "*"; \ + echo >&2 "* Unable to find any QT installation. Please make sure that"; \ + echo >&2 "* the QT4 or QT3 development package is correctly installed and"; \ + echo >&2 "* either qmake can be found or install pkg-config or set"; \ + echo >&2 "* the QTDIR environment variable to the correct location."; \ + echo >&2 "*"; \ false; \ fi; \ libpath=$$dir/lib; lib=qt; osdir=""; \ @@ -275,8 +271,8 @@ $(obj)/.tmp_qtcheck: else \ cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \ libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \ - binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \ - moc="$$binpath/bin/moc"; \ + moc="\$$(shell pkg-config QtCore --variable=moc_location)"; \ + [ -n "$$moc" ] || moc="\$$(shell pkg-config QtCore --variable=prefix)/bin/moc"; \ fi; \ echo "KC_QT_CFLAGS=$$cflags" > $@; \ echo "KC_QT_LIBS=$$libs" >> $@; \ @@ -294,61 +290,32 @@ $(obj)/.tmp_gtkcheck: if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ touch $@; \ else \ - echo "*"; \ - echo "* GTK+ is present but version >= 2.0.0 is required."; \ - echo "*"; \ + echo >&2 "*"; \ + echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \ + echo >&2 "*"; \ false; \ fi \ else \ - echo "*"; \ - echo "* Unable to find the GTK+ installation. Please make sure that"; \ - echo "* the GTK+ 2.0 development package is correctly installed..."; \ - echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ - echo "*"; \ + echo >&2 "*"; \ + echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; \ + echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; \ + echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo >&2 "*"; \ false; \ fi endif -$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c - -$(obj)/kconfig_load.o: $(obj)/lkc_defs.h +$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c -$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h +$(obj)/qconf.o: $(obj)/qconf.moc -$(obj)/gconf.o: $(obj)/lkc_defs.h +quiet_cmd_moc = MOC $@ + cmd_moc = $(KC_QT_MOC) -i $< -o $@ -$(obj)/%.moc: $(src)/%.h - $(KC_QT_MOC) -i $< -o $@ - -$(obj)/lkc_defs.h: $(src)/lkc_proto.h - sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' +$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck + $(call cmd,moc) # Extract gconf menu items for I18N support $(obj)/gconf.glade.h: $(obj)/gconf.glade - intltool-extract --type=gettext/glade $(obj)/gconf.glade - -### -# The following requires flex/bison/gperf -# By default we use the _shipped versions, uncomment the following line if -# you are modifying the flex/bison src. -# LKC_GENPARSER := 1 - -ifdef LKC_GENPARSER - -$(obj)/zconf.tab.c: $(src)/zconf.y -$(obj)/lex.zconf.c: $(src)/zconf.l -$(obj)/zconf.hash.c: $(src)/zconf.gperf - -%.tab.c: %.y - bison -l -b $* -p $(notdir $*) $< - cp $@ $@_shipped - -lex.%.c: %.l - flex -L -P$(notdir $*) -o$@ $< - cp $@ $@_shipped - -%.hash.c: %.gperf - gperf < $< > $@ - cp $@ $@_shipped - -endif + $(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \ + $(obj)/gconf.glade diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh index fa59cbf9d62..55b79ba1ba2 100755 --- a/scripts/kconfig/check.sh +++ b/scripts/kconfig/check.sh @@ -1,6 +1,6 @@ #!/bin/sh # Needed for systems without gettext -$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +$* -x c -o /dev/null - > /dev/null 2>&1 << EOF #include <libintl.h> int main() { @@ -11,4 +11,3 @@ EOF if [ ! "$?" -eq "0" ]; then echo -DKBUILD_NO_NLS; fi - diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 5459a38be86..fef75fc756f 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -13,12 +13,13 @@ #include <getopt.h> #include <sys/stat.h> #include <sys/time.h> +#include <errno.h> -#define LKC_DIRECT_LINK #include "lkc.h" static void conf(struct menu *menu); static void check_conf(struct menu *menu); +static void xfgets(char *str, int size, FILE *in); enum input_mode { oldaskconfig, @@ -32,12 +33,11 @@ enum input_mode { defconfig, savedefconfig, listnewconfig, - oldnoconfig, + olddefconfig, } input_mode = oldaskconfig; -char *defconfig_file; - static int indent = 1; +static int tty_stdio; static int valid_stdin = 1; static int sync_kconfig; static int conf_cnt; @@ -106,9 +106,12 @@ static int conf_askvalue(struct symbol *sym, const char *def) return 0; } check_stdin(); + /* fall through */ case oldaskconfig: fflush(stdout); xfgets(line, 128, stdin); + if (!tty_stdio) + printf("\n"); return 1; default: break; @@ -150,6 +153,7 @@ static int conf_string(struct menu *menu) def = NULL; break; } + /* fall through */ default: line[strlen(line)-1] = 0; def = line; @@ -304,6 +308,7 @@ static int conf_choice(struct menu *menu) break; } check_stdin(); + /* fall through */ case oldaskconfig: fflush(stdout); xfgets(line, 128, stdin); @@ -332,7 +337,7 @@ static int conf_choice(struct menu *menu) } if (!child) continue; - if (line[strlen(line) - 1] == '?') { + if (line[0] && line[strlen(line) - 1] == '?') { print_help(child); continue; } @@ -364,11 +369,12 @@ static void conf(struct menu *menu) case P_MENU: if ((input_mode == silentoldconfig || input_mode == listnewconfig || - input_mode == oldnoconfig) && + input_mode == olddefconfig) && rootEntry != menu) { check_conf(menu); return; } + /* fall through */ case P_COMMENT: prompt = menu_get_prompt(menu); if (prompt) @@ -427,7 +433,7 @@ static void check_conf(struct menu *menu) if (sym->name && !sym_is_choice_value(sym)) { printf("%s%s\n", CONFIG_, sym->name); } - } else if (input_mode != oldnoconfig) { + } else if (input_mode != olddefconfig) { if (!conf_cnt++) printf(_("*\n* Restart config...\n*\n")); rootEntry = menu_get_parent_menu(menu); @@ -452,20 +458,49 @@ static struct option long_opts[] = { {"alldefconfig", no_argument, NULL, alldefconfig}, {"randconfig", no_argument, NULL, randconfig}, {"listnewconfig", no_argument, NULL, listnewconfig}, - {"oldnoconfig", no_argument, NULL, oldnoconfig}, + {"olddefconfig", no_argument, NULL, olddefconfig}, + /* + * oldnoconfig is an alias of olddefconfig, because people already + * are dependent on its behavior(sets new symbols to their default + * value but not 'n') with the counter-intuitive name. + */ + {"oldnoconfig", no_argument, NULL, olddefconfig}, {NULL, 0, NULL, 0} }; +static void conf_usage(const char *progname) +{ + + printf("Usage: %s [option] <kconfig-file>\n", progname); + printf("[option] is _one_ of the following:\n"); + printf(" --listnewconfig List new options\n"); + printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); + printf(" --oldconfig Update a configuration using a provided .config as base\n"); + printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); + printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n"); + printf(" --oldnoconfig An alias of olddefconfig\n"); + printf(" --defconfig <file> New config with default defined in <file>\n"); + printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); + printf(" --allnoconfig New config where all options are answered with no\n"); + printf(" --allyesconfig New config where all options are answered with yes\n"); + printf(" --allmodconfig New config where all options are answered with mod\n"); + printf(" --alldefconfig New config with all symbols set to default\n"); + printf(" --randconfig New config with random answer to all options\n"); +} + int main(int ac, char **av) { + const char *progname = av[0]; int opt; - const char *name; + const char *name, *defconfig_file = NULL /* gcc uninit */; struct stat tmpstat; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + tty_stdio = isatty(0) && isatty(1) && isatty(2); + while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { input_mode = (enum input_mode)opt; switch (opt) { @@ -480,25 +515,45 @@ int main(int ac, char **av) { struct timeval now; unsigned int seed; + char *seed_env; /* * Use microseconds derived seed, * compensate for systems where it may be zero */ gettimeofday(&now, NULL); - seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); + + seed_env = getenv("KCONFIG_SEED"); + if( seed_env && *seed_env ) { + char *endp; + int tmp = (int)strtol(seed_env, &endp, 0); + if (*endp == '\0') { + seed = tmp; + } + } + fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed ); srand(seed); break; } + case oldaskconfig: + case oldconfig: + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case listnewconfig: + case olddefconfig: + break; case '?': - fprintf(stderr, _("See README for usage info\n")); + conf_usage(progname); exit(1); break; } } if (ac == optind) { printf(_("%s: Kconfig file missing\n"), av[0]); + conf_usage(progname); exit(1); } name = av[optind]; @@ -529,13 +584,11 @@ int main(int ac, char **av) } break; case savedefconfig: - conf_read(NULL); - break; case silentoldconfig: case oldaskconfig: case oldconfig: case listnewconfig: - case oldnoconfig: + case olddefconfig: conf_read(NULL); break; case allnoconfig: @@ -544,8 +597,15 @@ int main(int ac, char **av) case alldefconfig: case randconfig: name = getenv("KCONFIG_ALLCONFIG"); - if (name && !stat(name, &tmpstat)) { - conf_read_simple(name, S_DEF_USER); + if (!name) + break; + if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { + if (conf_read_simple(name, S_DEF_USER)) { + fprintf(stderr, + _("*** Can't read seed configuration \"%s\"!\n"), + name); + exit(1); + } break; } switch (input_mode) { @@ -556,10 +616,13 @@ int main(int ac, char **av) case randconfig: name = "allrandom.config"; break; default: break; } - if (!stat(name, &tmpstat)) - conf_read_simple(name, S_DEF_USER); - else if (!stat("all.config", &tmpstat)) - conf_read_simple("all.config", S_DEF_USER); + if (conf_read_simple(name, S_DEF_USER) && + conf_read_simple("all.config", S_DEF_USER)) { + fprintf(stderr, + _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), + name); + exit(1); + } break; default: break; @@ -574,7 +637,7 @@ int main(int ac, char **av) return 1; } } - valid_stdin = isatty(0) && isatty(1) && isatty(2); + valid_stdin = tty_stdio; } switch (input_mode) { @@ -591,7 +654,8 @@ int main(int ac, char **av) conf_set_all_new_symbols(def_default); break; case randconfig: - conf_set_all_new_symbols(def_random); + /* Really nothing to do in this loop */ + while (conf_set_all_new_symbols(def_random)) ; break; case defconfig: conf_set_all_new_symbols(def_default); @@ -605,7 +669,7 @@ int main(int ac, char **av) /* fall through */ case oldconfig: case listnewconfig: - case oldnoconfig: + case olddefconfig: case silentoldconfig: /* Update until a loop caused no more changes */ do { @@ -613,7 +677,7 @@ int main(int ac, char **av) check_conf(&rootmenu); } while (conf_cnt && (input_mode != listnewconfig && - input_mode != oldnoconfig)); + input_mode != olddefconfig)); break; } @@ -632,7 +696,7 @@ int main(int ac, char **av) } else if (input_mode == savedefconfig) { if (conf_write_defconfig(defconfig_file)) { fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), - defconfig_file); + defconfig_file); return 1; } } else if (input_mode != listnewconfig) { @@ -643,13 +707,11 @@ int main(int ac, char **av) } return 0; } + /* * Helper function to facilitate fgets() by Jean Sacren. */ -void xfgets(str, size, in) - char *str; - int size; - FILE *in; +void xfgets(char *str, int size, FILE *in) { if (fgets(str, size, in) == NULL) fprintf(stderr, "\nError in reading or end of file.\n"); diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 9df80114b47..f88d90f2022 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -7,13 +7,13 @@ #include <ctype.h> #include <errno.h> #include <fcntl.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> -#define LKC_DIRECT_LINK #include "lkc.h" static void conf_warning(const char *fmt, ...) @@ -128,6 +128,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) sym->flags |= def_flags; break; } + /* fall through */ case S_BOOLEAN: if (p[0] == 'y') { sym->def[def].tri = yes; @@ -139,8 +140,10 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) sym->flags |= def_flags; break; } - conf_warning("symbol value '%s' invalid for %s", p, sym->name); - break; + if (def != S_DEF_AUTO) + conf_warning("symbol value '%s' invalid for %s", + p, sym->name); + return 1; case S_OTHER: if (*p != '"') { for (p2 = p; *p2 && !isspace(*p2); p2++) @@ -148,6 +151,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) sym->type = S_STRING; goto done; } + /* fall through */ case S_STRING: if (*p++ != '"') break; @@ -159,9 +163,11 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) memmove(p2, p2 + 1, strlen(p2)); } if (!p2) { - conf_warning("invalid string found"); + if (def != S_DEF_AUTO) + conf_warning("invalid string found"); return 1; } + /* fall through */ case S_INT: case S_HEX: done: @@ -169,7 +175,9 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) sym->def[def].val = strdup(p); sym->flags |= def_flags; } else { - conf_warning("symbol value '%s' invalid for %s", p, sym->name); + if (def != S_DEF_AUTO) + conf_warning("symbol value '%s' invalid for %s", + p, sym->name); return 1; } break; @@ -179,10 +187,66 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) return 0; } +#define LINE_GROWTH 16 +static int add_byte(int c, char **lineptr, size_t slen, size_t *n) +{ + char *nline; + size_t new_size = slen + 1; + if (new_size > *n) { + new_size += LINE_GROWTH - 1; + new_size *= 2; + nline = realloc(*lineptr, new_size); + if (!nline) + return -1; + + *lineptr = nline; + *n = new_size; + } + + (*lineptr)[slen] = c; + + return 0; +} + +static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) +{ + char *line = *lineptr; + size_t slen = 0; + + for (;;) { + int c = getc(stream); + + switch (c) { + case '\n': + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + /* fall through */ + case EOF: + if (add_byte('\0', &line, slen, n) < 0) + goto e_out; + *lineptr = line; + if (slen == 0) + return -1; + return slen; + default: + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + } + } + +e_out: + line[slen-1] = '\0'; + *lineptr = line; + return -1; +} + int conf_read_simple(const char *name, int def) { FILE *in = NULL; - char line[1024]; + char *line = NULL; + size_t line_asize = 0; char *p, *p2; struct symbol *sym; int i, def_flags; @@ -237,13 +301,14 @@ load: case S_STRING: if (sym->def[def].val) free(sym->def[def].val); + /* fall through */ default: sym->def[def].val = NULL; sym->def[def].tri = no; } } - while (fgets(line, sizeof(line), in)) { + while (compat_getline(&line, &line_asize, in) != -1) { conf_lineno++; sym = NULL; if (line[0] == '#') { @@ -331,6 +396,7 @@ setsym: cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); } } + free(line); fclose(in); if (modules_sym) @@ -340,10 +406,8 @@ setsym: int conf_read(const char *name) { - struct symbol *sym, *choice_sym; - struct property *prop; - struct expr *e; - int i, flags; + struct symbol *sym; + int i; sym_set_change_count(0); @@ -353,7 +417,7 @@ int conf_read(const char *name) for_all_symbols(i, sym) { sym_calc_value(sym); if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) - goto sym_ok; + continue; if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { /* check that calculated value agrees with saved value */ switch (sym->type) { @@ -362,29 +426,18 @@ int conf_read(const char *name) if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) break; if (!sym_is_choice(sym)) - goto sym_ok; + continue; + /* fall through */ default: if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) - goto sym_ok; + continue; break; } } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) /* no previous value and not saved */ - goto sym_ok; + continue; conf_unsaved++; /* maybe print value in verbose mode... */ - sym_ok: - if (!sym_is_choice(sym)) - continue; - /* The choice symbol only has a set value (and thus is not new) - * if all its visible childs have values. - */ - prop = sym_get_choice_prop(sym); - flags = sym->flags; - expr_list_for_each_sym(prop->expr, e, choice_sym) - if (choice_sym->visible != no) - flags &= choice_sym->flags; - sym->flags &= flags | ~SYMBOL_DEF_USER; } for_all_symbols(i, sym) { @@ -417,65 +470,191 @@ int conf_read(const char *name) return 0; } -/* Write a S_STRING */ -static void conf_write_string(bool headerfile, const char *name, - const char *str, FILE *out) +/* + * Kconfig configuration printer + * + * This printer is used when generating the resulting configuration after + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by + * passing a non-NULL argument to the printer. + * + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) { - int l; - if (headerfile) - fprintf(out, "#define %s%s \"", CONFIG_, name); - else - fprintf(out, "%s%s=\"", CONFIG_, name); - - while (1) { - l = strcspn(str, "\"\\"); + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (*value == 'n') { + bool skip_unset = (arg != NULL); + + if (!skip_unset) + fprintf(fp, "# %s%s is not set\n", + CONFIG_, sym->name); + return; + } + break; + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); if (l) { - xfwrite(str, l, 1, out); - str += l; + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; } - if (!*str) + fprintf(fp, "\n"); + if (*p++ == '\0') break; - fprintf(out, "\\%c", *str++); } - fputs("\"\n", out); } -static void conf_write_symbol(struct symbol *sym, enum symbol_type type, - FILE *out, bool write_no) +static struct conf_printer kconfig_printer_cb = +{ + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * Header printer + * + * This printer is used when generating the `include/generated/autoconf.h' file. + */ +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) { - const char *str; - switch (type) { + switch (sym->type) { case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - if (write_no) - fprintf(out, "# %s%s is not set\n", - CONFIG_, sym->name); - break; - case mod: - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); - break; - case yes: - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); + case S_TRISTATE: { + const char *suffix = ""; + + switch (*value) { + case 'n': break; + case 'm': + suffix = "_MODULE"; + /* fall through */ + default: + fprintf(fp, "#define %s%s%s 1\n", + CONFIG_, sym->name, suffix); } break; - case S_STRING: - conf_write_string(false, sym->name, sym_get_string_value(sym), out); + } + case S_HEX: { + const char *prefix = ""; + + if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) + prefix = "0x"; + fprintf(fp, "#define %s%s %s%s\n", + CONFIG_, sym->name, prefix, value); break; - case S_HEX: + } + case S_STRING: case S_INT: - str = sym_get_string_value(sym); - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); + fprintf(fp, "#define %s%s %s\n", + CONFIG_, sym->name, value); + break; + default: break; + } + +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +/* + * Tristate printer + * + * This printer is used when generating the `include/config/tristate.conf' file. + */ +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + if (sym->type == S_TRISTATE && *value != 'n') + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { case S_OTHER: case S_UNKNOWN: break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); } } +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n", + rootmenu.prompt->text); + + printer->print_comment(fp, buf, printer_arg); +} + /* * Write out a minimal config. * All values that has default values are skipped as this is redundant. @@ -532,7 +711,7 @@ int conf_write_defconfig(const char *filename) goto next_menu; } } - conf_write_symbol(sym, sym->type, out, true); + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next_menu: if (menu->list != NULL) { @@ -561,9 +740,6 @@ int conf_write(const char *name) const char *basename; const char *str; char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; - enum symbol_type type; - time_t now; - int use_timestamp = 1; char *env; dirname[0] = 0; @@ -600,19 +776,7 @@ int conf_write(const char *name) if (!out) return 1; - time(&now); - env = getenv("KCONFIG_NOTIMESTAMP"); - if (env && *env) - use_timestamp = 0; - - fprintf(out, _("#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "%s%s" - "#\n"), - rootmenu.prompt->text, - use_timestamp ? "# " : "", - use_timestamp ? ctime(&now) : ""); + conf_write_heading(out, &kconfig_printer_cb, NULL); if (!conf_get_changed()) sym_clear_all_valid(); @@ -633,14 +797,8 @@ int conf_write(const char *name) if (!(sym->flags & SYMBOL_WRITE)) goto next; sym->flags &= ~SYMBOL_WRITE; - type = sym->type; - if (type == S_TRISTATE) { - sym_calc_value(modules_sym); - if (modules_sym->curr.tri == no) - type = S_BOOLEAN; - } - /* Write config symbol to file */ - conf_write_symbol(sym, type, out, true); + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next: @@ -789,10 +947,8 @@ out: int conf_write_autoconf(void) { struct symbol *sym; - const char *str; const char *name; FILE *out, *tristate, *out_h; - time_t now; int i; sym_clear_all_valid(); @@ -819,72 +975,23 @@ int conf_write_autoconf(void) return 1; } - time(&now); - fprintf(out, "#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "# %s" - "#\n", - rootmenu.prompt->text, ctime(&now)); - fprintf(tristate, "#\n" - "# Automatically generated - do not edit\n" - "\n"); - fprintf(out_h, "/*\n" - " * Automatically generated C config: don't edit\n" - " * %s\n" - " * %s" - " */\n" - "#define AUTOCONF_INCLUDED\n", - rootmenu.prompt->text, ctime(&now)); + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); for_all_symbols(i, sym) { sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE) || !sym->name) continue; - /* write symbol to config file */ - conf_write_symbol(sym, sym->type, out, false); + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); - /* update autoconf and tristate files */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - break; - case mod: - fprintf(tristate, "%s%s=M\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s_MODULE 1\n", - CONFIG_, sym->name); - break; - case yes: - if (sym->type == S_TRISTATE) - fprintf(tristate,"%s%s=Y\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s 1\n", - CONFIG_, sym->name); - break; - } - break; - case S_STRING: - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); - break; - case S_HEX: - str = sym_get_string_value(sym); - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out_h, "#define %s%s 0x%s\n", - CONFIG_, sym->name, str); - break; - } - case S_INT: - str = sym_get_string_value(sym); - fprintf(out_h, "#define %s%s %s\n", - CONFIG_, sym->name, str); - break; - default: - break; - } + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); } fclose(out); fclose(tristate); @@ -938,7 +1045,7 @@ void conf_set_changed_callback(void (*fn)(void)) conf_changed_callback = fn; } -static void randomize_choice_values(struct symbol *csym) +static bool randomize_choice_values(struct symbol *csym) { struct property *prop; struct symbol *sym; @@ -946,12 +1053,12 @@ static void randomize_choice_values(struct symbol *csym) int cnt, def; /* - * If choice is mod then we may have more items slected + * If choice is mod then we may have more items selected * and if no then no-one. * In both cases stop. */ if (csym->curr.tri != yes) - return; + return false; prop = sym_get_choice_prop(csym); @@ -975,13 +1082,18 @@ static void randomize_choice_values(struct symbol *csym) else { sym->def[S_DEF_USER].tri = no; } + sym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + sym->flags &= ~SYMBOL_VALID; } csym->flags |= SYMBOL_DEF_USER; /* clear VALID to get value calculated */ csym->flags &= ~(SYMBOL_VALID); + + return true; } -static void set_all_choice_values(struct symbol *csym) +void set_all_choice_values(struct symbol *csym) { struct property *prop; struct symbol *sym; @@ -998,20 +1110,66 @@ static void set_all_choice_values(struct symbol *csym) } csym->flags |= SYMBOL_DEF_USER; /* clear VALID to get value calculated */ - csym->flags &= ~(SYMBOL_VALID); + csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES); } -void conf_set_all_new_symbols(enum conf_def_mode mode) +bool conf_set_all_new_symbols(enum conf_def_mode mode) { struct symbol *sym, *csym; - int i, cnt; + int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y + * pty: probability of tristate = y + * ptm: probability of tristate = m + */ + + pby = 50; pty = ptm = 33; /* can't go as the default in switch-case + * below, otherwise gcc whines about + * -Wmaybe-uninitialized */ + if (mode == def_random) { + int n, p[3]; + char *env = getenv("KCONFIG_PROBABILITY"); + n = 0; + while( env && *env ) { + char *endp; + int tmp = strtol( env, &endp, 10 ); + if( tmp >= 0 && tmp <= 100 ) { + p[n++] = tmp; + } else { + errno = ERANGE; + perror( "KCONFIG_PROBABILITY" ); + exit( 1 ); + } + env = (*endp == ':') ? endp+1 : endp; + if( n >=3 ) { + break; + } + } + switch( n ) { + case 1: + pby = p[0]; ptm = pby/2; pty = pby-ptm; + break; + case 2: + pty = p[0]; ptm = p[1]; pby = pty + ptm; + break; + case 3: + pby = p[0]; pty = p[1]; ptm = p[2]; + break; + } + + if( pty+ptm > 100 ) { + errno = ERANGE; + perror( "KCONFIG_PROBABILITY" ); + exit( 1 ); + } + } + bool has_changed = false; for_all_symbols(i, sym) { - if (sym_has_value(sym)) + if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) continue; switch (sym_get_type(sym)) { case S_BOOLEAN: case S_TRISTATE: + has_changed = true; switch (mode) { case def_yes: sym->def[S_DEF_USER].tri = yes; @@ -1020,11 +1178,21 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) sym->def[S_DEF_USER].tri = mod; break; case def_no: - sym->def[S_DEF_USER].tri = no; + if (sym->flags & SYMBOL_ALLNOCONFIG_Y) + sym->def[S_DEF_USER].tri = yes; + else + sym->def[S_DEF_USER].tri = no; break; case def_random: - cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2; - sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt); + sym->def[S_DEF_USER].tri = no; + cnt = rand() % 100; + if (sym->type == S_TRISTATE) { + if (cnt < pty) + sym->def[S_DEF_USER].tri = yes; + else if (cnt < (pty+ptm)) + sym->def[S_DEF_USER].tri = mod; + } else if (cnt < pby) + sym->def[S_DEF_USER].tri = yes; break; default: continue; @@ -1042,21 +1210,33 @@ void conf_set_all_new_symbols(enum conf_def_mode mode) /* * We have different type of choice blocks. - * If curr.tri equal to mod then we can select several + * If curr.tri equals to mod then we can select several * choice symbols in one block. * In this case we do nothing. - * If curr.tri equal yes then only one symbol can be + * If curr.tri equals yes then only one symbol can be * selected in a choice block and we set it to yes, * and the rest to no. */ + if (mode != def_random) { + for_all_symbols(i, csym) { + if ((sym_is_choice(csym) && !sym_has_value(csym)) || + sym_is_choice_value(csym)) + csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES; + } + } + for_all_symbols(i, csym) { if (sym_has_value(csym) || !sym_is_choice(csym)) continue; sym_calc_value(csym); if (mode == def_random) - randomize_choice_values(csym); - else + has_changed = randomize_choice_values(csym); + else { set_all_choice_values(csym); + has_changed = true; + } } + + return has_changed; } diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index 330e7c0048a..d6626521f9b 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c @@ -7,15 +7,13 @@ #include <stdlib.h> #include <string.h> -#define LKC_DIRECT_LINK #include "lkc.h" #define DEBUG_EXPR 0 struct expr *expr_alloc_symbol(struct symbol *sym) { - struct expr *e = malloc(sizeof(*e)); - memset(e, 0, sizeof(*e)); + struct expr *e = xcalloc(1, sizeof(*e)); e->type = E_SYMBOL; e->left.sym = sym; return e; @@ -23,8 +21,7 @@ struct expr *expr_alloc_symbol(struct symbol *sym) struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) { - struct expr *e = malloc(sizeof(*e)); - memset(e, 0, sizeof(*e)); + struct expr *e = xcalloc(1, sizeof(*e)); e->type = type; e->left.expr = ce; return e; @@ -32,8 +29,7 @@ struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) { - struct expr *e = malloc(sizeof(*e)); - memset(e, 0, sizeof(*e)); + struct expr *e = xcalloc(1, sizeof(*e)); e->type = type; e->left.expr = e1; e->right.expr = e2; @@ -42,8 +38,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) { - struct expr *e = malloc(sizeof(*e)); - memset(e, 0, sizeof(*e)); + struct expr *e = xcalloc(1, sizeof(*e)); e->type = type; e->left.sym = s1; e->right.sym = s2; @@ -64,14 +59,14 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; } -struct expr *expr_copy(struct expr *org) +struct expr *expr_copy(const struct expr *org) { struct expr *e; if (!org) return NULL; - e = malloc(sizeof(*org)); + e = xmalloc(sizeof(*org)); memcpy(e, org, sizeof(*org)); switch (org->type) { case E_SYMBOL: @@ -1013,6 +1008,48 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2) #endif } +static inline struct expr * +expr_get_leftmost_symbol(const struct expr *e) +{ + + if (e == NULL) + return NULL; + + while (e->type != E_SYMBOL) + e = e->left.expr; + + return expr_copy(e); +} + +/* + * Given expression `e1' and `e2', returns the leaf of the longest + * sub-expression of `e1' not containing 'e2. + */ +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) +{ + struct expr *ret; + + switch (e1->type) { + case E_OR: + return expr_alloc_and( + expr_simplify_unmet_dep(e1->left.expr, e2), + expr_simplify_unmet_dep(e1->right.expr, e2)); + case E_AND: { + struct expr *e; + e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); + e = expr_eliminate_dups(e); + ret = (!expr_eq(e, e1)) ? e1 : NULL; + expr_free(e); + break; + } + default: + ret = e1; + break; + } + + return expr_get_leftmost_symbol(ret); +} + void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) { if (!e) { diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 184eb6a0b50..412ea8a2abb 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -10,7 +10,9 @@ extern "C" { #endif +#include <assert.h> #include <stdio.h> +#include "list.h" #ifndef __cplusplus #include <stdbool.h> #endif @@ -20,12 +22,8 @@ struct file { struct file *parent; const char *name; int lineno; - int flags; }; -#define FILE_BUSY 0x0001 -#define FILE_SCANNED 0x0002 - typedef enum tristate { no, mod, yes } tristate; @@ -95,7 +93,7 @@ struct symbol { #define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ #define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ -#define SYMBOL_WRITE 0x0200 /* ? */ +#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */ #define SYMBOL_CHANGED 0x0400 /* ? */ #define SYMBOL_AUTO 0x1000 /* value from environment variable */ #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ @@ -108,6 +106,12 @@ struct symbol { #define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ #define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ +/* choice values need to be set before calculating this symbol value */ +#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000 + +/* Set symbol to y if allnoconfig; used for symbols that hide others */ +#define SYMBOL_ALLNOCONFIG_Y 0x200000 + #define SYMBOL_MAXLENGTH 256 #define SYMBOL_HASHSIZE 9973 @@ -164,6 +168,7 @@ struct menu { struct menu *list; struct symbol *sym; struct property *prompt; + struct expr *visibility; struct expr *dep; unsigned int flags; char *help; @@ -175,7 +180,14 @@ struct menu { #define MENU_CHANGED 0x0001 #define MENU_ROOT 0x0002 -#ifndef SWIG +struct jump_key { + struct list_head entries; + size_t offset; + struct menu *target; + int index; +}; + +#define JUMP_NB 9 extern struct file *file_list; extern struct file *current_file; @@ -191,7 +203,7 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); -struct expr *expr_copy(struct expr *org); +struct expr *expr_copy(const struct expr *org); void expr_free(struct expr *e); int expr_eq(struct expr *e1, struct expr *e2); void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); @@ -206,6 +218,7 @@ struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); void expr_fprint(struct expr *e, FILE *out); struct gstr; /* forward */ @@ -220,7 +233,6 @@ static inline int expr_is_no(struct expr *e) { return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); } -#endif #ifdef __cplusplus } diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c index 455896164d7..d0a35b21f30 100644 --- a/scripts/kconfig/gconf.c +++ b/scripts/kconfig/gconf.c @@ -10,6 +10,7 @@ # include <config.h> #endif +#include <stdlib.h> #include "lkc.h" #include "images.c" @@ -22,7 +23,6 @@ #include <string.h> #include <unistd.h> #include <time.h> -#include <stdlib.h> //#define DEBUG @@ -253,7 +253,7 @@ void init_left_tree(void) gtk_tree_view_set_model(view, model1); gtk_tree_view_set_headers_visible(view, TRUE); - gtk_tree_view_set_rules_hint(view, FALSE); + gtk_tree_view_set_rules_hint(view, TRUE); column = gtk_tree_view_column_new(); gtk_tree_view_append_column(view, column); @@ -285,8 +285,6 @@ void init_left_tree(void) static void renderer_edited(GtkCellRendererText * cell, const gchar * path_string, const gchar * new_text, gpointer user_data); -static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, - gchar * arg1, gpointer user_data); void init_right_tree(void) { @@ -298,7 +296,7 @@ void init_right_tree(void) gtk_tree_view_set_model(view, model2); gtk_tree_view_set_headers_visible(view, TRUE); - gtk_tree_view_set_rules_hint(view, FALSE); + gtk_tree_view_set_rules_hint(view, TRUE); column = gtk_tree_view_column_new(); gtk_tree_view_append_column(view, column); @@ -320,8 +318,6 @@ void init_right_tree(void) "inconsistent", COL_BTNINC, "visible", COL_BTNVIS, "radio", COL_BTNRAD, NULL); - /*g_signal_connect(G_OBJECT(renderer), "toggled", - G_CALLBACK(renderer_toggled), NULL); */ renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), renderer, FALSE); @@ -687,7 +683,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, intro_text); + GTK_BUTTONS_CLOSE, "%s", intro_text); g_signal_connect_swapped(GTK_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(dialog)); @@ -705,7 +701,7 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, about_text); + GTK_BUTTONS_CLOSE, "%s", about_text); g_signal_connect_swapped(GTK_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(dialog)); @@ -724,7 +720,7 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, license_text); + GTK_BUTTONS_CLOSE, "%s", license_text); g_signal_connect_swapped(GTK_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(dialog)); @@ -756,7 +752,6 @@ void on_load_clicked(GtkButton * button, gpointer user_data) void on_single_clicked(GtkButton * button, gpointer user_data) { view_mode = SINGLE_VIEW; - gtk_paned_set_position(GTK_PANED(hpaned), 0); gtk_widget_hide(tree1_w); current = &rootmenu; display_tree_part(); @@ -782,7 +777,6 @@ void on_split_clicked(GtkButton * button, gpointer user_data) void on_full_clicked(GtkButton * button, gpointer user_data) { view_mode = FULL_VIEW; - gtk_paned_set_position(GTK_PANED(hpaned), 0); gtk_widget_hide(tree1_w); if (tree2) gtk_tree_store_clear(tree2); @@ -836,7 +830,7 @@ static void renderer_edited(GtkCellRendererText * cell, static void change_sym_value(struct menu *menu, gint col) { struct symbol *sym = menu->sym; - tristate oldval, newval; + tristate newval; if (!sym) return; @@ -853,7 +847,6 @@ static void change_sym_value(struct menu *menu, gint col) switch (sym_get_type(sym)) { case S_BOOLEAN: case S_TRISTATE: - oldval = sym_get_tristate_value(sym); if (!sym_tristate_within_range(sym, newval)) newval = yes; sym_set_tristate_value(sym, newval); @@ -890,35 +883,6 @@ static void toggle_sym_value(struct menu *menu) display_tree_part(); //fixme: keep exp/coll } -static void renderer_toggled(GtkCellRendererToggle * cell, - gchar * path_string, gpointer user_data) -{ - GtkTreePath *path, *sel_path = NULL; - GtkTreeIter iter, sel_iter; - GtkTreeSelection *sel; - struct menu *menu; - - path = gtk_tree_path_new_from_string(path_string); - if (!gtk_tree_model_get_iter(model2, &iter, path)) - return; - - sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w)); - if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter)) - sel_path = gtk_tree_model_get_path(model2, &sel_iter); - if (!sel_path) - goto out1; - if (gtk_tree_path_compare(path, sel_path)) - goto out2; - - gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); - toggle_sym_value(menu); - - out2: - gtk_tree_path_free(sel_path); - out1: - gtk_tree_path_free(path); -} - static gint column2index(GtkTreeViewColumn * column) { gint i; @@ -1174,6 +1138,7 @@ static gchar **fill_row(struct menu *menu) row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); if (sym_is_choice(sym)) break; + /* fall through */ case S_TRISTATE: val = sym_get_tristate_value(sym); switch (val) { @@ -1312,7 +1277,6 @@ static void update_tree(struct menu *src, GtkTreeIter * dst) gboolean valid; GtkTreeIter *sibling; struct symbol *sym; - struct property *prop; struct menu *menu1, *menu2; if (src == &rootmenu) @@ -1321,7 +1285,6 @@ static void update_tree(struct menu *src, GtkTreeIter * dst) valid = gtk_tree_model_iter_children(model2, child2, dst); for (child1 = src->list; child1; child1 = child1->next) { - prop = child1->prompt; sym = child1->sym; reparse: @@ -1441,9 +1404,15 @@ static void display_tree(struct menu *menu) && (tree == tree2)) continue; /* - if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) + if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) || (view_mode == FULL_VIEW) || (view_mode == SPLIT_VIEW))*/ + + /* Change paned position if the view is not in 'split mode' */ + if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) { + gtk_paned_set_position(GTK_PANED(hpaned), 0); + } + if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) || (view_mode == FULL_VIEW) || (view_mode == SPLIT_VIEW)) { @@ -1502,10 +1471,6 @@ int main(int ac, char *av[]) char *env; gchar *glade_file; -#ifndef LKC_DIRECT_LINK - kconfig_load(); -#endif - bindtextdomain(PACKAGE, LOCALEDIR); bind_textdomain_codeset(PACKAGE, "UTF-8"); textdomain(PACKAGE); diff --git a/scripts/kconfig/kconfig_load.c b/scripts/kconfig/kconfig_load.c deleted file mode 100644 index dbdcaad8232..00000000000 --- a/scripts/kconfig/kconfig_load.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <dlfcn.h> -#include <stdio.h> -#include <stdlib.h> - -#include "lkc.h" - -#define P(name,type,arg) type (*name ## _p) arg -#include "lkc_proto.h" -#undef P - -void kconfig_load(void) -{ - void *handle; - char *error; - - handle = dlopen("./libkconfig.so", RTLD_LAZY); - if (!handle) { - handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY); - if (!handle) { - fprintf(stderr, "%s\n", dlerror()); - exit(1); - } - } - -#define P(name,type,arg) \ -{ \ - name ## _p = dlsym(handle, #name); \ - if ((error = dlerror())) { \ - fprintf(stderr, "%s\n", error); \ - exit(1); \ - } \ -} -#include "lkc_proto.h" -#undef P -} diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c index e9d8e791bf0..2858738b22d 100644 --- a/scripts/kconfig/kxgettext.c +++ b/scripts/kconfig/kxgettext.c @@ -7,7 +7,6 @@ #include <stdlib.h> #include <string.h> -#define LKC_DIRECT_LINK #include "lkc.h" static char *escape(const char* text, char *bf, int len) diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h new file mode 100644 index 00000000000..685d80e1bb0 --- /dev/null +++ b/scripts/kconfig/list.h @@ -0,0 +1,131 @@ +#ifndef LIST_H +#define LIST_H + +/* + * Copied from include/linux/... + */ + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + +struct list_head { + struct list_head *next, *prev; +}; + + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *_new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *_new, struct list_head *head) +{ + __list_add(_new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (struct list_head*)LIST_POISON1; + entry->prev = (struct list_head*)LIST_POISON2; +} +#endif diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 753cdbd7b80..d5daa7af8b4 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -14,18 +14,14 @@ static inline const char *gettext(const char *txt) { return txt; } static inline void textdomain(const char *domainname) {} static inline void bindtextdomain(const char *name, const char *dir) {} +static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } #endif #ifdef __cplusplus extern "C" { #endif -#ifdef LKC_DIRECT_LINK #define P(name,type,arg) extern type name arg -#else -#include "lkc_defs.h" -#define P(name,type,arg) extern type (*name ## _p) arg -#endif #include "lkc_proto.h" #undef P @@ -43,6 +39,12 @@ extern "C" { #ifndef CONFIG_ #define CONFIG_ "CONFIG_" #endif +static inline const char *CONFIG_prefix(void) +{ + return getenv( "CONFIG_" ) ?: CONFIG_; +} +#undef CONFIG_ +#define CONFIG_ CONFIG_prefix() #define TF_COMMAND 0x0001 #define TF_PARAM 0x0002 @@ -59,6 +61,7 @@ enum conf_def_mode { #define T_OPT_MODULES 1 #define T_OPT_DEFCONFIG_LIST 2 #define T_OPT_ENV 3 +#define T_OPT_ALLNOCONFIG_Y 4 struct kconf_id { int name; @@ -67,10 +70,10 @@ struct kconf_id { enum symbol_type stype; }; +extern int zconfdebug; + int zconfparse(void); void zconfdump(FILE *out); - -extern int zconfdebug; void zconf_starthelp(void); FILE *zconf_fopen(const char *name); void zconf_initscan(const char *name); @@ -78,26 +81,28 @@ void zconf_nextfile(const char *name); int zconf_lineno(void); const char *zconf_curname(void); -/* conf.c */ -void xfgets(char *str, int size, FILE *in); - /* confdata.c */ const char *conf_get_configname(void); const char *conf_get_autoconfig_name(void); char *conf_get_default_confname(void); void sym_set_change_count(int count); void sym_add_change_count(int count); -void conf_set_all_new_symbols(enum conf_def_mode mode); +bool conf_set_all_new_symbols(enum conf_def_mode mode); +void set_all_choice_values(struct symbol *csym); + +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; /* confdata.c and expr.c */ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) { - if (fwrite(str, len, count, out) < count) - fprintf(stderr, "\nError in writing or end of file.\n"); -} + assert(len != 0); -/* kconfig_load.c */ -void kconfig_load(void); + if (fwrite(str, len, count, out) != count) + fprintf(stderr, "Error in writing or end of file.\n"); +} /* menu.c */ void _menu_init(void); @@ -107,6 +112,7 @@ void menu_end_menu(void); void menu_add_entry(struct symbol *sym); void menu_end_entry(void); void menu_add_dep(struct expr *dep); +void menu_add_visibility(struct expr *dep); struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); @@ -118,6 +124,8 @@ void menu_set_type(int type); /* util.c */ struct file *file_lookup(const char *name); int file_write_dep(const char *name); +void *xmalloc(size_t size); +void *xcalloc(size_t nmemb, size_t size); struct gstr { size_t len; diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 17342fef38b..ecdb9659b67 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -14,6 +14,7 @@ P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); /* menu.c */ P(rootmenu,struct menu,); +P(menu_is_empty, bool, (struct menu *menu)); P(menu_is_visible, bool, (struct menu *menu)); P(menu_has_prompt, bool, (struct menu *menu)); P(menu_get_prompt,const char *,(struct menu *menu)); @@ -21,8 +22,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu)); P(menu_get_parent_menu,struct menu *,(struct menu *menu)); P(menu_has_help,bool,(struct menu *menu)); P(menu_get_help,const char *,(struct menu *menu)); -P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); -P(get_relations_str, struct gstr, (struct symbol **sym_arr)); +P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head + *head)); +P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head + *head)); P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); /* symbol.c */ @@ -31,6 +34,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); P(sym_lookup,struct symbol *,(const char *name, int flags)); P(sym_find,struct symbol *,(const char *name)); P(sym_expand_string_value,const char *,(const char *in)); +P(sym_escape_string_value, const char *,(const char *in)); P(sym_re_search,struct symbol **,(const char *pattern)); P(sym_type_name,const char *,(enum symbol_type type)); P(sym_calc_value,void,(struct symbol *sym)); diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index 82cc3a85e7f..9d2a4c585ee 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -4,7 +4,9 @@ # What library to link ldflags() { - for ext in so a dylib ; do + pkg-config --libs ncursesw 2>/dev/null && exit + pkg-config --libs ncurses 2>/dev/null && exit + for ext in so a dll.a dylib ; do for lib in ncursesw ncurses curses ; do $cc -print-file-name=lib${lib}.${ext} | grep -q / if [ $? -eq 0 ]; then @@ -19,12 +21,13 @@ ldflags() # Where is ncurses.h? ccflags() { - if [ -f /usr/include/ncurses/ncurses.h ]; then + if [ -f /usr/include/ncursesw/curses.h ]; then + echo '-I/usr/include/ncursesw -DCURSES_LOC="<curses.h>"' + echo ' -DNCURSES_WIDECHAR=1' + elif [ -f /usr/include/ncurses/ncurses.h ]; then echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"' elif [ -f /usr/include/ncurses/curses.h ]; then - echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"' - elif [ -f /usr/include/ncursesw/curses.h ]; then - echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"' + echo '-I/usr/include/ncurses -DCURSES_LOC="<curses.h>"' elif [ -f /usr/include/ncurses.h ]; then echo '-DCURSES_LOC="<ncurses.h>"' else @@ -38,7 +41,7 @@ trap "rm -f $tmp" 0 1 2 3 15 # Check if we can link to ncurses check() { - $cc -xc - -o $tmp 2>/dev/null <<'EOF' + $cc -x c - -o $tmp 2>/dev/null <<'EOF' #include CURSES_LOC main() {} EOF diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c index a2eb80fbc89..8d016faa28d 100644 --- a/scripts/kconfig/lxdialog/checklist.c +++ b/scripts/kconfig/lxdialog/checklist.c @@ -132,16 +132,16 @@ int dialog_checklist(const char *title, const char *prompt, int height, } do_resize: - if (getmaxy(stdscr) < (height + 6)) + if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN)) return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) < (width + 6)) + if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN)) return -ERRDISPLAYTOOSMALL; max_choice = MIN(list_height, item_count()); /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); @@ -168,13 +168,13 @@ do_resize: /* create new window for the list */ list = subwin(dialog, list_height, list_width, y + box_y + 1, - x + box_x + 1); + x + box_x + 1); keypad(list, TRUE); /* draw a box around the list items */ draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, - dlg.menubox_border.atr, dlg.menubox.atr); + dlg.menubox_border.atr, dlg.menubox.atr); /* Find length of longest item in order to center checklist */ check_x = 0; diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h index b5211fce0d9..b4343d38492 100644 --- a/scripts/kconfig/lxdialog/dialog.h +++ b/scripts/kconfig/lxdialog/dialog.h @@ -106,8 +106,14 @@ struct dialog_color { int hl; /* highlight this item */ }; +struct subtitle_list { + struct subtitle_list *next; + const char *text; +}; + struct dialog_info { const char *backtitle; + struct subtitle_list *subtitles; struct dialog_color screen; struct dialog_color shadow; struct dialog_color dialog; @@ -144,6 +150,7 @@ struct dialog_info { */ extern struct dialog_info dlg; extern char dialog_input_result[]; +extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */ /* * Function prototypes @@ -193,8 +200,23 @@ int item_is_tag(char tag); int on_key_esc(WINDOW *win); int on_key_resize(void); +/* minimum (re)size values */ +#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */ +#define CHECKLIST_WIDTH_MIN 6 +#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */ +#define INPUTBOX_WIDTH_MIN 2 +#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */ +#define MENUBOX_WIDTH_MIN 65 +#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */ +#define TEXTBOX_WIDTH_MIN 8 +#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */ +#define YESNO_WIDTH_MIN 4 +#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */ +#define WINDOW_WIDTH_MIN 80 + int init_dialog(const char *backtitle); void set_dialog_backtitle(const char *backtitle); +void set_dialog_subtitles(struct subtitle_list *subtitles); void end_dialog(int x, int y); void attr_clear(WINDOW * win, int height, int width, chtype attr); void dialog_clear(void); @@ -209,12 +231,17 @@ int first_alpha(const char *string, const char *exempt); int dialog_yesno(const char *title, const char *prompt, int height, int width); int dialog_msgbox(const char *title, const char *prompt, int height, int width, int pause); -int dialog_textbox(const char *title, const char *file, int height, int width); + + +typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void + *_data); +int dialog_textbox(const char *title, char *tbuf, int initial_height, + int initial_width, int *keys, int *_vscroll, int *_hscroll, + update_text_fn update_text, void *data); int dialog_menu(const char *title, const char *prompt, const void *selected, int *s_scroll); int dialog_checklist(const char *title, const char *prompt, int height, int width, int list_height); -extern char dialog_input_result[]; int dialog_inputbox(const char *title, const char *prompt, int height, int width, const char *init); diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c index dd8e587c50e..d58de1dc536 100644 --- a/scripts/kconfig/lxdialog/inputbox.c +++ b/scripts/kconfig/lxdialog/inputbox.c @@ -42,10 +42,11 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) * Display a dialog box for inputing a string */ int dialog_inputbox(const char *title, const char *prompt, int height, int width, - const char *init) + const char *init) { int i, x, y, box_y, box_x, box_width; - int input_x = 0, scroll = 0, key = 0, button = -1; + int input_x = 0, key = 0, button = -1; + int show_x, len, pos; char *instr = dialog_input_result; WINDOW *dialog; @@ -55,14 +56,14 @@ int dialog_inputbox(const char *title, const char *prompt, int height, int width strcpy(instr, init); do_resize: - if (getmaxy(stdscr) <= (height - 2)) + if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN)) return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) <= (width - 2)) + if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) return -ERRDISPLAYTOOSMALL; /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); @@ -97,14 +98,17 @@ do_resize: wmove(dialog, box_y, box_x); wattrset(dialog, dlg.inputbox.atr); - input_x = strlen(instr); + len = strlen(instr); + pos = len; - if (input_x >= box_width) { - scroll = input_x - box_width + 1; + if (len >= box_width) { + show_x = len - box_width + 1; input_x = box_width - 1; for (i = 0; i < box_width - 1; i++) - waddch(dialog, instr[scroll + i]); + waddch(dialog, instr[show_x + i]); } else { + show_x = 0; + input_x = len; waddstr(dialog, instr); } @@ -121,45 +125,104 @@ do_resize: case KEY_UP: case KEY_DOWN: break; - case KEY_LEFT: - continue; - case KEY_RIGHT: - continue; case KEY_BACKSPACE: case 127: - if (input_x || scroll) { + if (pos) { wattrset(dialog, dlg.inputbox.atr); - if (!input_x) { - scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); - wmove(dialog, box_y, box_x); - for (i = 0; i < box_width; i++) - waddch(dialog, - instr[scroll + input_x + i] ? - instr[scroll + input_x + i] : ' '); - input_x = strlen(instr) - scroll; + if (input_x == 0) { + show_x--; } else input_x--; - instr[scroll + input_x] = '\0'; - mvwaddch(dialog, box_y, input_x + box_x, ' '); + + if (pos < len) { + for (i = pos - 1; i < len; i++) { + instr[i] = instr[i+1]; + } + } + + pos--; + len--; + instr[len] = '\0'; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } wmove(dialog, box_y, input_x + box_x); wrefresh(dialog); } continue; + case KEY_LEFT: + if (pos > 0) { + if (input_x > 0) { + wmove(dialog, box_y, --input_x + box_x); + } else if (input_x == 0) { + show_x--; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, box_x); + } + pos--; + } + continue; + case KEY_RIGHT: + if (pos < len) { + if (input_x < box_width - 1) { + wmove(dialog, box_y, ++input_x + box_x); + } else if (input_x == box_width - 1) { + show_x++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); + } + wmove(dialog, box_y, input_x + box_x); + } + pos++; + } + continue; default: if (key < 0x100 && isprint(key)) { - if (scroll + input_x < MAX_LEN) { + if (len < MAX_LEN) { wattrset(dialog, dlg.inputbox.atr); - instr[scroll + input_x] = key; - instr[scroll + input_x + 1] = '\0'; + if (pos < len) { + for (i = len; i > pos; i--) + instr[i] = instr[i-1]; + instr[pos] = key; + } else { + instr[len] = key; + } + pos++; + len++; + instr[len] = '\0'; + if (input_x == box_width - 1) { - scroll++; - wmove(dialog, box_y, box_x); - for (i = 0; i < box_width - 1; i++) - waddch(dialog, instr [scroll + i]); + show_x++; } else { - wmove(dialog, box_y, input_x++ + box_x); - waddch(dialog, key); + input_x++; + } + + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) { + if (!instr[show_x + i]) { + waddch(dialog, ' '); + break; + } + waddch(dialog, instr[show_x + i]); } + wmove(dialog, box_y, input_x + box_x); wrefresh(dialog); } else flash(); /* Alarm user about overflow */ diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c index 1d604738fa1..11ae9ad7ac7 100644 --- a/scripts/kconfig/lxdialog/menubox.c +++ b/scripts/kconfig/lxdialog/menubox.c @@ -26,7 +26,7 @@ * * *) A bugfix for the Page-Down problem * - * *) Formerly when I used Page Down and Page Up, the cursor would be set + * *) Formerly when I used Page Down and Page Up, the cursor would be set * to the first position in the menu box. Now lxdialog is a bit * smarter and works more like other menu systems (just have a look at * it). @@ -64,7 +64,7 @@ static int menu_width, item_x; * Print menu item */ static void do_print_item(WINDOW * win, const char *item, int line_y, - int selected, int hotkey) + int selected, int hotkey) { int j; char *menu_item = malloc(menu_width + 1); @@ -154,12 +154,14 @@ static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, */ static void print_buttons(WINDOW * win, int height, int width, int selected) { - int x = width / 2 - 16; + int x = width / 2 - 28; int y = height - 2; print_button(win, gettext("Select"), y, x, selected == 0); print_button(win, gettext(" Exit "), y, x + 12, selected == 1); print_button(win, gettext(" Help "), y, x + 24, selected == 2); + print_button(win, gettext(" Save "), y, x + 36, selected == 3); + print_button(win, gettext(" Load "), y, x + 48, selected == 4); wmove(win, y, x + 1 + 12 * selected); wrefresh(win); @@ -180,7 +182,7 @@ static void do_scroll(WINDOW *win, int *scroll, int n) * Display a menu for choosing among a number of options */ int dialog_menu(const char *title, const char *prompt, - const void *selected, int *s_scroll) + const void *selected, int *s_scroll) { int i, j, x, y, box_x, box_y; int height, width, menu_height; @@ -191,7 +193,7 @@ int dialog_menu(const char *title, const char *prompt, do_resize: height = getmaxy(stdscr); width = getmaxx(stdscr); - if (height < 15 || width < 65) + if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN) return -ERRDISPLAYTOOSMALL; height -= 4; @@ -201,8 +203,8 @@ do_resize: max_choice = MIN(menu_height, item_count()); /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); @@ -301,10 +303,11 @@ do_resize: } } - if (i < max_choice || - key == KEY_UP || key == KEY_DOWN || - key == '-' || key == '+' || - key == KEY_PPAGE || key == KEY_NPAGE) { + if (item_count() != 0 && + (i < max_choice || + key == KEY_UP || key == KEY_DOWN || + key == '-' || key == '+' || + key == KEY_PPAGE || key == KEY_NPAGE)) { /* Remove highligt of current item */ print_item(scroll + choice, choice, FALSE); @@ -372,7 +375,7 @@ do_resize: case TAB: case KEY_RIGHT: button = ((key == KEY_LEFT ? --button : ++button) < 0) - ? 2 : (button > 2 ? 0 : button); + ? 4 : (button > 4 ? 0 : button); print_buttons(dialog, height, width, button); wrefresh(menu); @@ -399,17 +402,17 @@ do_resize: return 2; case 's': case 'y': - return 3; + return 5; case 'n': - return 4; + return 6; case 'm': - return 5; + return 7; case ' ': - return 6; + return 8; case '/': - return 7; + return 9; case 'z': - return 8; + return 10; case '\n': return button; } diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c index c704712d022..1773319b95e 100644 --- a/scripts/kconfig/lxdialog/textbox.c +++ b/scripts/kconfig/lxdialog/textbox.c @@ -22,23 +22,25 @@ #include "dialog.h" static void back_lines(int n); -static void print_page(WINDOW * win, int height, int width); -static void print_line(WINDOW * win, int row, int width); +static void print_page(WINDOW *win, int height, int width, update_text_fn + update_text, void *data); +static void print_line(WINDOW *win, int row, int width); static char *get_line(void); static void print_position(WINDOW * win); static int hscroll; static int begin_reached, end_reached, page_length; -static const char *buf; -static const char *page; +static char *buf; +static char *page; /* * refresh window content */ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, - int cur_y, int cur_x) + int cur_y, int cur_x, update_text_fn update_text, + void *data) { - print_page(box, boxh, boxw); + print_page(box, boxh, boxw, update_text, data); print_position(dialog); wmove(dialog, cur_y, cur_x); /* Restore cursor position */ wrefresh(dialog); @@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, /* * Display text from a file in a dialog box. + * + * keys is a null-terminated array + * update_text() may not add or remove any '\n' or '\0' in tbuf */ -int dialog_textbox(const char *title, const char *tbuf, - int initial_height, int initial_width) +int dialog_textbox(const char *title, char *tbuf, int initial_height, + int initial_width, int *keys, int *_vscroll, int *_hscroll, + update_text_fn update_text, void *data) { int i, x, y, cur_x, cur_y, key = 0; int height, width, boxh, boxw; - int passed_end; WINDOW *dialog, *box; + bool done = false; begin_reached = 1; end_reached = 0; @@ -63,9 +69,18 @@ int dialog_textbox(const char *title, const char *tbuf, buf = tbuf; page = buf; /* page is pointer to start of page to be displayed */ + if (_vscroll && *_vscroll) { + begin_reached = 0; + + for (i = 0; i < *_vscroll; i++) + get_line(); + } + if (_hscroll) + hscroll = *_hscroll; + do_resize: getmaxyx(stdscr, height, width); - if (height < 8 || width < 8) + if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN) return -ERRDISPLAYTOOSMALL; if (initial_height != 0) height = initial_height; @@ -83,8 +98,8 @@ do_resize: width = 0; /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); @@ -120,25 +135,28 @@ do_resize: /* Print first page of text */ attr_clear(box, boxh, boxw, dlg.dialog.atr); - refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text, + data); - while ((key != KEY_ESC) && (key != '\n')) { + while (!done) { key = wgetch(dialog); switch (key) { case 'E': /* Exit */ case 'e': case 'X': case 'x': - delwin(box); - delwin(dialog); - return 0; + case 'q': + case '\n': + done = true; + break; case 'g': /* First page */ case KEY_HOME: if (!begin_reached) { begin_reached = 1; page = buf; refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); + cur_y, cur_x, update_text, + data); } break; case 'G': /* Last page */ @@ -148,78 +166,48 @@ do_resize: /* point to last char in buf */ page = buf + strlen(buf); back_lines(boxh); - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); break; case 'K': /* Previous line */ case 'k': case KEY_UP: - if (!begin_reached) { - back_lines(page_length + 1); - - /* We don't call print_page() here but use - * scrolling to ensure faster screen update. - * However, 'end_reached' and 'page_length' - * should still be updated, and 'page' should - * point to start of next page. This is done - * by calling get_line() in the following - * 'for' loop. */ - scrollok(box, TRUE); - wscrl(box, -1); /* Scroll box region down one line */ - scrollok(box, FALSE); - page_length = 0; - passed_end = 0; - for (i = 0; i < boxh; i++) { - if (!i) { - /* print first line of page */ - print_line(box, 0, boxw); - wnoutrefresh(box); - } else - /* Called to update 'end_reached' and 'page' */ - get_line(); - if (!passed_end) - page_length++; - if (end_reached && !passed_end) - passed_end = 1; - } + if (begin_reached) + break; - print_position(dialog); - wmove(dialog, cur_y, cur_x); /* Restore cursor position */ - wrefresh(dialog); - } + back_lines(page_length + 1); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); break; case 'B': /* Previous page */ case 'b': + case 'u': case KEY_PPAGE: if (begin_reached) break; back_lines(page_length + boxh); - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); break; case 'J': /* Next line */ case 'j': case KEY_DOWN: - if (!end_reached) { - begin_reached = 0; - scrollok(box, TRUE); - scroll(box); /* Scroll box region up one line */ - scrollok(box, FALSE); - print_line(box, boxh - 1, boxw); - wnoutrefresh(box); - print_position(dialog); - wmove(dialog, cur_y, cur_x); /* Restore cursor position */ - wrefresh(dialog); - } + if (end_reached) + break; + + back_lines(page_length - 1); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); break; case KEY_NPAGE: /* Next page */ case ' ': + case 'd': if (end_reached) break; begin_reached = 0; - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); break; case '0': /* Beginning of line */ case 'H': /* Scroll left */ @@ -234,8 +222,8 @@ do_resize: hscroll--; /* Reprint current page to scroll horizontally */ back_lines(page_length); - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); break; case 'L': /* Scroll right */ case 'l': @@ -245,11 +233,12 @@ do_resize: hscroll++; /* Reprint current page to scroll horizontally */ back_lines(page_length); - refresh_text_box(dialog, box, boxh, boxw, - cur_y, cur_x); + refresh_text_box(dialog, box, boxh, boxw, cur_y, + cur_x, update_text, data); break; case KEY_ESC: - key = on_key_esc(dialog); + if (on_key_esc(dialog) == KEY_ESC) + done = true; break; case KEY_RESIZE: back_lines(height); @@ -257,11 +246,31 @@ do_resize: delwin(dialog); on_key_resize(); goto do_resize; + default: + for (i = 0; keys[i]; i++) { + if (key == keys[i]) { + done = true; + break; + } + } } } delwin(box); delwin(dialog); - return key; /* ESC pressed */ + if (_vscroll) { + const char *s; + + s = buf; + *_vscroll = 0; + back_lines(page_length); + while (s < page && (s = strchr(s, '\n'))) { + (*_vscroll)++; + s++; + } + } + if (_hscroll) + *_hscroll = hscroll; + return key; } /* @@ -298,12 +307,23 @@ static void back_lines(int n) } /* - * Print a new page of text. Called by dialog_textbox(). + * Print a new page of text. */ -static void print_page(WINDOW * win, int height, int width) +static void print_page(WINDOW *win, int height, int width, update_text_fn + update_text, void *data) { int i, passed_end = 0; + if (update_text) { + char *end; + + for (i = 0; i < height; i++) + get_line(); + end = page; + back_lines(height); + update_text(buf, page - buf, end - buf, data); + } + page_length = 0; for (i = 0; i < height; i++) { print_line(win, i, width); @@ -316,11 +336,10 @@ static void print_page(WINDOW * win, int height, int width) } /* - * Print a new line of text. Called by dialog_textbox() and print_page(). + * Print a new line of text. */ static void print_line(WINDOW * win, int row, int width) { - int y, x; char *line; line = get_line(); @@ -329,10 +348,10 @@ static void print_line(WINDOW * win, int row, int width) waddch(win, ' '); waddnstr(win, line, MIN(strlen(line), width - 2)); - getyx(win, y, x); /* Clear 'residue' of previous line */ #if OLD_NCURSES { + int x = getcurx(win); int i; for (i = 0; i < width - x; i++) waddch(win, ' '); @@ -355,10 +374,8 @@ static char *get_line(void) end_reached = 0; while (*page != '\n') { if (*page == '\0') { - if (!end_reached) { - end_reached = 1; - break; - } + end_reached = 1; + break; } else if (i < MAX_LEN) line[i++] = *(page++); else { @@ -371,7 +388,7 @@ static char *get_line(void) if (i <= MAX_LEN) line[i] = '\0'; if (!end_reached) - page++; /* move pass '\n' */ + page++; /* move past '\n' */ return line; } diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c index f2375ad7ebc..f7abdeb92af 100644 --- a/scripts/kconfig/lxdialog/util.c +++ b/scripts/kconfig/lxdialog/util.c @@ -23,6 +23,9 @@ #include "dialog.h" +/* Needed in signal handler in mconf.c */ +int saved_x, saved_y; + struct dialog_info dlg; static void set_mono_theme(void) @@ -251,15 +254,56 @@ void attr_clear(WINDOW * win, int height, int width, chtype attr) void dialog_clear(void) { - attr_clear(stdscr, LINES, COLS, dlg.screen.atr); + int lines, columns; + + lines = getmaxy(stdscr); + columns = getmaxx(stdscr); + + attr_clear(stdscr, lines, columns, dlg.screen.atr); /* Display background title if it exists ... - SLH */ if (dlg.backtitle != NULL) { - int i; + int i, len = 0, skip = 0; + struct subtitle_list *pos; wattrset(stdscr, dlg.screen.atr); mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); + + for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { + /* 3 is for the arrow and spaces */ + len += strlen(pos->text) + 3; + } + wmove(stdscr, 1, 1); - for (i = 1; i < COLS - 1; i++) + if (len > columns - 2) { + const char *ellipsis = "[...] "; + waddstr(stdscr, ellipsis); + skip = len - (columns - 2 - strlen(ellipsis)); + } + + for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { + if (skip == 0) + waddch(stdscr, ACS_RARROW); + else + skip--; + + if (skip == 0) + waddch(stdscr, ' '); + else + skip--; + + if (skip < strlen(pos->text)) { + waddstr(stdscr, pos->text + skip); + skip = 0; + } else + skip -= strlen(pos->text); + + if (skip == 0) + waddch(stdscr, ' '); + else + skip--; + } + + for (i = len + 1; i < columns - 1; i++) waddch(stdscr, ACS_HLINE); } wnoutrefresh(stdscr); @@ -273,8 +317,12 @@ int init_dialog(const char *backtitle) int height, width; initscr(); /* Init curses */ + + /* Get current cursor position for signal handler in mconf.c */ + getyx(stdscr, saved_y, saved_x); + getmaxyx(stdscr, height, width); - if (height < 19 || width < 80) { + if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) { endwin(); return -ERRDISPLAYTOOSMALL; } @@ -295,6 +343,11 @@ void set_dialog_backtitle(const char *backtitle) dlg.backtitle = backtitle; } +void set_dialog_subtitles(struct subtitle_list *subtitles) +{ + dlg.subtitles = subtitles; +} + /* * End using dialog functions. */ @@ -323,27 +376,19 @@ void print_title(WINDOW *dialog, const char *title, int width) /* * Print a string of text in a window, automatically wrap around to the * next line if the string is too long to fit on one line. Newline - * characters '\n' are replaced by spaces. We start on a new line + * characters '\n' are propperly processed. We start on a new line * if there is no room for at least 4 nonblanks following a double-space. */ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) { int newl, cur_x, cur_y; - int i, prompt_len, room, wlen; - char tempstr[MAX_LEN + 1], *word, *sp, *sp2; + int prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; strcpy(tempstr, prompt); prompt_len = strlen(tempstr); - /* - * Remove newlines - */ - for (i = 0; i < prompt_len; i++) { - if (tempstr[i] == '\n') - tempstr[i] = ' '; - } - if (prompt_len <= width - x * 2) { /* If prompt is short */ wmove(win, y, (width - prompt_len) / 2); waddstr(win, tempstr); @@ -353,7 +398,10 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) newl = 1; word = tempstr; while (word && *word) { - sp = strchr(word, ' '); + sp = strpbrk(word, "\n "); + if (sp && *sp == '\n') + newline_separator = sp; + if (sp) *sp++ = 0; @@ -365,7 +413,7 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) if (wlen > room || (newl && wlen < 4 && sp && wlen + 1 + strlen(sp) > room - && (!(sp2 = strchr(sp, ' ')) + && (!(sp2 = strpbrk(sp, "\n ")) || wlen + 1 + (sp2 - sp) > room))) { cur_y++; cur_x = x; @@ -373,7 +421,15 @@ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) wmove(win, cur_y, cur_x); waddstr(win, word); getyx(win, cur_y, cur_x); - cur_x++; + + /* Move to the next line if the word separator was a newline */ + if (newline_separator) { + cur_y++; + cur_x = x; + newline_separator = 0; + } else + cur_x++; + if (sp && *sp == ' ') { cur_x++; /* double space */ while (*++sp == ' ') ; @@ -567,7 +623,7 @@ void item_make(const char *fmt, ...) void item_add_str(const char *fmt, ...) { va_list ap; - size_t avail; + size_t avail; avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c index 4e6e8090c20..676fb2f824a 100644 --- a/scripts/kconfig/lxdialog/yesno.c +++ b/scripts/kconfig/lxdialog/yesno.c @@ -45,14 +45,14 @@ int dialog_yesno(const char *title, const char *prompt, int height, int width) WINDOW *dialog; do_resize: - if (getmaxy(stdscr) < (height + 4)) + if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN)) return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) < (width + 4)) + if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN)) return -ERRDISPLAYTOOSMALL; /* center dialog box on screen */ - x = (COLS - width) / 2; - y = (LINES - height) / 2; + x = (getmaxx(stdscr) - width) / 2; + y = (getmaxy(stdscr) - height) / 2; draw_shadow(stdscr, y, x, height, width); diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index d433c7a2474..14cea7463a6 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -15,17 +15,17 @@ #include <stdarg.h> #include <stdlib.h> #include <string.h> +#include <signal.h> #include <unistd.h> #include <locale.h> -#define LKC_DIRECT_LINK #include "lkc.h" #include "lxdialog/dialog.h" static const char mconf_readme[] = N_( "Overview\n" "--------\n" -"This interface let you select features and parameters for the build.\n" +"This interface lets you select features and parameters for the build.\n" "Features can either be built-in, modularized, or ignored. Parameters\n" "must be entered in as decimal or hexadecimal numbers or text.\n" "\n" @@ -39,16 +39,16 @@ static const char mconf_readme[] = N_( "\n" "To change any of these features, highlight it with the cursor\n" "keys and press <Y> to build it in, <M> to make it a module or\n" -"<N> to removed it. You may also press the <Space Bar> to cycle\n" -"through the available options (ie. Y->N->M->Y).\n" +"<N> to remove it. You may also press the <Space Bar> to cycle\n" +"through the available options (i.e. Y->N->M->Y).\n" "\n" "Some additional keyboard hints:\n" "\n" "Menus\n" "----------\n" -"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" -" you wish to change or submenu wish to select and press <Enter>.\n" -" Submenus are designated by \"--->\".\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item you\n" +" wish to change or the submenu you wish to select and press <Enter>.\n" +" Submenus are designated by \"--->\", empty ones by \"----\".\n" "\n" " Shortcut: Press the option's highlighted letter (hotkey).\n" " Pressing a hotkey more than once will sequence\n" @@ -65,7 +65,7 @@ static const char mconf_readme[] = N_( " there is a delayed response which you may find annoying.\n" "\n" " Also, the <TAB> and cursor keys will cycle between <Select>,\n" -" <Exit> and <Help>.\n" +" <Exit>, <Help>, <Save>, and <Load>.\n" "\n" "o To get help with an item, use the cursor keys to highlight <Help>\n" " and press <ENTER>.\n" @@ -105,10 +105,10 @@ static const char mconf_readme[] = N_( "Text Box (Help Window)\n" "--------\n" "o Use the cursor keys to scroll up/down/left/right. The VI editor\n" -" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n" -" who are familiar with less and lynx.\n" +" keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for\n" +" those who are familiar with less and lynx.\n" "\n" -"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n" +"o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n" "\n" "\n" "Alternate Configuration Files\n" @@ -117,23 +117,21 @@ static const char mconf_readme[] = N_( "those who, for various reasons, find it necessary to switch\n" "between different configurations.\n" "\n" -"At the end of the main menu you will find two options. One is\n" -"for saving the current configuration to a file of your choosing.\n" -"The other option is for loading a previously saved alternate\n" -"configuration.\n" +"The <Save> button will let you save the current configuration to\n" +"a file of your choosing. Use the <Load> button to load a previously\n" +"saved alternate configuration.\n" "\n" -"Even if you don't use alternate configuration files, but you\n" -"find during a Menuconfig session that you have completely messed\n" -"up your settings, you may use the \"Load Alternate...\" option to\n" -"restore your previously saved settings from \".config\" without\n" -"restarting Menuconfig.\n" +"Even if you don't use alternate configuration files, but you find\n" +"during a Menuconfig session that you have completely messed up your\n" +"settings, you may use the <Load> button to restore your previously\n" +"saved settings from \".config\" without restarting Menuconfig.\n" "\n" "Other information\n" "-----------------\n" -"If you use Menuconfig in an XTERM window make sure you have your\n" -"$TERM variable set to point to a xterm definition which supports color.\n" -"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n" -"display correctly in a RXVT window because rxvt displays only one\n" +"If you use Menuconfig in an XTERM window, make sure you have your\n" +"$TERM variable set to point to an xterm definition which supports\n" +"color. Otherwise, Menuconfig will look rather bad. Menuconfig will\n" +"not display correctly in an RXVT window because rxvt displays only one\n" "intensity of color, bright.\n" "\n" "Menuconfig will display larger menus on screens or xterms which are\n" @@ -148,8 +146,8 @@ static const char mconf_readme[] = N_( "\n" "Optional personality available\n" "------------------------------\n" -"If you prefer to have all of the options listed in a single menu, rather\n" -"than the default multimenu hierarchy, run the menuconfig with\n" +"If you prefer to have all of the options listed in a single menu,\n" +"rather than the default multimenu hierarchy, run the menuconfig with\n" "MENUCONFIG_MODE environment variable set to single_menu. Example:\n" "\n" "make MENUCONFIG_MODE=single_menu menuconfig\n" @@ -172,11 +170,11 @@ static const char mconf_readme[] = N_( " mono => selects colors suitable for monochrome displays\n" " blackbg => selects a color scheme with black background\n" " classic => theme with blue background. The classic look\n" -" bluetitle => a LCD friendly version of classic. (default)\n" +" bluetitle => an LCD friendly version of classic. (default)\n" "\n"), menu_instructions[] = N_( "Arrow keys navigate the menu. " - "<Enter> selects submenus --->. " + "<Enter> selects submenus ---> (or empty submenus ----). " "Highlighted letters are hotkeys. " "Pressing <Y> includes, <N> excludes, <M> modularizes features. " "Press <Esc><Esc> to exit, <?> for Help, </> for Search. " @@ -236,29 +234,36 @@ search_help[] = N_( "Result:\n" "-----------------------------------------------------------------\n" "Symbol: FOO [=m]\n" + "Type : tristate\n" "Prompt: Foo bus is used to drive the bar HW\n" - "Defined at drivers/pci/Kconfig:47\n" - "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" - "Location:\n" - " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" - " -> PCI support (PCI [=y])\n" - " -> PCI access mode (<choice> [=y])\n" - "Selects: LIBCRC32\n" - "Selected by: BAR\n" + " Location:\n" + " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" + " -> PCI support (PCI [=y])\n" + "(1) -> PCI access mode (<choice> [=y])\n" + " Defined at drivers/pci/Kconfig:47\n" + " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" + " Selects: LIBCRC32\n" + " Selected by: BAR [=n]\n" "-----------------------------------------------------------------\n" + "o The line 'Type:' shows the type of the configuration option for\n" + " this symbol (boolean, tristate, string, ...)\n" "o The line 'Prompt:' shows the text used in the menu structure for\n" " this symbol\n" - "o The 'Defined at' line tell at what file / line number the symbol\n" + "o The 'Defined at' line tells at what file / line number the symbol\n" " is defined\n" - "o The 'Depends on:' line tell what symbols needs to be defined for\n" + "o The 'Depends on:' line tells what symbols need to be defined for\n" " this symbol to be visible in the menu (selectable)\n" - "o The 'Location:' lines tell where in the menu structure this symbol\n" + "o The 'Location:' lines tells where in the menu structure this symbol\n" " is located\n" - " A location followed by a [=y] indicate that this is a selectable\n" - " menu item - and current value is displayed inside brackets.\n" - "o The 'Selects:' line tell what symbol will be automatically\n" + " A location followed by a [=y] indicates that this is a\n" + " selectable menu item - and the current value is displayed inside\n" + " brackets.\n" + " Press the key in the (#) prefix to jump directly to that\n" + " location. You will be returned to the current search results\n" + " after exiting this new menu.\n" + "o The 'Selects:' line tells what symbols will be automatically\n" " selected if this symbol is selected (y or m)\n" - "o The 'Selected by' line tell what symbol has selected this symbol\n" + "o The 'Selected by' line tells what symbol has selected this symbol\n" "\n" "Only relevant lines are shown.\n" "\n\n" @@ -273,12 +278,16 @@ static struct menu *current_menu; static int child_count; static int single_menu_mode; static int show_all_options; +static int save_and_exit; -static void conf(struct menu *menu); +static void conf(struct menu *menu, struct menu *active_menu); static void conf_choice(struct menu *menu); static void conf_string(struct menu *menu); static void conf_load(void); static void conf_save(void); +static int show_textbox_ext(const char *title, char *text, int r, int c, + int *keys, int *vscroll, int *hscroll, + update_text_fn update_text, void *data); static void show_textbox(const char *title, const char *text, int r, int c); static void show_helptext(const char *title, const char *text); static void show_help(struct menu *menu); @@ -290,7 +299,7 @@ static void set_config_filename(const char *config_filename) int size; size = snprintf(menu_backtitle, sizeof(menu_backtitle), - "%s - %s", config_filename, rootmenu.prompt->text); + "%s - %s", config_filename, rootmenu.prompt->text); if (size >= sizeof(menu_backtitle)) menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; set_dialog_backtitle(menu_backtitle); @@ -300,18 +309,103 @@ static void set_config_filename(const char *config_filename) filename[sizeof(filename)-1] = '\0'; } +struct subtitle_part { + struct list_head entries; + const char *text; +}; +static LIST_HEAD(trail); + +static struct subtitle_list *subtitles; +static void set_subtitle(void) +{ + struct subtitle_part *sp; + struct subtitle_list *pos, *tmp; + + for (pos = subtitles; pos != NULL; pos = tmp) { + tmp = pos->next; + free(pos); + } + + subtitles = NULL; + list_for_each_entry(sp, &trail, entries) { + if (sp->text) { + if (pos) { + pos->next = xcalloc(sizeof(*pos), 1); + pos = pos->next; + } else { + subtitles = pos = xcalloc(sizeof(*pos), 1); + } + pos->text = sp->text; + } + } + + set_dialog_subtitles(subtitles); +} + +static void reset_subtitle(void) +{ + struct subtitle_list *pos, *tmp; + + for (pos = subtitles; pos != NULL; pos = tmp) { + tmp = pos->next; + free(pos); + } + subtitles = NULL; + set_dialog_subtitles(subtitles); +} + +struct search_data { + struct list_head *head; + struct menu **targets; + int *keys; +}; + +static void update_text(char *buf, size_t start, size_t end, void *_data) +{ + struct search_data *data = _data; + struct jump_key *pos; + int k = 0; + + list_for_each_entry(pos, data->head, entries) { + if (pos->offset >= start && pos->offset < end) { + char header[4]; + + if (k < JUMP_NB) { + int key = '0' + (pos->index % JUMP_NB) + 1; + + sprintf(header, "(%c)", key); + data->keys[k] = key; + data->targets[k] = pos->target; + k++; + } else { + sprintf(header, " "); + } + + memcpy(buf + pos->offset, header, sizeof(header) - 1); + } + } + data->keys[k] = 0; +} static void search_conf(void) { struct symbol **sym_arr; struct gstr res; + struct gstr title; char *dialog_input; - int dres; + int dres, vscroll = 0, hscroll = 0; + bool again; + struct gstr sttext; + struct subtitle_part stpart; + + title = str_new(); + str_printf( &title, _("Enter (sub)string or regexp to search for " + "(with or without \"%s\")"), CONFIG_); + again: dialog_clear(); dres = dialog_inputbox(_("Search Configuration Parameter"), - _("Enter " CONFIG_ " (sub)string to search for " - "(with or without \"" CONFIG_ "\")"), + str_get(&title), 10, 75, ""); switch (dres) { case 0: @@ -320,6 +414,7 @@ again: show_helptext(_("Search Configuration"), search_help); goto again; default: + str_free(&title); return; } @@ -328,11 +423,43 @@ again: if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) dialog_input += strlen(CONFIG_); + sttext = str_new(); + str_printf(&sttext, "Search (%s)", dialog_input_result); + stpart.text = str_get(&sttext); + list_add_tail(&stpart.entries, &trail); + sym_arr = sym_re_search(dialog_input); - res = get_relations_str(sym_arr); + do { + LIST_HEAD(head); + struct menu *targets[JUMP_NB]; + int keys[JUMP_NB + 1], i; + struct search_data data = { + .head = &head, + .targets = targets, + .keys = keys, + }; + struct jump_key *pos, *tmp; + + res = get_relations_str(sym_arr, &head); + set_subtitle(); + dres = show_textbox_ext(_("Search Results"), (char *) + str_get(&res), 0, 0, keys, &vscroll, + &hscroll, &update_text, (void *) + &data); + again = false; + for (i = 0; i < JUMP_NB && keys[i]; i++) + if (dres == keys[i]) { + conf(targets[i]->parent, targets[i]); + again = true; + } + str_free(&res); + list_for_each_entry_safe(pos, tmp, &head, entries) + free(pos); + } while (again); free(sym_arr); - show_textbox(_("Search Results"), str_get(&res), 0, 0); - str_free(&res); + str_free(&title); + list_del(trail.prev); + str_free(&sttext); } static void build_conf(struct menu *menu) @@ -369,8 +496,9 @@ static void build_conf(struct menu *menu) menu->data ? "-->" : "++>", indent + 1, ' ', prompt); } else - item_make(" %*c%s --->", indent + 1, ' ', prompt); - + item_make(" %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); item_set_tag('m'); item_set_data(menu); if (single_menu_mode && menu->data) @@ -501,7 +629,7 @@ static void build_conf(struct menu *menu) (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : _(" (NEW)")); if (menu->prompt->type == P_MENU) { - item_add_str(" --->"); + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); return; } } @@ -513,40 +641,40 @@ conf_childs: indent -= doint; } -static void conf(struct menu *menu) +static void conf(struct menu *menu, struct menu *active_menu) { struct menu *submenu; const char *prompt = menu_get_prompt(menu); + struct subtitle_part stpart; struct symbol *sym; - struct menu *active_menu = NULL; int res; int s_scroll = 0; + if (menu != &rootmenu) + stpart.text = menu_get_prompt(menu); + else + stpart.text = NULL; + list_add_tail(&stpart.entries, &trail); + while (1) { item_reset(); current_menu = menu; build_conf(menu); if (!child_count) break; - if (menu == &rootmenu) { - item_make("--- "); - item_set_tag(':'); - item_make(_(" Load an Alternate Configuration File")); - item_set_tag('L'); - item_make(_(" Save an Alternate Configuration File")); - item_set_tag('S'); - } + set_subtitle(); dialog_clear(); res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), _(menu_instructions), active_menu, &s_scroll); if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) break; - if (!item_activate_selected()) - continue; - if (!item_tag()) - continue; - + if (item_count() != 0) { + if (!item_activate_selected()) + continue; + if (!item_tag()) + continue; + } submenu = item_data(); active_menu = item_data(); if (submenu) @@ -561,32 +689,36 @@ static void conf(struct menu *menu) if (single_menu_mode) submenu->data = (void *) (long) !submenu->data; else - conf(submenu); + conf(submenu, NULL); break; case 't': if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) conf_choice(submenu); else if (submenu->prompt->type == P_MENU) - conf(submenu); + conf(submenu, NULL); break; case 's': conf_string(submenu); break; - case 'L': - conf_load(); - break; - case 'S': - conf_save(); - break; } break; case 2: if (sym) show_help(submenu); - else + else { + reset_subtitle(); show_helptext(_("README"), _(mconf_readme)); + } break; case 3: + reset_subtitle(); + conf_save(); + break; + case 4: + reset_subtitle(); + conf_load(); + break; + case 5: if (item_is_tag('t')) { if (sym_set_tristate_value(sym, yes)) break; @@ -594,34 +726,45 @@ static void conf(struct menu *menu) show_textbox(NULL, setmod_text, 6, 74); } break; - case 4: + case 6: if (item_is_tag('t')) sym_set_tristate_value(sym, no); break; - case 5: + case 7: if (item_is_tag('t')) sym_set_tristate_value(sym, mod); break; - case 6: + case 8: if (item_is_tag('t')) sym_toggle_tristate_value(sym); else if (item_is_tag('m')) - conf(submenu); + conf(submenu, NULL); break; - case 7: + case 9: search_conf(); break; - case 8: + case 10: show_all_options = !show_all_options; break; } } + + list_del(trail.prev); } -static void show_textbox(const char *title, const char *text, int r, int c) +static int show_textbox_ext(const char *title, char *text, int r, int c, int + *keys, int *vscroll, int *hscroll, update_text_fn + update_text, void *data) { dialog_clear(); - dialog_textbox(title, text, r, c); + return dialog_textbox(title, text, r, c, keys, vscroll, hscroll, + update_text, data); +} + +static void show_textbox(const char *title, const char *text, int r, int c) +{ + show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL, + NULL, NULL); } static void show_helptext(const char *title, const char *text) @@ -629,6 +772,17 @@ static void show_helptext(const char *title, const char *text) show_textbox(title, text, 0, 0); } +static void conf_message_callback(const char *fmt, va_list ap) +{ + char buf[PATH_MAX+1]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + if (save_and_exit) + printf("%s", buf); + else + show_textbox(NULL, buf, 6, 60); +} + static void show_help(struct menu *menu) { struct gstr help = str_new(); @@ -671,7 +825,9 @@ static void conf_choice(struct menu *menu) dialog_clear(); res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), _(radiolist_instructions), - 15, 70, 6); + MENUBOX_HEIGTH_MIN, + MENUBOX_WIDTH_MIN, + CHECKLIST_HEIGTH_MIN); selected = item_activate_selected(); switch (res) { case 0: @@ -793,9 +949,58 @@ static void conf_save(void) } } +static int handle_exit(void) +{ + int res; + + save_and_exit = 1; + reset_subtitle(); + dialog_clear(); + if (conf_get_changed()) + res = dialog_yesno(NULL, + _("Do you wish to save your new configuration?\n" + "(Press <ESC><ESC> to continue kernel configuration.)"), + 6, 60); + else + res = -1; + + end_dialog(saved_x, saved_y); + + switch (res) { + case 0: + if (conf_write(filename)) { + fprintf(stderr, _("\n\n" + "Error while writing of the configuration.\n" + "Your configuration changes were NOT saved." + "\n\n")); + return 1; + } + /* fall through */ + case -1: + printf(_("\n\n" + "*** End of the configuration.\n" + "*** Execute 'make' to start the build or try 'make help'." + "\n\n")); + res = 0; + break; + default: + fprintf(stderr, _("\n\n" + "Your configuration changes were NOT saved." + "\n\n")); + if (res != KEY_ESC) + res = 0; + } + + return res; +} + +static void sig_handler(int signo) +{ + exit(handle_exit()); +} + int main(int ac, char **av) { - int saved_x, saved_y; char *mode; int res; @@ -803,6 +1008,8 @@ int main(int ac, char **av) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + signal(SIGINT, sig_handler); + conf_parse(av[1]); conf_read(NULL); @@ -812,9 +1019,6 @@ int main(int ac, char **av) single_menu_mode = 1; } - initscr(); - - getyx(stdscr, saved_y, saved_x); if (init_dialog(NULL)) { fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); @@ -822,41 +1026,11 @@ int main(int ac, char **av) } set_config_filename(conf_get_configname()); + conf_set_message_callback(conf_message_callback); do { - conf(&rootmenu); - dialog_clear(); - if (conf_get_changed()) - res = dialog_yesno(NULL, - _("Do you wish to save your " - "new configuration?\n" - "<ESC><ESC> to continue."), - 6, 60); - else - res = -1; + conf(&rootmenu, NULL); + res = handle_exit(); } while (res == KEY_ESC); - end_dialog(saved_x, saved_y); - switch (res) { - case 0: - if (conf_write(filename)) { - fprintf(stderr, _("\n\n" - "Error while writing of the configuration.\n" - "Your configuration changes were NOT saved." - "\n\n")); - return 1; - } - case -1: - printf(_("\n\n" - "*** End of the configuration.\n" - "*** Execute 'make' to start the build or try 'make help'." - "\n\n")); - break; - default: - fprintf(stderr, _("\n\n" - "Your configuration changes were NOT saved." - "\n\n")); - } - - return 0; + return res; } - diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 7e83aef42c6..a26cc5d2a9b 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -3,14 +3,14 @@ * Released under the terms of the GNU GPL v2.0. */ +#include <ctype.h> +#include <stdarg.h> #include <stdlib.h> #include <string.h> -#define LKC_DIRECT_LINK #include "lkc.h" -static const char nohelp_text[] = N_( - "There is no help available for this option.\n"); +static const char nohelp_text[] = "There is no help available for this option."; struct menu rootmenu; static struct menu **last_entry_ptr; @@ -48,7 +48,7 @@ void menu_add_entry(struct symbol *sym) { struct menu *menu; - menu = malloc(sizeof(*menu)); + menu = xmalloc(sizeof(*menu)); memset(menu, 0, sizeof(*menu)); menu->sym = sym; menu->parent = current_menu; @@ -119,9 +119,10 @@ void menu_set_type(int type) sym->type = type; return; } - menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", - sym->name ? sym->name : "<choice>", - sym_type_name(sym->type), sym_type_name(type)); + menu_warn(current_entry, + "ignoring type redefinition of '%s' from '%s' to '%s'", + sym->name ? sym->name : "<choice>", + sym_type_name(sym->type), sym_type_name(type)); } struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) @@ -140,6 +141,33 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e } if (current_entry->prompt && current_entry != &rootmenu) prop_warn(prop, "prompt redefined"); + + /* Apply all upper menus' visibilities to actual prompts. */ + if(type == P_PROMPT) { + struct menu *menu = current_entry; + + while ((menu = menu->parent) != NULL) { + struct expr *dup_expr; + + if (!menu->visibility) + continue; + /* + * Do not add a reference to the + * menu's visibility expression but + * use a copy of it. Otherwise the + * expression reduction functions + * will modify expressions that have + * multiple references which can + * cause unwanted side effects. + */ + dup_expr = expr_copy(menu->visibility); + + prop->visible.expr + = expr_alloc_and(prop->visible.expr, + dup_expr); + } + } + current_entry->prompt = prop; } prop->text = prompt; @@ -152,6 +180,12 @@ struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr return menu_add_prop(type, prompt, NULL, dep); } +void menu_add_visibility(struct expr *expr) +{ + current_entry->visibility = expr_alloc_and(current_entry->visibility, + expr); +} + void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) { menu_add_prop(type, NULL, expr, dep); @@ -164,12 +198,15 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) void menu_add_option(int token, char *arg) { - struct property *prop; - switch (token) { case T_OPT_MODULES: - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(current_entry->sym); + if (modules_sym) + zconf_error("symbol '%s' redefines option 'modules'" + " already defined by symbol '%s'", + current_entry->sym->name, + modules_sym->name + ); + modules_sym = current_entry->sym; break; case T_OPT_DEFCONFIG_LIST: if (!sym_defconfig_list) @@ -180,10 +217,13 @@ void menu_add_option(int token, char *arg) case T_OPT_ENV: prop_add_env(arg); break; + case T_OPT_ALLNOCONFIG_Y: + current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y; + break; } } -static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) +static int menu_validate_number(struct symbol *sym, struct symbol *sym2) { return sym2->type == S_INT || sym2->type == S_HEX || (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); @@ -201,6 +241,15 @@ static void sym_check_prop(struct symbol *sym) prop_warn(prop, "default for config symbol '%s'" " must be a single symbol", sym->name); + if (prop->expr->type != E_SYMBOL) + break; + sym2 = prop_get_symbol(prop); + if (sym->type == S_HEX || sym->type == S_INT) { + if (!menu_validate_number(sym, sym2)) + prop_warn(prop, + "'%s': number is invalid", + sym->name); + } break; case P_SELECT: sym2 = prop_get_symbol(prop); @@ -209,8 +258,8 @@ static void sym_check_prop(struct symbol *sym) "config symbol '%s' uses select, but is " "not boolean or tristate", sym->name); else if (sym2->type != S_UNKNOWN && - sym2->type != S_BOOLEAN && - sym2->type != S_TRISTATE) + sym2->type != S_BOOLEAN && + sym2->type != S_TRISTATE) prop_warn(prop, "'%s' has wrong type. 'select' only " "accept arguments of boolean and " @@ -219,9 +268,9 @@ static void sym_check_prop(struct symbol *sym) case P_RANGE: if (sym->type != S_INT && sym->type != S_HEX) prop_warn(prop, "range is only allowed " - "for int or hex symbols"); - if (!menu_range_valid_sym(sym, prop->expr->left.sym) || - !menu_range_valid_sym(sym, prop->expr->right.sym)) + "for int or hex symbols"); + if (!menu_validate_number(sym, prop->expr->left.sym) || + !menu_validate_number(sym, prop->expr->right.sym)) prop_warn(prop, "range is invalid"); break; default: @@ -321,7 +370,7 @@ void menu_finalize(struct menu *parent) last_menu->next = NULL; } - sym->dir_dep.expr = parent->dep; + sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep); } for (menu = parent->list; menu; menu = menu->next) { if (sym && sym_is_choice(sym) && @@ -401,6 +450,22 @@ bool menu_has_prompt(struct menu *menu) return true; } +/* + * Determine if a menu is empty. + * A menu is considered empty if it contains no or only + * invisible entries. + */ +bool menu_is_empty(struct menu *menu) +{ + struct menu *child; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child)) + return(false); + } + return(true); +} + bool menu_is_visible(struct menu *menu) { struct menu *child; @@ -410,6 +475,11 @@ bool menu_is_visible(struct menu *menu) if (!menu->prompt) return false; + if (menu->visibility) { + if (expr_calc_value(menu->visibility) == no) + return no; + } + sym = menu->sym; if (sym) { sym_calc_value(sym); @@ -473,27 +543,53 @@ const char *menu_get_help(struct menu *menu) return ""; } -static void get_prompt_str(struct gstr *r, struct property *prop) +static void get_prompt_str(struct gstr *r, struct property *prop, + struct list_head *head) { int i, j; - struct menu *submenu[8], *menu; + struct menu *submenu[8], *menu, *location = NULL; + struct jump_key *jump; str_printf(r, _("Prompt: %s\n"), _(prop->text)); - str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, - prop->menu->lineno); - if (!expr_is_yes(prop->visible.expr)) { - str_append(r, _(" Depends on: ")); - expr_gstr_print(prop->visible.expr, r); - str_append(r, "\n"); - } menu = prop->menu->parent; - for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) { + bool accessible = menu_is_visible(menu); + submenu[i++] = menu; + if (location == NULL && accessible) + location = menu; + } + if (head && location) { + jump = xmalloc(sizeof(struct jump_key)); + + if (menu_is_visible(prop->menu)) { + /* + * There is not enough room to put the hint at the + * beginning of the "Prompt" line. Put the hint on the + * last "Location" line even when it would belong on + * the former. + */ + jump->target = prop->menu; + } else + jump->target = location; + + if (list_empty(head)) + jump->index = 0; + else + jump->index = list_entry(head->prev, struct jump_key, + entries)->index + 1; + + list_add_tail(&jump->entries, head); + } + if (i > 0) { str_printf(r, _(" Location:\n")); for (j = 4; --i >= 0; j += 2) { menu = submenu[i]; - str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); + if (head && location && menu == location) + jump->offset = strlen(r->s); + str_printf(r, "%*c-> %s", j, ' ', + _(menu_get_prompt(menu))); if (menu->sym) { str_printf(r, " (%s [=%s])", menu->sym->name ? menu->sym->name : _("<choice>"), @@ -504,7 +600,23 @@ static void get_prompt_str(struct gstr *r, struct property *prop) } } -void get_symbol_str(struct gstr *r, struct symbol *sym) +/* + * get property of type P_SYMBOL + */ +static struct property *get_symbol_prop(struct symbol *sym) +{ + struct property *prop = NULL; + + for_all_properties(sym, prop, P_SYMBOL) + break; + return prop; +} + +/* + * head is optional and may be NULL + */ +void get_symbol_str(struct gstr *r, struct symbol *sym, + struct list_head *head) { bool hit; struct property *prop; @@ -523,7 +635,19 @@ void get_symbol_str(struct gstr *r, struct symbol *sym) } } for_all_prompts(sym, prop) - get_prompt_str(r, prop); + get_prompt_str(r, prop, head); + + prop = get_symbol_prop(sym); + if (prop) { + str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, + prop->menu->lineno); + if (!expr_is_yes(prop->visible.expr)) { + str_append(r, _(" Depends on: ")); + expr_gstr_print(prop->visible.expr, r); + str_append(r, "\n"); + } + } + hit = false; for_all_properties(sym, prop, P_SELECT) { if (!hit) { @@ -543,14 +667,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym) str_append(r, "\n\n"); } -struct gstr get_relations_str(struct symbol **sym_arr) +struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head) { struct symbol *sym; struct gstr res = str_new(); int i; for (i = 0; sym_arr && (sym = sym_arr[i]); i++) - get_symbol_str(&res, sym); + get_symbol_str(&res, sym, head); if (!i) str_append(&res, _("No matches found.\n")); return res; @@ -560,16 +684,14 @@ struct gstr get_relations_str(struct symbol **sym_arr) void menu_get_ext_help(struct menu *menu, struct gstr *help) { struct symbol *sym = menu->sym; + const char *help_text = nohelp_text; if (menu_has_help(menu)) { - if (sym->name) { + if (sym->name) str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); - str_append(help, _(menu_get_help(menu))); - str_append(help, "\n"); - } - } else { - str_append(help, nohelp_text); + help_text = menu_get_help(menu); } + str_printf(help, "%s\n", _(help_text)); if (sym) - get_symbol_str(help, sym); + get_symbol_str(help, sym, NULL); } diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh new file mode 100755 index 00000000000..81b0c61bb9e --- /dev/null +++ b/scripts/kconfig/merge_config.sh @@ -0,0 +1,150 @@ +#!/bin/sh +# merge_config.sh - Takes a list of config fragment values, and merges +# them one by one. Provides warnings on overridden values, and specified +# values that did not make it to the resulting .config file (due to missed +# dependencies or config symbol removal). +# +# Portions reused from kconf_check and generate_cfg: +# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check +# http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg +# +# Copyright (c) 2009-2010 Wind River Systems, Inc. +# Copyright 2011 Linaro +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. + +clean_up() { + rm -f $TMP_FILE + exit +} +trap clean_up HUP INT TERM + +usage() { + echo "Usage: $0 [OPTIONS] [CONFIG [...]]" + echo " -h display this help text" + echo " -m only merge the fragments, do not execute the make command" + echo " -n use allnoconfig instead of alldefconfig" + echo " -r list redundant entries when merging fragments" + echo " -O dir to put generated output files" +} + +MAKE=true +ALLTARGET=alldefconfig +WARNREDUN=false +OUTPUT=. + +while true; do + case $1 in + "-n") + ALLTARGET=allnoconfig + shift + continue + ;; + "-m") + MAKE=false + shift + continue + ;; + "-h") + usage + exit + ;; + "-r") + WARNREDUN=true + shift + continue + ;; + "-O") + if [ -d $2 ];then + OUTPUT=$(echo $2 | sed 's/\/*$//') + else + echo "output directory $2 does not exist" 1>&2 + exit 1 + fi + shift 2 + continue + ;; + *) + break + ;; + esac +done + +INITFILE=$1 +shift; + +MERGE_LIST=$* +SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p" +TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX) + +echo "Using $INITFILE as base" +cat $INITFILE > $TMP_FILE + +# Merge files, printing warnings on overrided values +for MERGE_FILE in $MERGE_LIST ; do + echo "Merging $MERGE_FILE" + CFG_LIST=$(sed -n "$SED_CONFIG_EXP" $MERGE_FILE) + + for CFG in $CFG_LIST ; do + grep -q -w $CFG $TMP_FILE + if [ $? -eq 0 ] ; then + PREV_VAL=$(grep -w $CFG $TMP_FILE) + NEW_VAL=$(grep -w $CFG $MERGE_FILE) + if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then + echo Value of $CFG is redefined by fragment $MERGE_FILE: + echo Previous value: $PREV_VAL + echo New value: $NEW_VAL + echo + elif [ "$WARNREDUN" = "true" ]; then + echo Value of $CFG is redundant by fragment $MERGE_FILE: + fi + sed -i "/$CFG[ =]/d" $TMP_FILE + fi + done + cat $MERGE_FILE >> $TMP_FILE +done + +if [ "$MAKE" = "false" ]; then + cp $TMP_FILE $OUTPUT/.config + echo "#" + echo "# merged configuration written to $OUTPUT/.config (needs make)" + echo "#" + clean_up + exit +fi + +# If we have an output dir, setup the O= argument, otherwise leave +# it blank, since O=. will create an unnecessary ./source softlink +OUTPUT_ARG="" +if [ "$OUTPUT" != "." ] ; then + OUTPUT_ARG="O=$OUTPUT" +fi + + +# Use the merged file as the starting point for: +# alldefconfig: Fills in any missing symbols with Kconfig default +# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set +make KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET + + +# Check all specified config values took (might have missed-dependency issues) +for CFG in $(sed -n "$SED_CONFIG_EXP" $TMP_FILE); do + + REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE) + ACTUAL_VAL=$(grep -w -e "$CFG" $OUTPUT/.config) + if [ "x$REQUESTED_VAL" != "x$ACTUAL_VAL" ] ; then + echo "Value requested for $CFG not in final .config" + echo "Requested value: $REQUESTED_VAL" + echo "Actual value: $ACTUAL_VAL" + echo "" + fi +done + +clean_up diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 272a987f23e..984489ef2b4 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -7,217 +7,208 @@ */ #define _GNU_SOURCE #include <string.h> -#define LKC_DIRECT_LINK +#include <stdlib.h> + #include "lkc.h" #include "nconf.h" #include <ctype.h> -static const char nconf_readme[] = N_( -"Overview\n" -"--------\n" -"This interface let you select features and parameters for the build.\n" -"Features can either be built-in, modularized, or ignored. Parameters\n" -"must be entered in as decimal or hexadecimal numbers or text.\n" -"\n" -"Menu items beginning with following braces represent features that\n" -" [ ] can be built in or removed\n" -" < > can be built in, modularized or removed\n" -" { } can be built in or modularized (selected by other feature)\n" -" - - are selected by other feature,\n" -" XXX cannot be selected. Use Symbol Info to find out why,\n" -"while *, M or whitespace inside braces means to build in, build as\n" -"a module or to exclude the feature respectively.\n" +static const char nconf_global_help[] = N_( +"Help windows\n" +"------------\n" +"o Global help: Unless in a data entry window, pressing <F1> will give \n" +" you the global help window, which you are just reading.\n" "\n" -"To change any of these features, highlight it with the cursor\n" -"keys and press <Y> to build it in, <M> to make it a module or\n" -"<N> to removed it. You may also press the <Space Bar> to cycle\n" -"through the available options (ie. Y->N->M->Y).\n" +"o A short version of the global help is available by pressing <F3>.\n" "\n" -"Some additional keyboard hints:\n" -"\n" -"Menus\n" -"----------\n" -"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" -" you wish to change use <Enter> or <Space>. Goto submenu by \n" -" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n" -" Submenus are designated by \"--->\".\n" +"o Local help: To get help related to the current menu entry, use any\n" +" of <?> <h>, or if in a data entry window then press <F1>.\n" "\n" -" Searching: pressing '/' triggers interactive search mode.\n" -" nconfig performs a case insensitive search for the string\n" -" in the menu prompts (no regex support).\n" -" Pressing the up/down keys highlights the previous/next\n" -" matching item. Backspace removes one character from the\n" -" match string. Pressing either '/' again or ESC exits\n" -" search mode. All other keys behave normally.\n" "\n" -" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n" -" unseen options into view.\n" +"Menu entries\n" +"------------\n" +"This interface lets you select features and parameters for the kernel\n" +"build. Kernel features can either be built-in, modularized, or removed.\n" +"Parameters must be entered as text or decimal or hexadecimal numbers.\n" "\n" -"o To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n" +"Menu entries beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized, are selected by another feature\n" +" - - are selected by another feature\n" +" XXX cannot be selected. Symbol Info <F2> tells you why.\n" +"*, M or whitespace inside braces means to build in, build as a module\n" +"or to exclude the feature respectively.\n" "\n" -"o To get help with an item, press <F1>\n" -" Shortcut: Press <h> or <?>.\n" +"To change any of these features, highlight it with the movement keys\n" +"listed below and press <y> to build it in, <m> to make it a module or\n" +"<n> to remove it. You may press the <Space> key to cycle through the\n" +"available options.\n" "\n" +"A trailing \"--->\" designates a submenu, a trailing \"----\" an\n" +"empty submenu.\n" "\n" -"Radiolists (Choice lists)\n" -"-----------\n" -"o Use the cursor keys to select the option you wish to set and press\n" -" <S> or the <SPACE BAR>.\n" +"Menu navigation keys\n" +"----------------------------------------------------------------------\n" +"Linewise up <Up>\n" +"Linewise down <Down>\n" +"Pagewise up <Page Up>\n" +"Pagewise down <Page Down>\n" +"First entry <Home>\n" +"Last entry <End>\n" +"Enter a submenu <Right> <Enter>\n" +"Go back to parent menu <Left> <Esc> <F5>\n" +"Close a help window <Enter> <Esc> <F5>\n" +"Close entry window, apply <Enter>\n" +"Close entry window, forget <Esc> <F5>\n" +"Start incremental, case-insensitive search for STRING in menu entries,\n" +" no regex support, STRING is displayed in upper left corner\n" +" </>STRING\n" +" Remove last character <Backspace>\n" +" Jump to next hit <Down>\n" +" Jump to previous hit <Up>\n" +"Exit menu search mode </> <Esc>\n" +"Search for configuration variables with or without leading CONFIG_\n" +" <F8>RegExpr<Enter>\n" +"Verbose search help <F8><F1>\n" +"----------------------------------------------------------------------\n" "\n" -" Shortcut: Press the first letter of the option you wish to set then\n" -" press <S> or <SPACE BAR>.\n" +"Unless in a data entry window, key <1> may be used instead of <F1>,\n" +"<2> instead of <F2>, etc.\n" "\n" -"o To see available help for the item, press <F1>\n" -" Shortcut: Press <H> or <?>.\n" "\n" +"Radiolist (Choice list)\n" +"-----------------------\n" +"Use the movement keys listed above to select the option you wish to set\n" +"and press <Space>.\n" "\n" -"Data Entry\n" -"-----------\n" -"o Enter the requested information and press <ENTER>\n" -" If you are entering hexadecimal values, it is not necessary to\n" -" add the '0x' prefix to the entry.\n" "\n" -"o For help, press <F1>.\n" +"Data entry\n" +"----------\n" +"Enter the requested information and press <Enter>. Hexadecimal values\n" +"may be entered without the \"0x\" prefix.\n" "\n" "\n" -"Text Box (Help Window)\n" -"--------\n" -"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" -" keys h,j,k,l function here as do <SPACE BAR> for those\n" -" who are familiar with less and lynx.\n" +"Text Box (Help Window)\n" +"----------------------\n" +"Use movement keys as listed in table above.\n" "\n" -"o Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n" +"Press any of <Enter> <Esc> <q> <F5> <F9> to exit.\n" "\n" "\n" -"Alternate Configuration Files\n" +"Alternate configuration files\n" "-----------------------------\n" -"nconfig supports the use of alternate configuration files for\n" -"those who, for various reasons, find it necessary to switch\n" -"between different configurations.\n" +"nconfig supports switching between different configurations.\n" +"Press <F6> to save your current configuration. Press <F7> and enter\n" +"a file name to load a previously saved configuration.\n" "\n" -"At the end of the main menu you will find two options. One is\n" -"for saving the current configuration to a file of your choosing.\n" -"The other option is for loading a previously saved alternate\n" -"configuration.\n" "\n" -"Even if you don't use alternate configuration files, but you\n" -"find during a nconfig session that you have completely messed\n" -"up your settings, you may use the \"Load Alternate...\" option to\n" -"restore your previously saved settings from \".config\" without\n" -"restarting nconfig.\n" +"Terminal configuration\n" +"----------------------\n" +"If you use nconfig in a xterm window, make sure your TERM environment\n" +"variable specifies a terminal configuration which supports at least\n" +"16 colors. Otherwise nconfig will look rather bad.\n" "\n" -"Other information\n" -"-----------------\n" -"If you use nconfig in an XTERM window make sure you have your\n" -"$TERM variable set to point to a xterm definition which supports color.\n" -"Otherwise, nconfig will look rather bad. nconfig will not\n" -"display correctly in a RXVT window because rxvt displays only one\n" -"intensity of color, bright.\n" +"If the \"stty size\" command reports the current terminalsize correctly,\n" +"nconfig will adapt to sizes larger than the traditional 80x25 \"standard\"\n" +"and display longer menus properly.\n" "\n" -"nconfig will display larger menus on screens or xterms which are\n" -"set to display more than the standard 25 row by 80 column geometry.\n" -"In order for this to work, the \"stty size\" command must be able to\n" -"display the screen's current row and column geometry. I STRONGLY\n" -"RECOMMEND that you make sure you do NOT have the shell variables\n" -"LINES and COLUMNS exported into your environment. Some distributions\n" -"export those variables via /etc/profile. Some ncurses programs can\n" -"become confused when those variables (LINES & COLUMNS) don't reflect\n" -"the true screen size.\n" "\n" -"Optional personality available\n" -"------------------------------\n" -"If you prefer to have all of the options listed in a single menu, rather\n" -"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n" -"environment variable set to single_menu. Example:\n" +"Single menu mode\n" +"----------------\n" +"If you prefer to have all of the menu entries listed in a single menu,\n" +"rather than the default multimenu hierarchy, run nconfig with\n" +"NCONFIG_MODE environment variable set to single_menu. Example:\n" "\n" "make NCONFIG_MODE=single_menu nconfig\n" "\n" -"<Enter> will then unroll the appropriate category, or enfold it if it\n" -"is already unrolled.\n" +"<Enter> will then unfold the appropriate category, or fold it if it\n" +"is already unfolded. Folded menu entries will be designated by a\n" +"leading \"++>\" and unfolded entries by a leading \"-->\".\n" "\n" -"Note that this mode can eventually be a little more CPU expensive\n" -"(especially with a larger number of unrolled categories) than the\n" -"default mode.\n" +"Note that this mode can eventually be a little more CPU expensive than\n" +"the default mode, especially with a larger number of unfolded submenus.\n" "\n"), menu_no_f_instructions[] = N_( -" You do not have function keys support. Please follow the\n" -" following instructions:\n" -" Arrow keys navigate the menu.\n" -" <Enter> or <right-arrow> selects submenus --->.\n" -" Capital Letters are hotkeys.\n" -" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n" -" Pressing SpaceBar toggles between the above options.\n" -" Press <Esc> or <left-arrow> to go back one menu,\n" -" <?> or <h> for Help, </> for Search.\n" -" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n" -" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" -" <Esc> always leaves the current window.\n"), +"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" +"\n" +"Use the following keys to navigate the menus:\n" +"Move up or down with <Up> and <Down>.\n" +"Enter a submenu with <Enter> or <Right>.\n" +"Exit a submenu to its parent menu with <Esc> or <Left>.\n" +"Pressing <y> includes, <n> excludes, <m> modularizes features.\n" +"Pressing <Space> cycles through the available options.\n" +"To search for menu entries press </>.\n" +"<Esc> always leaves the current window.\n" +"\n" +"You do not have function keys support.\n" +"Press <1> instead of <F1>, <2> instead of <F2>, etc.\n" +"For verbose global help use key <1>.\n" +"For help related to the current menu entry press <?> or <h>.\n"), menu_instructions[] = N_( -" Arrow keys navigate the menu.\n" -" <Enter> or <right-arrow> selects submenus --->.\n" -" Capital Letters are hotkeys.\n" -" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n" -" Pressing SpaceBar toggles between the above options\n" -" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n" -" <?>, <F1> or <h> for Help, </> for Search.\n" -" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n" -" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" -" <Esc> always leaves the current window\n"), +"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" +"\n" +"Use the following keys to navigate the menus:\n" +"Move up or down with <Up> or <Down>.\n" +"Enter a submenu with <Enter> or <Right>.\n" +"Exit a submenu to its parent menu with <Esc> or <Left>.\n" +"Pressing <y> includes, <n> excludes, <m> modularizes features.\n" +"Pressing <Space> cycles through the available options.\n" +"To search for menu entries press </>.\n" +"<Esc> always leaves the current window.\n" +"\n" +"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n" +"For verbose global help press <F1>.\n" +"For help related to the current menu entry press <?> or <h>.\n"), radiolist_instructions[] = N_( -" Use the arrow keys to navigate this window or\n" -" press the hotkey of the item you wish to select\n" -" followed by the <SPACE BAR>.\n" -" Press <?>, <F1> or <h> for additional information about this option.\n"), +"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n" +"with <Space>.\n" +"For help related to the current entry press <?> or <h>.\n" +"For global help press <F1>.\n"), inputbox_instructions_int[] = N_( "Please enter a decimal value.\n" "Fractions will not be accepted.\n" -"Press <RETURN> to accept, <ESC> to cancel."), +"Press <Enter> to apply, <Esc> to cancel."), inputbox_instructions_hex[] = N_( "Please enter a hexadecimal value.\n" -"Press <RETURN> to accept, <ESC> to cancel."), +"Press <Enter> to apply, <Esc> to cancel."), inputbox_instructions_string[] = N_( "Please enter a string value.\n" -"Press <RETURN> to accept, <ESC> to cancel."), +"Press <Enter> to apply, <Esc> to cancel."), setmod_text[] = N_( -"This feature depends on another which\n" -"has been configured as a module.\n" -"As a result, this feature will be built as a module."), -nohelp_text[] = N_( -"There is no help available for this option.\n"), +"This feature depends on another feature which has been configured as a\n" +"module. As a result, the current feature will be built as a module too."), load_config_text[] = N_( "Enter the name of the configuration file you wish to load.\n" -"Accept the name shown to restore the configuration you\n" -"last retrieved. Leave blank to abort."), +"Accept the name shown to restore the configuration you last\n" +"retrieved. Leave empty to abort."), load_config_help[] = N_( -"\n" "For various reasons, one may wish to keep several different\n" "configurations available on a single machine.\n" "\n" "If you have saved a previous configuration in a file other than the\n" -"default one, entering its name here will allow you to modify that\n" -"configuration.\n" +"default one, entering its name here will allow you to load and modify\n" +"that configuration.\n" "\n" -"If you are uncertain, then you have probably never used alternate\n" -"configuration files. You should therefor leave this blank to abort.\n"), +"Leave empty to abort.\n"), save_config_text[] = N_( "Enter a filename to which this configuration should be saved\n" -"as an alternate. Leave blank to abort."), +"as an alternate. Leave empty to abort."), save_config_help[] = N_( -"\n" -"For various reasons, one may wish to keep different configurations\n" -"available on a single machine.\n" +"For various reasons, one may wish to keep several different\n" +"configurations available on a single machine.\n" "\n" "Entering a file name here will allow you to later retrieve, modify\n" "and use the current configuration as an alternate to whatever\n" "configuration options you have selected at that time.\n" "\n" -"If you are uncertain what all this means then you should probably\n" -"leave this blank.\n"), +"Leave empty to abort.\n"), search_help[] = N_( -"\n" -"Search for symbols and display their relations. Regular expressions\n" -"are allowed.\n" -"Example: search for \"^FOO\"\n" +"Search for symbols (configuration variable names CONFIG_*) and display\n" +"their relations. Regular expressions are supported.\n" +"Example: Search for \"^FOO\".\n" "Result:\n" "-----------------------------------------------------------------\n" "Symbol: FOO [ = m]\n" @@ -225,32 +216,32 @@ search_help[] = N_( "Defined at drivers/pci/Kconfig:47\n" "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" "Location:\n" -" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" +" -> Bus options (PCI, PCMCIA, EISA, ISA)\n" " -> PCI support (PCI [ = y])\n" " -> PCI access mode (<choice> [ = y])\n" "Selects: LIBCRC32\n" "Selected by: BAR\n" "-----------------------------------------------------------------\n" -"o The line 'Prompt:' shows the text used in the menu structure for\n" -" this symbol\n" -"o The 'Defined at' line tell at what file / line number the symbol\n" -" is defined\n" -"o The 'Depends on:' line tell what symbols needs to be defined for\n" -" this symbol to be visible in the menu (selectable)\n" -"o The 'Location:' lines tell where in the menu structure this symbol\n" -" is located\n" -" A location followed by a [ = y] indicate that this is a selectable\n" -" menu item - and current value is displayed inside brackets.\n" -"o The 'Selects:' line tell what symbol will be automatically\n" -" selected if this symbol is selected (y or m)\n" -"o The 'Selected by' line tell what symbol has selected this symbol\n" +"o The line 'Prompt:' shows the text displayed for this symbol in\n" +" the menu hierarchy.\n" +"o The 'Defined at' line tells at what file / line number the symbol is\n" +" defined.\n" +"o The 'Depends on:' line lists symbols that need to be defined for\n" +" this symbol to be visible and selectable in the menu.\n" +"o The 'Location:' lines tell, where in the menu structure this symbol\n" +" is located. A location followed by a [ = y] indicates that this is\n" +" a selectable menu item, and the current value is displayed inside\n" +" brackets.\n" +"o The 'Selects:' line tells, what symbol will be automatically selected\n" +" if this symbol is selected (y or m).\n" +"o The 'Selected by' line tells what symbol has selected this symbol.\n" "\n" "Only relevant lines are shown.\n" "\n\n" "Search examples:\n" -"Examples: USB = > find all symbols containing USB\n" -" ^USB => find all symbols starting with USB\n" -" USB$ => find all symbols ending with USB\n" +"USB => find all symbols containing USB\n" +"^USB => find all symbols starting with USB\n" +"USB$ => find all symbols ending with USB\n" "\n"); struct mitem { @@ -280,6 +271,9 @@ static int global_exit; /* the currently selected button */ const char *current_instructions = menu_instructions; +static char *dialog_input_result; +static int dialog_input_result_len; + static void conf(struct menu *menu); static void conf_choice(struct menu *menu); static void conf_string(struct menu *menu); @@ -318,19 +312,19 @@ struct function_keys function_keys[] = { }, { .key_str = "F2", - .func = "Sym Info", + .func = "SymInfo", .key = F_SYMBOL, .handler = handle_f2, }, { .key_str = "F3", - .func = "Insts", + .func = "Help 2", .key = F_INSTS, .handler = handle_f3, }, { .key_str = "F4", - .func = "Config", + .func = "ShowAll", .key = F_CONF, .handler = handle_f4, }, @@ -354,7 +348,7 @@ struct function_keys function_keys[] = { }, { .key_str = "F8", - .func = "Sym Search", + .func = "SymSearch", .key = F_SEARCH, .handler = handle_f8, }, @@ -371,27 +365,28 @@ static void print_function_line(void) int i; int offset = 1; const int skip = 1; + int lines = getmaxy(stdscr); for (i = 0; i < function_keys_num; i++) { - wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); - mvwprintw(main_window, LINES-3, offset, + (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); + mvwprintw(main_window, lines-3, offset, "%s", function_keys[i].key_str); - wattrset(main_window, attributes[FUNCTION_TEXT]); + (void) wattrset(main_window, attributes[FUNCTION_TEXT]); offset += strlen(function_keys[i].key_str); - mvwprintw(main_window, LINES-3, + mvwprintw(main_window, lines-3, offset, "%s", function_keys[i].func); offset += strlen(function_keys[i].func) + skip; } - wattrset(main_window, attributes[NORMAL]); + (void) wattrset(main_window, attributes[NORMAL]); } /* help */ static void handle_f1(int *key, struct menu *current_item) { show_scroll_win(main_window, - _("README"), _(nconf_readme)); + _("Global help"), _(nconf_global_help)); return; } @@ -406,7 +401,7 @@ static void handle_f2(int *key, struct menu *current_item) static void handle_f3(int *key, struct menu *current_item) { show_scroll_win(main_window, - _("Instructions"), + _("Short help"), _(current_instructions)); return; } @@ -695,15 +690,19 @@ static void search_conf(void) { struct symbol **sym_arr; struct gstr res; - char dialog_input_result[100]; + struct gstr title; char *dialog_input; int dres; + + title = str_new(); + str_printf( &title, _("Enter (sub)string or regexp to search for " + "(with or without \"%s\")"), CONFIG_); + again: dres = dialog_inputbox(main_window, _("Search Configuration Parameter"), - _("Enter " CONFIG_ " (sub)string to search for " - "(with or without \"" CONFIG_ "\")"), - "", dialog_input_result, 99); + str_get(&title), + "", &dialog_input_result, &dialog_input_result_len); switch (dres) { case 0: break; @@ -712,6 +711,7 @@ again: _("Search Configuration"), search_help); goto again; default: + str_free(&title); return; } @@ -721,11 +721,12 @@ again: dialog_input += strlen(CONFIG_); sym_arr = sym_re_search(dialog_input); - res = get_relations_str(sym_arr); + res = get_relations_str(sym_arr, NULL); free(sym_arr); show_scroll_win(main_window, _("Search Results"), str_get(&res)); str_free(&res); + str_free(&title); } @@ -759,9 +760,9 @@ static void build_conf(struct menu *menu) indent + 1, ' ', prompt); } else item_make(menu, 'm', - " %*c%s --->", - indent + 1, - ' ', prompt); + " %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); if (single_menu_mode && menu->data) goto conf_childs; @@ -903,7 +904,7 @@ static void build_conf(struct menu *menu) (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : _(" (NEW)")); if (menu->prompt && menu->prompt->type == P_MENU) { - item_add_str(" --->"); + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); return; } } @@ -953,16 +954,16 @@ static void show_menu(const char *prompt, const char *instructions, current_instructions = instructions; clear(); - wattrset(main_window, attributes[NORMAL]); - print_in_middle(stdscr, 1, 0, COLS, + (void) wattrset(main_window, attributes[NORMAL]); + print_in_middle(stdscr, 1, 0, getmaxx(stdscr), menu_backtitle, attributes[MAIN_HEADING]); - wattrset(main_window, attributes[MAIN_MENU_BOX]); + (void) wattrset(main_window, attributes[MAIN_MENU_BOX]); box(main_window, 0, 0); - wattrset(main_window, attributes[MAIN_MENU_HEADING]); + (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]); mvwprintw(main_window, 0, 3, " %s ", prompt); - wattrset(main_window, attributes[NORMAL]); + (void) wattrset(main_window, attributes[NORMAL]); set_menu_items(curses_menu, curses_menu_items); @@ -1067,7 +1068,6 @@ static void conf(struct menu *menu) struct menu *submenu = 0; const char *prompt = menu_get_prompt(menu); struct symbol *sym; - struct menu *active_menu = NULL; int res; int current_index = 0; int last_top_row = 0; @@ -1152,13 +1152,9 @@ static void conf(struct menu *menu) continue; submenu = (struct menu *) item_data(); - active_menu = (struct menu *)item_data(); if (!submenu || !menu_is_visible(submenu)) continue; - if (submenu) - sym = submenu->sym; - else - sym = NULL; + sym = submenu->sym; switch (res) { case ' ': @@ -1222,20 +1218,13 @@ static void conf_message_callback(const char *fmt, va_list ap) static void show_help(struct menu *menu) { - struct gstr help = str_new(); - - if (menu && menu->sym && menu_has_help(menu)) { - if (menu->sym->name) { - str_printf(&help, "%s%s:\n\n", CONFIG_, menu->sym->name); - str_append(&help, _(menu_get_help(menu))); - str_append(&help, "\n"); - get_symbol_str(&help, menu->sym); - } else { - str_append(&help, _(menu_get_help(menu))); - } - } else { - str_append(&help, nohelp_text); - } + struct gstr help; + + if (!menu) + return; + + help = str_new(); + menu_get_ext_help(menu, &help); show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); str_free(&help); } @@ -1266,9 +1255,13 @@ static void conf_choice(struct menu *menu) if (child->sym == sym_get_choice_value(menu->sym)) item_make(child, ':', "<X> %s", _(menu_get_prompt(child))); - else + else if (child->sym) item_make(child, ':', " %s", _(menu_get_prompt(child))); + else + item_make(child, ':', "*** %s ***", + _(menu_get_prompt(child))); + if (child->sym == active){ last_top_row = top_row(curses_menu); selected_index = i; @@ -1334,7 +1327,7 @@ static void conf_choice(struct menu *menu) break; child = item_data(); - if (!child || !menu_is_visible(child)) + if (!child || !menu_is_visible(child) || !child->sym) continue; switch (res) { case ' ': @@ -1356,7 +1349,6 @@ static void conf_choice(struct menu *menu) static void conf_string(struct menu *menu) { const char *prompt = menu_get_prompt(menu); - char dialog_input_result[256]; while (1) { int res; @@ -1379,8 +1371,8 @@ static void conf_string(struct menu *menu) prompt ? _(prompt) : _("Main Menu"), heading, sym_get_string_value(menu->sym), - dialog_input_result, - sizeof(dialog_input_result)); + &dialog_input_result, + &dialog_input_result_len); switch (res) { case 0: if (sym_set_string_value(menu->sym, @@ -1400,14 +1392,13 @@ static void conf_string(struct menu *menu) static void conf_load(void) { - char dialog_input_result[256]; while (1) { int res; res = dialog_inputbox(main_window, NULL, load_config_text, filename, - dialog_input_result, - sizeof(dialog_input_result)); + &dialog_input_result, + &dialog_input_result_len); switch (res) { case 0: if (!dialog_input_result[0]) @@ -1432,14 +1423,13 @@ static void conf_load(void) static void conf_save(void) { - char dialog_input_result[256]; while (1) { int res; res = dialog_inputbox(main_window, NULL, save_config_text, filename, - dialog_input_result, - sizeof(dialog_input_result)); + &dialog_input_result, + &dialog_input_result_len); switch (res) { case 0: if (!dialog_input_result[0]) @@ -1466,14 +1456,18 @@ static void conf_save(void) void setup_windows(void) { + int lines, columns; + + getmaxyx(stdscr, lines, columns); + if (main_window != NULL) delwin(main_window); /* set up the menu and menu window */ - main_window = newwin(LINES-2, COLS-2, 2, 1); + main_window = newwin(lines-2, columns-2, 2, 1); keypad(main_window, TRUE); - mwin_max_lines = LINES-7; - mwin_max_cols = COLS-6; + mwin_max_lines = lines-7; + mwin_max_cols = columns-6; /* panels order is from bottom to top */ new_panel(main_window); @@ -1481,6 +1475,7 @@ void setup_windows(void) int main(int ac, char **av) { + int lines, columns; char *mode; setlocale(LC_ALL, ""); @@ -1506,7 +1501,8 @@ int main(int ac, char **av) keypad(stdscr, TRUE); curs_set(0); - if (COLS < 75 || LINES < 20) { + getmaxyx(stdscr, lines, columns); + if (columns < 75 || lines < 20) { endwin(); printf("Your terminal should have at " "least 20 lines and 75 columns\n"); @@ -1514,7 +1510,11 @@ int main(int ac, char **av) } notimeout(stdscr, FALSE); +#if NCURSES_REENTRANT + set_escdelay(1); +#else ESCDELAY = 1; +#endif /* set btns menu */ curses_menu = new_menu(curses_menu_items); @@ -1554,4 +1554,3 @@ int main(int ac, char **av) endwin(); return 0; } - diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c index f8137b3a538..8275f0e5510 100644 --- a/scripts/kconfig/nconf.gui.c +++ b/scripts/kconfig/nconf.gui.c @@ -48,7 +48,7 @@ static void set_normal_colors(void) init_pair(INPUT_FIELD, -1, -1); init_pair(FUNCTION_HIGHLIGHT, -1, -1); - init_pair(FUNCTION_TEXT, COLOR_BLUE, -1); + init_pair(FUNCTION_TEXT, COLOR_YELLOW, -1); } /* available attributes: @@ -276,8 +276,8 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...) total_width = max(msg_width, btns_width); /* place dialog in middle of screen */ - y = (LINES-(msg_lines+4))/2; - x = (COLS-(total_width+4))/2; + y = (getmaxy(stdscr)-(msg_lines+4))/2; + x = (getmaxx(stdscr)-(total_width+4))/2; /* create the windows */ @@ -356,7 +356,7 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...) int dialog_inputbox(WINDOW *main_window, const char *title, const char *prompt, - const char *init, char *result, int result_len) + const char *init, char **resultp, int *result_len) { int prompt_lines = 0; int prompt_width = 0; @@ -367,7 +367,13 @@ int dialog_inputbox(WINDOW *main_window, int i, x, y; int res = -1; int cursor_position = strlen(init); + int cursor_form_win; + char *result = *resultp; + if (strlen(init)+1 > *result_len) { + *result_len = strlen(init)+1; + *resultp = result = realloc(result, *result_len); + } /* find the widest line of msg: */ prompt_lines = get_line_no(prompt); @@ -381,10 +387,10 @@ int dialog_inputbox(WINDOW *main_window, prompt_width = max(prompt_width, strlen(title)); /* place dialog in middle of screen */ - y = (LINES-(prompt_lines+4))/2; - x = (COLS-(prompt_width+4))/2; + y = (getmaxy(stdscr)-(prompt_lines+4))/2; + x = (getmaxx(stdscr)-(prompt_width+4))/2; - strncpy(result, init, result_len); + strncpy(result, init, *result_len); /* create the windows */ win = newwin(prompt_lines+6, prompt_width+7, y, x); @@ -405,7 +411,9 @@ int dialog_inputbox(WINDOW *main_window, fill_window(prompt_win, prompt); mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); - mvwprintw(form_win, 0, 0, "%s", result); + cursor_form_win = min(cursor_position, prompt_width-1); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); /* create panels */ panel = new_panel(win); @@ -431,6 +439,8 @@ int dialog_inputbox(WINDOW *main_window, &result[cursor_position], len-cursor_position+1); cursor_position--; + cursor_form_win--; + len--; } break; case KEY_DC: @@ -438,38 +448,63 @@ int dialog_inputbox(WINDOW *main_window, memmove(&result[cursor_position], &result[cursor_position+1], len-cursor_position+1); + len--; } break; case KEY_UP: case KEY_RIGHT: - if (cursor_position < len && - cursor_position < min(result_len, prompt_width)) + if (cursor_position < len) { cursor_position++; + cursor_form_win++; + } break; case KEY_DOWN: case KEY_LEFT: - if (cursor_position > 0) + if (cursor_position > 0) { cursor_position--; + cursor_form_win--; + } + break; + case KEY_HOME: + cursor_position = 0; + cursor_form_win = 0; + break; + case KEY_END: + cursor_position = len; + cursor_form_win = min(cursor_position, prompt_width-1); break; default: - if ((isgraph(res) || isspace(res)) && - len-2 < result_len) { + if ((isgraph(res) || isspace(res))) { + /* one for new char, one for '\0' */ + if (len+2 > *result_len) { + *result_len = len+2; + *resultp = result = realloc(result, + *result_len); + } /* insert the char at the proper position */ memmove(&result[cursor_position+1], &result[cursor_position], - len+1); + len-cursor_position+1); result[cursor_position] = res; cursor_position++; + cursor_form_win++; + len++; } else { - mvprintw(0, 0, "unknow key: %d\n", res); + mvprintw(0, 0, "unknown key: %d\n", res); } break; } + if (cursor_form_win < 0) + cursor_form_win = 0; + else if (cursor_form_win > prompt_width-1) + cursor_form_win = prompt_width-1; + wmove(form_win, 0, 0); wclrtoeol(form_win); mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); - mvwprintw(form_win, 0, 0, "%s", result); - wmove(form_win, 0, cursor_position); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + wmove(form_win, 0, cursor_form_win); touchwin(win); refresh_all_windows(main_window); @@ -510,7 +545,7 @@ void show_scroll_win(WINDOW *main_window, { int res; int total_lines = get_line_no(text); - int x, y; + int x, y, lines, columns; int start_x = 0, start_y = 0; int text_lines = 0, text_cols = 0; int total_cols = 0; @@ -521,6 +556,8 @@ void show_scroll_win(WINDOW *main_window, WINDOW *pad; PANEL *panel; + getmaxyx(stdscr, lines, columns); + /* find the widest line of msg: */ total_lines = get_line_no(text); for (i = 0; i < total_lines; i++) { @@ -534,14 +571,14 @@ void show_scroll_win(WINDOW *main_window, (void) wattrset(pad, attributes[SCROLLWIN_TEXT]); fill_window(pad, text); - win_lines = min(total_lines+4, LINES-2); - win_cols = min(total_cols+2, COLS-2); + win_lines = min(total_lines+4, lines-2); + win_cols = min(total_cols+2, columns-2); text_lines = max(win_lines-4, 0); text_cols = max(win_cols-2, 0); /* place window in middle of screen */ - y = (LINES-win_lines)/2; - x = (COLS-win_cols)/2; + y = (lines-win_lines)/2; + x = (columns-win_cols)/2; win = newwin(win_lines, win_cols, y, x); keypad(win, TRUE); @@ -569,9 +606,11 @@ void show_scroll_win(WINDOW *main_window, switch (res) { case KEY_NPAGE: case ' ': + case 'd': start_y += text_lines-2; break; case KEY_PPAGE: + case 'u': start_y -= text_lines+2; break; case KEY_HOME: @@ -597,10 +636,10 @@ void show_scroll_win(WINDOW *main_window, start_x++; break; } - if (res == 10 || res == 27 || res == 'q' - || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) { + if (res == 10 || res == 27 || res == 'q' || + res == KEY_F(F_HELP) || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) break; - } if (start_y < 0) start_y = 0; if (start_y >= total_lines-text_lines) diff --git a/scripts/kconfig/nconf.h b/scripts/kconfig/nconf.h index 58fbda8fc0d..0d5261705ef 100644 --- a/scripts/kconfig/nconf.h +++ b/scripts/kconfig/nconf.h @@ -89,7 +89,7 @@ void fill_window(WINDOW *win, const char *text); int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...); int dialog_inputbox(WINDOW *main_window, const char *title, const char *prompt, - const char *init, char *result, int result_len); + const char *init, char **resultp, int *result_len); void refresh_all_windows(WINDOW *main_window); void show_scroll_win(WINDOW *main_window, const char *title, diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 06dd2e33581..9d3b04b0769 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -6,6 +6,7 @@ #include <qglobal.h> #if QT_VERSION < 0x040000 +#include <stddef.h> #include <qmainwindow.h> #include <qvbox.h> #include <qvaluelist.h> @@ -68,6 +69,11 @@ static inline QString qgettext(const QString& str) return QString::fromLocal8Bit(gettext(str.latin1())); } +ConfigSettings::ConfigSettings() + : QSettings("kernel.org", "qconf") +{ +} + /** * Reads a list of integer values from the application settings. */ @@ -1478,10 +1484,13 @@ void ConfigMainWindow::loadConfig(void) ConfigView::updateListAll(); } -void ConfigMainWindow::saveConfig(void) +bool ConfigMainWindow::saveConfig(void) { - if (conf_write(NULL)) + if (conf_write(NULL)) { QMessageBox::information(this, "qconf", _("Unable to save configuration!")); + return false; + } + return true; } void ConfigMainWindow::saveConfigAs(void) @@ -1489,8 +1498,7 @@ void ConfigMainWindow::saveConfigAs(void) QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this); if (s.isNull()) return; - if (conf_write(QFile::encodeName(s))) - QMessageBox::information(this, "qconf", _("Unable to save configuration!")); + saveConfig(); } void ConfigMainWindow::searchConfig(void) @@ -1643,7 +1651,11 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e) mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); switch (mb.exec()) { case QMessageBox::Yes: - conf_write(NULL); + if (saveConfig()) + e->accept(); + else + e->ignore(); + break; case QMessageBox::No: e->accept(); break; @@ -1746,10 +1758,6 @@ int main(int ac, char** av) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); -#ifndef LKC_DIRECT_LINK - kconfig_load(); -#endif - progname = av[0]; configApp = new QApplication(ac, av); if (ac > 1 && av[1][0] == '-') { diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index 91677d900db..bde0c6b6f9e 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -32,6 +32,7 @@ class ConfigMainWindow; class ConfigSettings : public QSettings { public: + ConfigSettings(); Q3ValueList<int> readSizes(const QString& key, bool *ok); bool writeSizes(const QString& key, const Q3ValueList<int>& value); }; @@ -311,7 +312,7 @@ public slots: void listFocusChanged(void); void goBack(void); void loadConfig(void); - void saveConfig(void); + bool saveConfig(void); void saveConfigAs(void); void searchConfig(void); void showSingleView(void); diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index fd81fc33d63..9cb8522d8d2 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# Copywrite 2005-2009 - Steven Rostedt +# Copyright 2005-2009 - Steven Rostedt # Licensed under the terms of the GNU GPL License version 2 # # It's simple enough to figure out how this works. @@ -43,6 +43,17 @@ # make oldconfig # use strict; +use Getopt::Long; + +# set the environment variable LOCALMODCONFIG_DEBUG to get +# debug output. +my $debugprint = 0; +$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG})); + +sub dprint { + return if (!$debugprint); + print STDERR @_; +} my $config = ".config"; @@ -89,7 +100,7 @@ my @searchconfigs = ( }, ); -sub find_config { +sub read_config { foreach my $conf (@searchconfigs) { my $file = $conf->{"file"}; @@ -104,18 +115,27 @@ sub find_config { print STDERR "using config: '$file'\n"; - open(CIN, "$exec $file |") || die "Failed to run $exec $file"; - return; + open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file"; + my @x = <$infile>; + close $infile; + return @x; } die "No config file found"; } -find_config; +my @config_file = read_config; + +# Parse options +my $localmodconfig = 0; +my $localyesconfig = 0; + +GetOptions("localmodconfig" => \$localmodconfig, + "localyesconfig" => \$localyesconfig); # Get the build source and top level Kconfig file (passed in) -my $ksource = $ARGV[0]; +my $ksource = ($ARGV[0] ? $ARGV[0] : '.'); my $kconfig = $ARGV[1]; -my $lsmod_file = $ARGV[2]; +my $lsmod_file = $ENV{'LSMOD'}; my @makefiles = `find $ksource -name Makefile 2>/dev/null`; chomp @makefiles; @@ -136,7 +156,6 @@ sub read_kconfig { my $state = "NONE"; my $config; - my @kconfigs; my $cont = 0; my $line; @@ -151,8 +170,8 @@ sub read_kconfig { $source =~ s/\$$env/$ENV{$env}/; } - open(KIN, "$source") || die "Can't open $kconfig"; - while (<KIN>) { + open(my $kinfile, '<', $source) || die "Can't open $kconfig"; + while (<$kinfile>) { chomp; # Make sure that lines ending with \ continue @@ -170,7 +189,13 @@ sub read_kconfig { # collect any Kconfig sources if (/^source\s*"(.*)"/) { - $kconfigs[$#kconfigs+1] = $1; + my $kconfig = $1; + # prevent reading twice. + if (!defined($read_kconfigs{$kconfig})) { + $read_kconfigs{$kconfig} = 1; + read_kconfig($kconfig); + } + next; } # configs found @@ -178,6 +203,7 @@ sub read_kconfig { $state = "NEW"; $config = $2; + # Add depends for 'if' nesting for (my $i = 0; $i < $iflevel; $i++) { if ($i) { $depends{$config} .= " " . $ifdeps[$i]; @@ -193,13 +219,21 @@ sub read_kconfig { $depends{$config} = $1; } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) { $depends{$config} .= " " . $1; + } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) { + my $dep = $3; + if ($dep !~ /^\s*(y|m|n)\s*$/) { + $dep =~ s/.*\sif\s+//; + $depends{$config} .= " " . $dep; + dprint "Added default depends $dep to $config\n"; + } # Get the configs that select this config } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { - if (defined($selects{$1})) { - $selects{$1} .= " " . $config; + my $conf = $1; + if (defined($selects{$conf})) { + $selects{$conf} .= " " . $config; } else { - $selects{$1} = $config; + $selects{$conf} = $config; } # configs without prompts must be selected @@ -227,48 +261,70 @@ sub read_kconfig { $state = "NONE"; } } - close(KIN); - - # read in any configs that were found. - foreach $kconfig (@kconfigs) { - if (!defined($read_kconfigs{$kconfig})) { - $read_kconfigs{$kconfig} = 1; - read_kconfig($kconfig); - } - } + close($kinfile); } if ($kconfig) { read_kconfig($kconfig); } +# Makefiles can use variables to define their dependencies +sub convert_vars { + my ($line, %vars) = @_; + + my $process = ""; + + while ($line =~ s/^(.*?)(\$\((.*?)\))//) { + my $start = $1; + my $variable = $2; + my $var = $3; + + if (defined($vars{$var})) { + $process .= $start . $vars{$var}; + } else { + $process .= $start . $variable; + } + } + + $process .= $line; + + return $process; +} + # Read all Makefiles to map the configs to the objects foreach my $makefile (@makefiles) { - my $cont = 0; + my $line = ""; + my %make_vars; + + open(my $infile, '<', $makefile) || die "Can't open $makefile"; + while (<$infile>) { + # if this line ends with a backslash, continue + chomp; + if (/^(.*)\\$/) { + $line .= $1; + next; + } + + $line .= $_; + $_ = $line; + $line = ""; - open(MIN,$makefile) || die "Can't open $makefile"; - while (<MIN>) { my $objs; - # is this a line after a line with a backslash? - if ($cont && /(\S.*)$/) { - $objs = $1; - } - $cont = 0; + # Convert variables in a line (could define configs) + $_ = convert_vars($_, %make_vars); # collect objects after obj-$(CONFIG_FOO_BAR) if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) { $var = $1; $objs = $2; + + # check if variables are set + } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) { + $make_vars{$1} = $2; } if (defined($objs)) { - # test if the line ends with a backslash - if ($objs =~ m,(.*)\\$,) { - $objs = $1; - $cont = 1; - } - foreach my $obj (split /\s+/,$objs) { $obj =~ s/-/_/g; if ($obj =~ /(.*)\.o$/) { @@ -289,22 +345,24 @@ foreach my $makefile (@makefiles) { } } } - close(MIN); + close($infile); } my %modules; +my $linfile; if (defined($lsmod_file)) { if ( ! -f $lsmod_file) { - die "$lsmod_file not found"; - } - if ( -x $lsmod_file) { - # the file is executable, run it - open(LIN, "$lsmod_file|"); - } else { - # Just read the contents - open(LIN, "$lsmod_file"); + if ( -f $ENV{'objtree'}."/".$lsmod_file) { + $lsmod_file = $ENV{'objtree'}."/".$lsmod_file; + } else { + die "$lsmod_file not found"; + } } + + my $otype = ( -x $lsmod_file) ? '-|' : '<'; + open($linfile, $otype, $lsmod_file); + } else { # see what modules are loaded on this system @@ -321,25 +379,36 @@ if (defined($lsmod_file)) { $lsmod = "lsmod"; } - open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod"; + open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod"; } -while (<LIN>) { +while (<$linfile>) { next if (/^Module/); # Skip the first line. if (/^(\S+)/) { $modules{$1} = 1; } } -close (LIN); +close ($linfile); # add to the configs hash all configs that are needed to enable -# a loaded module. +# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o +# where we know we need bar.o so we add FOO to the list. my %configs; foreach my $module (keys(%modules)) { if (defined($objects{$module})) { my @arr = @{$objects{$module}}; foreach my $conf (@arr) { $configs{$conf} = $module; + dprint "$conf added by direct ($module)\n"; + if ($debugprint) { + my $c=$conf; + $c =~ s/^CONFIG_//; + if (defined($depends{$c})) { + dprint " deps = $depends{$c}\n"; + } else { + dprint " no deps\n"; + } + } } } else { # Most likely, someone has a custom (binary?) module loaded. @@ -347,9 +416,24 @@ foreach my $module (keys(%modules)) { } } +# Read the current config, and see what is enabled. We want to +# ignore configs that we would not enable anyway. + +my %orig_configs; my $valid = "A-Za-z_0-9"; + +foreach my $line (@config_file) { + $_ = $line; + + if (/(CONFIG_[$valid]*)=(m|y)/) { + $orig_configs{$1} = $2; + } +} + my $repeat = 1; +my $depconfig; + # # Note, we do not care about operands (like: &&, ||, !) we want to add any # config that is in the depend list of another config. This script does @@ -358,7 +442,7 @@ my $repeat = 1; # to keep on. If A was on in the original config, B would not have been # and B would not be turned on by this script. # -sub parse_config_dep_select +sub parse_config_depends { my ($p) = @_; @@ -369,10 +453,16 @@ sub parse_config_dep_select $p =~ s/^[^$valid]*[$valid]+//; + # We only need to process if the depend config is a module + if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") { + next; + } + if (!defined($configs{$conf})) { # We must make sure that this config has its # dependencies met. $repeat = 1; # do again + dprint "$conf selected by depend $depconfig\n"; $configs{$conf} = 1; } } else { @@ -381,31 +471,132 @@ sub parse_config_dep_select } } -while ($repeat) { - $repeat = 0; +# Select is treated a bit differently than depends. We call this +# when a config has no prompt and requires another config to be +# selected. We use to just select all configs that selected this +# config, but found that that can balloon into enabling hundreds +# of configs that we do not care about. +# +# The idea is we look at all the configs that select it. If one +# is already in our list of configs to enable, then there's nothing +# else to do. If there isn't, we pick the first config that was +# enabled in the orignal config and use that. +sub parse_config_selects +{ + my ($config, $p) = @_; - foreach my $config (keys %configs) { - $config =~ s/^CONFIG_//; + my $next_config; + + while ($p =~ /[$valid]/) { - if (defined($depends{$config})) { - # This config has dependencies. Make sure they are also included - parse_config_dep_select $depends{$config}; + if ($p =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $p =~ s/^[^$valid]*[$valid]+//; + + # Make sure that this config exists in the current .config file + if (!defined($orig_configs{$conf})) { + dprint "$conf not set for $config select\n"; + next; + } + + # Check if something other than a module selects this config + if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") { + dprint "$conf (non module) selects config, we are good\n"; + # we are good with this + return; + } + if (defined($configs{$conf})) { + dprint "$conf selects $config so we are good\n"; + # A set config selects this config, we are good + return; + } + # Set this config to be selected + if (!defined($next_config)) { + $next_config = $conf; + } + } else { + die "this should never happen"; } + } - if (defined($prompts{$config}) || !defined($selects{$config})) { - next; + # If no possible config selected this, then something happened. + if (!defined($next_config)) { + print STDERR "WARNING: $config is required, but nothing in the\n"; + print STDERR " current config selects it.\n"; + return; + } + + # If we are here, then we found no config that is set and + # selects this config. Repeat. + $repeat = 1; + # Make this config need to be selected + $configs{$next_config} = 1; + dprint "$next_config selected by select $config\n"; +} + +my %process_selects; + +# loop through all configs, select their dependencies. +sub loop_depend { + $repeat = 1; + + while ($repeat) { + $repeat = 0; + + forloop: + foreach my $config (keys %configs) { + + # If this config is not a module, we do not need to process it + if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") { + next forloop; + } + + $config =~ s/^CONFIG_//; + $depconfig = $config; + + if (defined($depends{$config})) { + # This config has dependencies. Make sure they are also included + parse_config_depends $depends{$config}; + } + + # If the config has no prompt, then we need to check if a config + # that is enabled selected it. Or if we need to enable one. + if (!defined($prompts{$config}) && defined($selects{$config})) { + $process_selects{$config} = 1; + } } + } +} + +sub loop_select { + + foreach my $config (keys %process_selects) { + $config =~ s/^CONFIG_//; + + dprint "Process select $config\n"; # config has no prompt and must be selected. - parse_config_dep_select $selects{$config}; + parse_config_selects $config, $selects{$config}; } } +while ($repeat) { + # Get the first set of configs and their dependencies. + loop_depend; + + $repeat = 0; + + # Now we need to see if we have to check selects; + loop_select; +} + my %setconfigs; # Finally, read the .config file and turn off any module enabled that # we could not find a reason to keep enabled. -while(<CIN>) { +foreach my $line (@config_file) { + $_ = $line; if (/CONFIG_IKCONFIG/) { if (/# CONFIG_IKCONFIG is not set/) { @@ -421,7 +612,13 @@ while(<CIN>) { if (/^(CONFIG.*)=(m|y)/) { if (defined($configs{$1})) { - $setconfigs{$1} = $2; + if ($localyesconfig) { + $setconfigs{$1} = 'y'; + print "$1=y\n"; + next; + } else { + $setconfigs{$1} = $2; + } } elsif ($2 eq "m") { print "# $1 is not set\n"; next; @@ -429,7 +626,6 @@ while(<CIN>) { } print; } -close(CIN); # Integrity check, make sure all modules that we want enabled do # indeed have their configs set. diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index af6e9f3de95..7caabdb51c6 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -9,7 +9,6 @@ #include <regex.h> #include <sys/utsname.h> -#define LKC_DIRECT_LINK #include "lkc.h" struct symbol symbol_yes = { @@ -137,7 +136,7 @@ static struct property *sym_get_range_prop(struct symbol *sym) return NULL; } -static int sym_get_range_val(struct symbol *sym, int base) +static long long sym_get_range_val(struct symbol *sym, int base) { sym_calc_value(sym); switch (sym->type) { @@ -150,13 +149,14 @@ static int sym_get_range_val(struct symbol *sym, int base) default: break; } - return strtol(sym->curr.val, NULL, base); + return strtoll(sym->curr.val, NULL, base); } static void sym_validate_range(struct symbol *sym) { struct property *prop; - int base, val, val2; + int base; + long long val, val2; char str[64]; switch (sym->type) { @@ -172,7 +172,7 @@ static void sym_validate_range(struct symbol *sym) prop = sym_get_range_prop(sym); if (!prop) return; - val = strtol(sym->curr.val, NULL, base); + val = strtoll(sym->curr.val, NULL, base); val2 = sym_get_range_val(prop->expr->left.sym, base); if (val >= val2) { val2 = sym_get_range_val(prop->expr->right.sym, base); @@ -180,9 +180,9 @@ static void sym_validate_range(struct symbol *sym) return; } if (sym->type == S_INT) - sprintf(str, "%d", val2); + sprintf(str, "%lld", val2); else - sprintf(str, "0x%x", val2); + sprintf(str, "0x%llx", val2); sym->curr.val = strdup(str); } @@ -263,11 +263,18 @@ static struct symbol *sym_calc_choice(struct symbol *sym) struct symbol *def_sym; struct property *prop; struct expr *e; + int flags; /* first calculate all choice values' visibilities */ + flags = sym->flags; prop = sym_get_choice_prop(sym); - expr_list_for_each_sym(prop->expr, e, def_sym) + expr_list_for_each_sym(prop->expr, e, def_sym) { sym_calc_visibility(def_sym); + if (def_sym->visible != no) + flags &= def_sym->flags; + } + + sym->flags &= flags | ~SYMBOL_DEF_USER; /* is the user choice visible? */ def_sym = sym->def[S_DEF_USER].val; @@ -294,6 +301,14 @@ void sym_calc_value(struct symbol *sym) if (sym->flags & SYMBOL_VALID) return; + + if (sym_is_choice_value(sym) && + sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) { + sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES; + prop = sym_get_choice_prop(sym); + sym_calc_value(prop_get_symbol(prop)); + } + sym->flags |= SYMBOL_VALID; oldval = sym->curr; @@ -351,12 +366,16 @@ void sym_calc_value(struct symbol *sym) } calc_newval: if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { + struct expr *e; + e = expr_simplify_unmet_dep(sym->rev_dep.expr, + sym->dir_dep.expr); fprintf(stderr, "warning: ("); - expr_fprint(sym->rev_dep.expr, stderr); + expr_fprint(e, stderr); fprintf(stderr, ") selects %s which has unmet direct dependencies (", sym->name); expr_fprint(sym->dir_dep.expr, stderr); fprintf(stderr, ")\n"); + expr_free(e); } newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); } @@ -415,6 +434,9 @@ void sym_calc_value(struct symbol *sym) if (sym->flags & SYMBOL_AUTO) sym->flags &= ~SYMBOL_WRITE; + + if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) + set_all_choice_values(sym); } void sym_clear_all_valid(void) @@ -573,7 +595,7 @@ bool sym_string_valid(struct symbol *sym, const char *str) bool sym_string_within_range(struct symbol *sym, const char *str) { struct property *prop; - int val; + long long val; switch (sym->type) { case S_STRING: @@ -584,7 +606,7 @@ bool sym_string_within_range(struct symbol *sym, const char *str) prop = sym_get_range_prop(sym); if (!prop) return true; - val = strtol(str, NULL, 10); + val = strtoll(str, NULL, 10); return val >= sym_get_range_val(prop->expr->left.sym, 10) && val <= sym_get_range_val(prop->expr->right.sym, 10); case S_HEX: @@ -593,7 +615,7 @@ bool sym_string_within_range(struct symbol *sym, const char *str) prop = sym_get_range_prop(sym); if (!prop) return true; - val = strtol(str, NULL, 16); + val = strtoll(str, NULL, 16); return val >= sym_get_range_val(prop->expr->left.sym, 16) && val <= sym_get_range_val(prop->expr->right.sym, 16); case S_BOOLEAN: @@ -646,11 +668,11 @@ bool sym_set_string_value(struct symbol *sym, const char *newval) size = strlen(newval) + 1; if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { size += 2; - sym->def[S_DEF_USER].val = val = malloc(size); + sym->def[S_DEF_USER].val = val = xmalloc(size); *val++ = '0'; *val++ = 'x'; } else if (!oldval || strcmp(oldval, newval)) - sym->def[S_DEF_USER].val = val = malloc(size); + sym->def[S_DEF_USER].val = val = xmalloc(size); else return true; @@ -686,7 +708,7 @@ const char *sym_get_string_default(struct symbol *sym) switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: - /* The visibility imay limit the value from yes => mod */ + /* The visibility may limit the value from yes => mod */ val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); break; default: @@ -747,7 +769,8 @@ const char *sym_get_string_value(struct symbol *sym) case no: return "n"; case mod: - return "m"; + sym_calc_value(modules_sym); + return (modules_sym->curr.tri == no) ? "n" : "m"; case yes: return "y"; } @@ -801,7 +824,7 @@ struct symbol *sym_lookup(const char *name, int flags) hash = 0; } - symbol = malloc(sizeof(*symbol)); + symbol = xmalloc(sizeof(*symbol)); memset(symbol, 0, sizeof(*symbol)); symbol->name = new_name; symbol->type = S_UNKNOWN; @@ -852,7 +875,7 @@ const char *sym_expand_string_value(const char *in) size_t reslen; reslen = strlen(in) + 1; - res = malloc(reslen); + res = xmalloc(reslen); res[0] = '\0'; while ((src = strchr(in, '$'))) { @@ -889,38 +912,132 @@ const char *sym_expand_string_value(const char *in) return res; } +const char *sym_escape_string_value(const char *in) +{ + const char *p; + size_t reslen; + char *res; + size_t l; + + reslen = strlen(in) + strlen("\"\"") + 1; + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + p += l; + + if (p[0] == '\0') + break; + + reslen++; + p++; + } + + res = xmalloc(reslen); + res[0] = '\0'; + + strcat(res, "\""); + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + strncat(res, p, l); + p += l; + + if (p[0] == '\0') + break; + + strcat(res, "\\"); + strncat(res, p++, 1); + } + + strcat(res, "\""); + return res; +} + +struct sym_match { + struct symbol *sym; + off_t so, eo; +}; + +/* Compare matched symbols as thus: + * - first, symbols that match exactly + * - then, alphabetical sort + */ +static int sym_rel_comp(const void *sym1, const void *sym2) +{ + const struct sym_match *s1 = sym1; + const struct sym_match *s2 = sym2; + int exact1, exact2; + + /* Exact match: + * - if matched length on symbol s1 is the length of that symbol, + * then this symbol should come first; + * - if matched length on symbol s2 is the length of that symbol, + * then this symbol should come first. + * Note: since the search can be a regexp, both symbols may match + * exactly; if this is the case, we can't decide which comes first, + * and we fallback to sorting alphabetically. + */ + exact1 = (s1->eo - s1->so) == strlen(s1->sym->name); + exact2 = (s2->eo - s2->so) == strlen(s2->sym->name); + if (exact1 && !exact2) + return -1; + if (!exact1 && exact2) + return 1; + + /* As a fallback, sort symbols alphabetically */ + return strcmp(s1->sym->name, s2->sym->name); +} + struct symbol **sym_re_search(const char *pattern) { struct symbol *sym, **sym_arr = NULL; + struct sym_match *sym_match_arr = NULL; int i, cnt, size; regex_t re; + regmatch_t match[1]; cnt = size = 0; /* Skip if empty */ if (strlen(pattern) == 0) return NULL; - if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) + if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE)) return NULL; for_all_symbols(i, sym) { if (sym->flags & SYMBOL_CONST || !sym->name) continue; - if (regexec(&re, sym->name, 0, NULL, 0)) + if (regexec(&re, sym->name, 1, match, 0)) continue; - if (cnt + 1 >= size) { - void *tmp = sym_arr; + if (cnt >= size) { + void *tmp; size += 16; - sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); - if (!sym_arr) { - free(tmp); - return NULL; - } + tmp = realloc(sym_match_arr, size * sizeof(struct sym_match)); + if (!tmp) + goto sym_re_search_free; + sym_match_arr = tmp; } sym_calc_value(sym); - sym_arr[cnt++] = sym; + /* As regexec returned 0, we know we have a match, so + * we can use match[0].rm_[se]o without further checks + */ + sym_match_arr[cnt].so = match[0].rm_so; + sym_match_arr[cnt].eo = match[0].rm_eo; + sym_match_arr[cnt++].sym = sym; } - if (sym_arr) + if (sym_match_arr) { + qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp); + sym_arr = malloc((cnt+1) * sizeof(struct symbol)); + if (!sym_arr) + goto sym_re_search_free; + for (i = 0; i < cnt; i++) + sym_arr[i] = sym_match_arr[i].sym; sym_arr[cnt] = NULL; + } +sym_re_search_free: + /* sym_match_arr can be NULL if no match, but free(NULL) is OK */ + free(sym_match_arr); regfree(&re); return sym_arr; @@ -930,7 +1047,7 @@ struct symbol **sym_re_search(const char *pattern) * When we check for recursive dependencies we use a stack to save * current state so we can print out relevant info to user. * The entries are located on the call stack so no need to free memory. - * Note inser() remove() must always match to properly clear the stack. + * Note insert() remove() must always match to properly clear the stack. */ static struct dep_stack { struct dep_stack *prev, *next; @@ -1174,7 +1291,7 @@ struct property *prop_alloc(enum prop_type type, struct symbol *sym) struct property *prop; struct property **propp; - prop = malloc(sizeof(*prop)); + prop = xmalloc(sizeof(*prop)); memset(prop, 0, sizeof(*prop)); prop->type = type; prop->sym = sym; diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c index 6330cc871a4..94f9c83e324 100644 --- a/scripts/kconfig/util.c +++ b/scripts/kconfig/util.c @@ -5,6 +5,8 @@ * Released under the terms of the GNU GPL v2.0. */ +#include <stdarg.h> +#include <stdlib.h> #include <string.h> #include "lkc.h" @@ -21,7 +23,7 @@ struct file *file_lookup(const char *name) } } - file = malloc(sizeof(*file)); + file = xmalloc(sizeof(*file)); memset(file, 0, sizeof(*file)); file->name = file_name; file->next = file_list; @@ -79,7 +81,7 @@ int file_write_dep(const char *name) struct gstr str_new(void) { struct gstr gs; - gs.s = malloc(sizeof(char) * 64); + gs.s = xmalloc(sizeof(char) * 64); gs.len = 64; gs.max_width = 0; strcpy(gs.s, "\0"); @@ -136,3 +138,20 @@ const char *str_get(struct gstr *gs) return gs->s; } +void *xmalloc(size_t size) +{ + void *p = malloc(size); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} + +void *xcalloc(size_t nmemb, size_t size) +{ + void *p = calloc(nmemb, size); + if (p) + return p; + fprintf(stderr, "Out of memory.\n"); + exit(1); +} diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf index d8bc7424962..b6ac02d604f 100644 --- a/scripts/kconfig/zconf.gperf +++ b/scripts/kconfig/zconf.gperf @@ -9,7 +9,7 @@ struct kconf_id; -static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); %% mainmenu, T_MAINMENU, TF_COMMAND @@ -38,9 +38,11 @@ hex, T_TYPE, TF_COMMAND, S_HEX string, T_TYPE, TF_COMMAND, S_STRING select, T_SELECT, TF_COMMAND range, T_RANGE, TF_COMMAND +visible, T_VISIBLE, TF_COMMAND option, T_OPTION, TF_COMMAND on, T_ON, TF_PARAM modules, T_OPT_MODULES, TF_OPTION defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION env, T_OPT_ENV, TF_OPTION +allnoconfig_y, T_OPT_ALLNOCONFIG_Y,TF_OPTION %% diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped index c1748faf463..c77a8eff1ef 100644 --- a/scripts/kconfig/zconf.hash.c_shipped +++ b/scripts/kconfig/zconf.hash.c_shipped @@ -1,6 +1,5 @@ -/* ANSI-C code produced by gperf version 3.0.3 */ -/* Command-line: gperf */ -/* Computed positions: -k'1,3' */ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ @@ -29,10 +28,11 @@ #error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." #endif +#line 10 "scripts/kconfig/zconf.gperf" struct kconf_id; -static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); -/* maximum key range = 47, duplicates = 0 */ +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); +/* maximum key range = 71, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -44,34 +44,34 @@ inline static unsigned int kconf_id_hash (register const char *str, register unsigned int len) { - static unsigned char asso_values[] = + static const unsigned char asso_values[] = { - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 11, 5, - 0, 0, 5, 49, 5, 20, 49, 49, 5, 20, - 5, 0, 30, 49, 0, 15, 0, 10, 0, 49, - 25, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, - 49, 49, 49, 49, 49, 49 + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 5, 25, 25, + 0, 0, 0, 5, 0, 0, 73, 73, 5, 0, + 10, 5, 45, 73, 20, 20, 0, 15, 15, 73, + 20, 5, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73 }; register int hval = len; @@ -85,137 +85,186 @@ kconf_id_hash (register const char *str, register unsigned int len) hval += asso_values[(unsigned char)str[0]]; break; } - return hval; + return hval + asso_values[(unsigned char)str[len - 1]]; } struct kconf_id_strings_t { - char kconf_id_strings_str2[sizeof("on")]; - char kconf_id_strings_str3[sizeof("env")]; + char kconf_id_strings_str2[sizeof("if")]; + char kconf_id_strings_str3[sizeof("int")]; char kconf_id_strings_str5[sizeof("endif")]; - char kconf_id_strings_str6[sizeof("option")]; - char kconf_id_strings_str7[sizeof("endmenu")]; - char kconf_id_strings_str8[sizeof("optional")]; + char kconf_id_strings_str7[sizeof("default")]; + char kconf_id_strings_str8[sizeof("tristate")]; char kconf_id_strings_str9[sizeof("endchoice")]; - char kconf_id_strings_str10[sizeof("range")]; - char kconf_id_strings_str11[sizeof("choice")]; - char kconf_id_strings_str12[sizeof("default")]; + char kconf_id_strings_str12[sizeof("def_tristate")]; char kconf_id_strings_str13[sizeof("def_bool")]; - char kconf_id_strings_str14[sizeof("help")]; - char kconf_id_strings_str15[sizeof("bool")]; - char kconf_id_strings_str16[sizeof("config")]; - char kconf_id_strings_str17[sizeof("def_tristate")]; - char kconf_id_strings_str18[sizeof("boolean")]; - char kconf_id_strings_str19[sizeof("defconfig_list")]; - char kconf_id_strings_str21[sizeof("string")]; - char kconf_id_strings_str22[sizeof("if")]; - char kconf_id_strings_str23[sizeof("int")]; - char kconf_id_strings_str26[sizeof("select")]; + char kconf_id_strings_str14[sizeof("defconfig_list")]; + char kconf_id_strings_str17[sizeof("on")]; + char kconf_id_strings_str18[sizeof("optional")]; + char kconf_id_strings_str21[sizeof("option")]; + char kconf_id_strings_str22[sizeof("endmenu")]; + char kconf_id_strings_str23[sizeof("mainmenu")]; + char kconf_id_strings_str25[sizeof("menuconfig")]; char kconf_id_strings_str27[sizeof("modules")]; - char kconf_id_strings_str28[sizeof("tristate")]; + char kconf_id_strings_str28[sizeof("allnoconfig_y")]; char kconf_id_strings_str29[sizeof("menu")]; - char kconf_id_strings_str31[sizeof("source")]; + char kconf_id_strings_str31[sizeof("select")]; char kconf_id_strings_str32[sizeof("comment")]; - char kconf_id_strings_str33[sizeof("hex")]; - char kconf_id_strings_str35[sizeof("menuconfig")]; - char kconf_id_strings_str36[sizeof("prompt")]; - char kconf_id_strings_str37[sizeof("depends")]; - char kconf_id_strings_str48[sizeof("mainmenu")]; + char kconf_id_strings_str33[sizeof("env")]; + char kconf_id_strings_str35[sizeof("range")]; + char kconf_id_strings_str36[sizeof("choice")]; + char kconf_id_strings_str39[sizeof("bool")]; + char kconf_id_strings_str41[sizeof("source")]; + char kconf_id_strings_str42[sizeof("visible")]; + char kconf_id_strings_str43[sizeof("hex")]; + char kconf_id_strings_str46[sizeof("config")]; + char kconf_id_strings_str47[sizeof("boolean")]; + char kconf_id_strings_str51[sizeof("string")]; + char kconf_id_strings_str54[sizeof("help")]; + char kconf_id_strings_str56[sizeof("prompt")]; + char kconf_id_strings_str72[sizeof("depends")]; }; -static struct kconf_id_strings_t kconf_id_strings_contents = +static const struct kconf_id_strings_t kconf_id_strings_contents = { - "on", - "env", + "if", + "int", "endif", + "default", + "tristate", + "endchoice", + "def_tristate", + "def_bool", + "defconfig_list", + "on", + "optional", "option", "endmenu", - "optional", - "endchoice", + "mainmenu", + "menuconfig", + "modules", + "allnoconfig_y", + "menu", + "select", + "comment", + "env", "range", "choice", - "default", - "def_bool", - "help", "bool", + "source", + "visible", + "hex", "config", - "def_tristate", "boolean", - "defconfig_list", "string", - "if", - "int", - "select", - "modules", - "tristate", - "menu", - "source", - "comment", - "hex", - "menuconfig", + "help", "prompt", - "depends", - "mainmenu" + "depends" }; #define kconf_id_strings ((const char *) &kconf_id_strings_contents) #ifdef __GNUC__ __inline -#ifdef __GNUC_STDC_INLINE__ +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ __attribute__ ((__gnu_inline__)) #endif #endif -struct kconf_id * +const struct kconf_id * kconf_id_lookup (register const char *str, register unsigned int len) { enum { - TOTAL_KEYWORDS = 31, + TOTAL_KEYWORDS = 33, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 14, MIN_HASH_VALUE = 2, - MAX_HASH_VALUE = 48 + MAX_HASH_VALUE = 72 }; - static struct kconf_id wordlist[] = + static const struct kconf_id wordlist[] = { {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_OPT_ENV, TF_OPTION}, +#line 25 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM}, +#line 36 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT}, {-1}, +#line 26 "scripts/kconfig/zconf.gperf" {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_OPTIONAL, TF_COMMAND}, + {-1}, +#line 29 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, +#line 31 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE}, +#line 20 "scripts/kconfig/zconf.gperf" {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_CHOICE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, + {-1}, {-1}, +#line 32 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE}, +#line 35 "scripts/kconfig/zconf.gperf" {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_HELP, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str15, T_TYPE, TF_COMMAND, S_BOOLEAN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_CONFIG, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_TYPE, TF_COMMAND, S_BOOLEAN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_OPT_DEFCONFIG_LIST,TF_OPTION}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT}, +#line 45 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION}, {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND}, +#line 43 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_ON, TF_PARAM}, +#line 28 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND}, + {-1}, {-1}, +#line 42 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_OPTION, TF_COMMAND}, +#line 17 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND}, +#line 15 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_MAINMENU, TF_COMMAND}, + {-1}, +#line 23 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND}, + {-1}, +#line 44 "scripts/kconfig/zconf.gperf" {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE}, +#line 47 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_OPT_ALLNOCONFIG_Y,TF_OPTION}, +#line 16 "scripts/kconfig/zconf.gperf" {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SOURCE, TF_COMMAND}, +#line 39 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND}, +#line 21 "scripts/kconfig/zconf.gperf" {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_HEX}, +#line 46 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_OPT_ENV, TF_OPTION}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_PROMPT, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_DEPENDS, TF_COMMAND}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 40 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_RANGE, TF_COMMAND}, +#line 19 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CHOICE, TF_COMMAND}, + {-1}, {-1}, +#line 33 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, +#line 18 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND}, +#line 41 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_VISIBLE, TF_COMMAND}, +#line 37 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_TYPE, TF_COMMAND, S_HEX}, + {-1}, {-1}, +#line 22 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_CONFIG, TF_COMMAND}, +#line 34 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, {-1}, {-1}, +#line 38 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_TYPE, TF_COMMAND, S_STRING}, + {-1}, {-1}, +#line 24 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54, T_HELP, TF_COMMAND}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND} +#line 30 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56, T_PROMPT, TF_COMMAND}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 27 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72, T_DEPENDS, TF_COMMAND} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) @@ -236,4 +285,5 @@ kconf_id_lookup (register const char *str, register unsigned int len) } return 0; } +#line 48 "scripts/kconfig/zconf.gperf" diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l index 3dbaec185cc..6c62d93b4ff 100644 --- a/scripts/kconfig/zconf.l +++ b/scripts/kconfig/zconf.l @@ -1,5 +1,5 @@ -%option backup nostdinit noyywrap never-interactive full ecs -%option 8bit backup nodefault perf-report perf-report +%option nostdinit noyywrap never-interactive full ecs +%option 8bit nodefault perf-report perf-report %option noinput %x COMMAND HELP STRING PARAM %{ @@ -14,7 +14,6 @@ #include <string.h> #include <unistd.h> -#define LKC_DIRECT_LINK #include "lkc.h" #define START_STRSIZE 16 @@ -28,8 +27,8 @@ static char *text; static int text_size, text_asize; struct buffer { - struct buffer *parent; - YY_BUFFER_STATE state; + struct buffer *parent; + YY_BUFFER_STATE state; }; struct buffer *current_buf; @@ -41,7 +40,7 @@ static void zconf_endfile(void); static void new_string(void) { - text = malloc(START_STRSIZE); + text = xmalloc(START_STRSIZE); text_asize = START_STRSIZE; text_size = 0; *text = 0; @@ -63,13 +62,12 @@ static void append_string(const char *str, int size) static void alloc_string(const char *str, int size) { - text = malloc(size + 1); + text = xmalloc(size + 1); memcpy(text, str, size); text[size] = 0; } %} -ws [ \n\t] n [A-Za-z0-9_] %% @@ -96,7 +94,7 @@ n [A-Za-z0-9_] <COMMAND>{ {n}+ { - struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); BEGIN(PARAM); current_pos.file = current_file; current_pos.lineno = current_file->lineno; @@ -132,7 +130,7 @@ n [A-Za-z0-9_] \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; --- /* ignore */ ({n}|[-/.])+ { - struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); if (id && id->flags & TF_PARAM) { zconflval.id = id; return id->token; @@ -289,18 +287,18 @@ void zconf_initscan(const char *name) exit(1); } - current_buf = malloc(sizeof(*current_buf)); + current_buf = xmalloc(sizeof(*current_buf)); memset(current_buf, 0, sizeof(*current_buf)); current_file = file_lookup(name); current_file->lineno = 1; - current_file->flags = FILE_BUSY; } void zconf_nextfile(const char *name) { + struct file *iter; struct file *file = file_lookup(name); - struct buffer *buf = malloc(sizeof(*buf)); + struct buffer *buf = xmalloc(sizeof(*buf)); memset(buf, 0, sizeof(*buf)); current_buf->state = YY_CURRENT_BUFFER; @@ -314,18 +312,25 @@ void zconf_nextfile(const char *name) buf->parent = current_buf; current_buf = buf; - if (file->flags & FILE_BUSY) { - printf("%s:%d: do not source '%s' from itself\n", - zconf_curname(), zconf_lineno(), name); - exit(1); - } - if (file->flags & FILE_SCANNED) { - printf("%s:%d: file '%s' is already sourced from '%s'\n", - zconf_curname(), zconf_lineno(), name, - file->parent->name); - exit(1); + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } } - file->flags |= FILE_BUSY; file->lineno = 1; file->parent = current_file; current_file = file; @@ -335,8 +340,6 @@ static void zconf_endfile(void) { struct buffer *parent; - current_file->flags |= FILE_SCANNED; - current_file->flags &= ~FILE_BUSY; current_file = current_file->parent; parent = current_buf->parent; diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/zconf.lex.c_shipped index 6eb03971825..349a7f24315 100644 --- a/scripts/kconfig/lex.zconf.c_shipped +++ b/scripts/kconfig/zconf.lex.c_shipped @@ -1,5 +1,5 @@ -#line 3 "scripts/kconfig/lex.zconf.c" +#line 3 "scripts/kconfig/zconf.lex.c_shipped" #define YY_INT_ALIGNED short int @@ -72,6 +72,7 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -102,8 +103,6 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif -#endif /* ! C99 */ - #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -160,15 +159,7 @@ typedef unsigned int flex_uint32_t; /* Size of default input buffer. */ #ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 -#else #define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. @@ -785,7 +776,6 @@ char *zconftext; #include <string.h> #include <unistd.h> -#define LKC_DIRECT_LINK #include "lkc.h" #define START_STRSIZE 16 @@ -799,8 +789,8 @@ static char *text; static int text_size, text_asize; struct buffer { - struct buffer *parent; - YY_BUFFER_STATE state; + struct buffer *parent; + YY_BUFFER_STATE state; }; struct buffer *current_buf; @@ -812,7 +802,7 @@ static void zconf_endfile(void); static void new_string(void) { - text = malloc(START_STRSIZE); + text = xmalloc(START_STRSIZE); text_asize = START_STRSIZE; text_size = 0; *text = 0; @@ -834,7 +824,7 @@ static void append_string(const char *str, int size) static void alloc_string(const char *str, int size) { - text = malloc(size + 1); + text = xmalloc(size + 1); memcpy(text, str, size); text[size] = 0; } @@ -922,12 +912,7 @@ static int input (void ); /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else #define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ @@ -1100,7 +1085,7 @@ YY_RULE_SETUP case 6: YY_RULE_SETUP { - struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); BEGIN(PARAM); current_pos.file = current_file; current_pos.lineno = current_file->lineno; @@ -1175,7 +1160,7 @@ YY_RULE_SETUP case 19: YY_RULE_SETUP { - struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); if (id && id->flags & TF_PARAM) { zconflval.id = id; return id->token; @@ -2073,8 +2058,8 @@ YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ @@ -2358,18 +2343,18 @@ void zconf_initscan(const char *name) exit(1); } - current_buf = malloc(sizeof(*current_buf)); + current_buf = xmalloc(sizeof(*current_buf)); memset(current_buf, 0, sizeof(*current_buf)); current_file = file_lookup(name); current_file->lineno = 1; - current_file->flags = FILE_BUSY; } void zconf_nextfile(const char *name) { + struct file *iter; struct file *file = file_lookup(name); - struct buffer *buf = malloc(sizeof(*buf)); + struct buffer *buf = xmalloc(sizeof(*buf)); memset(buf, 0, sizeof(*buf)); current_buf->state = YY_CURRENT_BUFFER; @@ -2383,18 +2368,25 @@ void zconf_nextfile(const char *name) buf->parent = current_buf; current_buf = buf; - if (file->flags & FILE_BUSY) { - printf("%s:%d: do not source '%s' from itself\n", - zconf_curname(), zconf_lineno(), name); - exit(1); - } - if (file->flags & FILE_SCANNED) { - printf("%s:%d: file '%s' is already sourced from '%s'\n", - zconf_curname(), zconf_lineno(), name, - file->parent->name); - exit(1); + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } } - file->flags |= FILE_BUSY; file->lineno = 1; file->parent = current_file; current_file = file; @@ -2404,8 +2396,6 @@ static void zconf_endfile(void) { struct buffer *parent; - current_file->flags |= FILE_SCANNED; - current_file->flags &= ~FILE_BUSY; current_file = current_file->parent; parent = current_buf->parent; diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index 699d4b26518..de5e84ed3f9 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -1,10 +1,8 @@ +/* A Bison parser, made by GNU Bison 2.5. */ -/* A Bison parser, made by GNU Bison 2.4.1. */ - -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.4.1" +#define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -88,7 +86,6 @@ #include <string.h> #include <stdbool.h> -#define LKC_DIRECT_LINK #include "lkc.h" #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) @@ -102,22 +99,18 @@ extern int zconflex(void); static void zconfprint(const char *err, ...); static void zconf_error(const char *err, ...); static void zconferror(const char *err); -static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); struct symbol *symbol_hash[SYMBOL_HASHSIZE]; static struct menu *current_menu, *current_entry; -#define YYDEBUG 0 -#if YYDEBUG -#define YYERROR_VERBOSE -#endif /* Enabling traces. */ #ifndef YYDEBUG -# define YYDEBUG 0 +# define YYDEBUG 1 #endif /* Enabling verbose error messages. */ @@ -160,18 +153,19 @@ static struct menu *current_menu, *current_entry; T_DEFAULT = 275, T_SELECT = 276, T_RANGE = 277, - T_OPTION = 278, - T_ON = 279, - T_WORD = 280, - T_WORD_QUOTE = 281, - T_UNEQUAL = 282, - T_CLOSE_PAREN = 283, - T_OPEN_PAREN = 284, - T_EOL = 285, - T_OR = 286, - T_AND = 287, - T_EQUAL = 288, - T_NOT = 289 + T_VISIBLE = 278, + T_OPTION = 279, + T_ON = 280, + T_WORD = 281, + T_WORD_QUOTE = 282, + T_UNEQUAL = 283, + T_CLOSE_PAREN = 284, + T_OPEN_PAREN = 285, + T_EOL = 286, + T_OR = 287, + T_AND = 288, + T_EQUAL = 289, + T_NOT = 290 }; #endif @@ -187,7 +181,7 @@ typedef union YYSTYPE struct symbol *symbol; struct expr *expr; struct menu *menu; - struct kconf_id *id; + const struct kconf_id *id; @@ -254,7 +248,7 @@ typedef short int yytype_int16; #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ -# if YYENABLE_NLS +# if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include <libintl.h> /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) @@ -307,11 +301,11 @@ YYID (yyi) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -334,24 +328,24 @@ YYID (yyi) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ +# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif @@ -380,23 +374,7 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of @@ -416,23 +394,43 @@ union yyalloc #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 11 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 277 +#define YYLAST 290 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 35 +#define YYNTOKENS 36 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 48 +#define YYNNTS 50 /* YYNRULES -- Number of rules. */ -#define YYNRULES 113 +#define YYNRULES 118 /* YYNRULES -- Number of states. */ -#define YYNSTATES 185 +#define YYNSTATES 191 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 289 +#define YYMAXUTOK 290 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -468,7 +466,8 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35 }; #if YYDEBUG @@ -478,72 +477,73 @@ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 6, 8, 11, 13, 14, 17, 20, 23, 26, 31, 36, 40, 42, 44, 46, 48, 50, - 52, 54, 56, 58, 60, 62, 64, 66, 70, 73, - 77, 80, 84, 87, 88, 91, 94, 97, 100, 103, - 106, 110, 115, 120, 125, 131, 135, 136, 140, 141, - 144, 148, 151, 153, 157, 158, 161, 164, 167, 170, - 173, 178, 182, 185, 190, 191, 194, 198, 200, 204, - 205, 208, 211, 214, 218, 222, 225, 227, 231, 232, - 235, 238, 241, 245, 249, 252, 255, 258, 259, 262, - 265, 268, 273, 274, 277, 279, 281, 284, 287, 290, - 292, 295, 296, 299, 301, 305, 309, 313, 316, 320, - 324, 326, 328, 329 + 52, 54, 56, 58, 60, 62, 64, 66, 68, 72, + 75, 79, 82, 86, 89, 90, 93, 96, 99, 102, + 105, 108, 112, 117, 122, 127, 133, 137, 138, 142, + 143, 146, 150, 153, 155, 159, 160, 163, 166, 169, + 172, 175, 180, 184, 187, 192, 193, 196, 200, 202, + 206, 207, 210, 213, 216, 220, 224, 228, 230, 234, + 235, 238, 241, 244, 248, 252, 255, 258, 261, 262, + 265, 268, 271, 276, 277, 280, 283, 286, 287, 290, + 292, 294, 297, 300, 303, 305, 308, 309, 312, 314, + 318, 322, 326, 329, 333, 337, 339, 341, 342 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 36, 0, -1, 78, 37, -1, 37, -1, 62, 38, - -1, 38, -1, -1, 38, 40, -1, 38, 54, -1, - 38, 66, -1, 38, 77, -1, 38, 25, 1, 30, - -1, 38, 39, 1, 30, -1, 38, 1, 30, -1, + 37, 0, -1, 81, 38, -1, 38, -1, 63, 39, + -1, 39, -1, -1, 39, 41, -1, 39, 55, -1, + 39, 67, -1, 39, 80, -1, 39, 26, 1, 31, + -1, 39, 40, 1, 31, -1, 39, 1, 31, -1, 16, -1, 18, -1, 19, -1, 21, -1, 17, -1, - 22, -1, 20, -1, 30, -1, 60, -1, 70, -1, - 43, -1, 45, -1, 68, -1, 25, 1, 30, -1, - 1, 30, -1, 10, 25, 30, -1, 42, 46, -1, - 11, 25, 30, -1, 44, 46, -1, -1, 46, 47, - -1, 46, 48, -1, 46, 74, -1, 46, 72, -1, - 46, 41, -1, 46, 30, -1, 19, 75, 30, -1, - 18, 76, 79, 30, -1, 20, 80, 79, 30, -1, - 21, 25, 79, 30, -1, 22, 81, 81, 79, 30, - -1, 23, 49, 30, -1, -1, 49, 25, 50, -1, - -1, 33, 76, -1, 7, 82, 30, -1, 51, 55, - -1, 77, -1, 52, 57, 53, -1, -1, 55, 56, - -1, 55, 74, -1, 55, 72, -1, 55, 30, -1, - 55, 41, -1, 18, 76, 79, 30, -1, 19, 75, - 30, -1, 17, 30, -1, 20, 25, 79, 30, -1, - -1, 57, 40, -1, 14, 80, 78, -1, 77, -1, - 58, 61, 59, -1, -1, 61, 40, -1, 61, 66, - -1, 61, 54, -1, 3, 76, 78, -1, 4, 76, - 30, -1, 63, 73, -1, 77, -1, 64, 67, 65, - -1, -1, 67, 40, -1, 67, 66, -1, 67, 54, - -1, 6, 76, 30, -1, 9, 76, 30, -1, 69, - 73, -1, 12, 30, -1, 71, 13, -1, -1, 73, - 74, -1, 73, 30, -1, 73, 41, -1, 16, 24, - 80, 30, -1, -1, 76, 79, -1, 25, -1, 26, - -1, 5, 30, -1, 8, 30, -1, 15, 30, -1, - 30, -1, 78, 30, -1, -1, 14, 80, -1, 81, - -1, 81, 33, 81, -1, 81, 27, 81, -1, 29, - 80, 28, -1, 34, 80, -1, 80, 31, 80, -1, - 80, 32, 80, -1, 25, -1, 26, -1, -1, 25, - -1 + 22, -1, 20, -1, 23, -1, 31, -1, 61, -1, + 71, -1, 44, -1, 46, -1, 69, -1, 26, 1, + 31, -1, 1, 31, -1, 10, 26, 31, -1, 43, + 47, -1, 11, 26, 31, -1, 45, 47, -1, -1, + 47, 48, -1, 47, 49, -1, 47, 75, -1, 47, + 73, -1, 47, 42, -1, 47, 31, -1, 19, 78, + 31, -1, 18, 79, 82, 31, -1, 20, 83, 82, + 31, -1, 21, 26, 82, 31, -1, 22, 84, 84, + 82, 31, -1, 24, 50, 31, -1, -1, 50, 26, + 51, -1, -1, 34, 79, -1, 7, 85, 31, -1, + 52, 56, -1, 80, -1, 53, 58, 54, -1, -1, + 56, 57, -1, 56, 75, -1, 56, 73, -1, 56, + 31, -1, 56, 42, -1, 18, 79, 82, 31, -1, + 19, 78, 31, -1, 17, 31, -1, 20, 26, 82, + 31, -1, -1, 58, 41, -1, 14, 83, 81, -1, + 80, -1, 59, 62, 60, -1, -1, 62, 41, -1, + 62, 67, -1, 62, 55, -1, 3, 79, 81, -1, + 4, 79, 31, -1, 64, 76, 74, -1, 80, -1, + 65, 68, 66, -1, -1, 68, 41, -1, 68, 67, + -1, 68, 55, -1, 6, 79, 31, -1, 9, 79, + 31, -1, 70, 74, -1, 12, 31, -1, 72, 13, + -1, -1, 74, 75, -1, 74, 31, -1, 74, 42, + -1, 16, 25, 83, 31, -1, -1, 76, 77, -1, + 76, 31, -1, 23, 82, -1, -1, 79, 82, -1, + 26, -1, 27, -1, 5, 31, -1, 8, 31, -1, + 15, 31, -1, 31, -1, 81, 31, -1, -1, 14, + 83, -1, 84, -1, 84, 34, 84, -1, 84, 28, + 84, -1, 30, 83, 29, -1, 35, 83, -1, 83, + 32, 83, -1, 83, 33, 83, -1, 26, -1, 27, + -1, -1, 26, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 107, 107, 107, 109, 109, 111, 113, 114, 115, - 116, 117, 118, 122, 126, 126, 126, 126, 126, 126, - 126, 130, 131, 132, 133, 134, 135, 139, 140, 146, - 154, 160, 168, 178, 180, 181, 182, 183, 184, 185, - 188, 196, 202, 212, 218, 224, 227, 229, 240, 241, - 246, 255, 260, 268, 271, 273, 274, 275, 276, 277, - 280, 286, 297, 303, 313, 315, 320, 328, 336, 339, - 341, 342, 343, 348, 355, 362, 367, 375, 378, 380, - 381, 382, 385, 393, 400, 407, 413, 420, 422, 423, - 424, 427, 435, 437, 442, 443, 446, 447, 448, 452, - 453, 456, 457, 460, 461, 462, 463, 464, 465, 466, - 469, 470, 473, 474 + 0, 103, 103, 103, 105, 105, 107, 109, 110, 111, + 112, 113, 114, 118, 122, 122, 122, 122, 122, 122, + 122, 122, 126, 127, 128, 129, 130, 131, 135, 136, + 142, 150, 156, 164, 174, 176, 177, 178, 179, 180, + 181, 184, 192, 198, 208, 214, 220, 223, 225, 236, + 237, 242, 251, 256, 264, 267, 269, 270, 271, 272, + 273, 276, 282, 293, 299, 309, 311, 316, 324, 332, + 335, 337, 338, 339, 344, 351, 358, 363, 371, 374, + 376, 377, 378, 381, 389, 396, 403, 409, 416, 418, + 419, 420, 423, 431, 433, 434, 437, 444, 446, 451, + 452, 455, 456, 457, 461, 462, 465, 466, 469, 470, + 471, 472, 473, 474, 475, 478, 479, 482, 483 }; #endif @@ -556,7 +556,7 @@ static const char *const yytname[] = "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE", - "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", "T_NOT", "$accept", "input", "start", "stmt_list", "option_name", "common_stmt", "option_error", "config_entry_start", "config_stmt", @@ -567,8 +567,8 @@ static const char *const yytname[] = "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu", "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt", "help_start", "help", "depends_list", - "depends", "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", - "symbol", "word_opt", 0 + "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt", + "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0 }; #endif @@ -580,25 +580,25 @@ static const yytype_uint16 yytoknum[] = 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289 + 285, 286, 287, 288, 289, 290 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 35, 36, 36, 37, 37, 38, 38, 38, 38, - 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, - 39, 40, 40, 40, 40, 40, 40, 41, 41, 42, - 43, 44, 45, 46, 46, 46, 46, 46, 46, 46, - 47, 47, 47, 47, 47, 48, 49, 49, 50, 50, - 51, 52, 53, 54, 55, 55, 55, 55, 55, 55, - 56, 56, 56, 56, 57, 57, 58, 59, 60, 61, - 61, 61, 61, 62, 63, 64, 65, 66, 67, 67, - 67, 67, 68, 69, 70, 71, 72, 73, 73, 73, - 73, 74, 75, 75, 76, 76, 77, 77, 77, 78, - 78, 79, 79, 80, 80, 80, 80, 80, 80, 80, - 81, 81, 82, 82 + 0, 36, 37, 37, 38, 38, 39, 39, 39, 39, + 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, + 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, + 43, 44, 45, 46, 47, 47, 47, 47, 47, 47, + 47, 48, 48, 48, 48, 48, 49, 50, 50, 51, + 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, + 56, 57, 57, 57, 57, 58, 58, 59, 60, 61, + 62, 62, 62, 62, 63, 64, 65, 66, 67, 68, + 68, 68, 68, 69, 70, 71, 72, 73, 74, 74, + 74, 74, 75, 76, 76, 76, 77, 78, 78, 79, + 79, 80, 80, 80, 81, 81, 82, 82, 83, 83, + 83, 83, 83, 83, 83, 84, 84, 85, 85 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -606,182 +606,194 @@ static const yytype_uint8 yyr2[] = { 0, 2, 2, 1, 2, 1, 0, 2, 2, 2, 2, 4, 4, 3, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, - 2, 3, 2, 0, 2, 2, 2, 2, 2, 2, - 3, 4, 4, 4, 5, 3, 0, 3, 0, 2, - 3, 2, 1, 3, 0, 2, 2, 2, 2, 2, - 4, 3, 2, 4, 0, 2, 3, 1, 3, 0, - 2, 2, 2, 3, 3, 2, 1, 3, 0, 2, - 2, 2, 3, 3, 2, 2, 2, 0, 2, 2, - 2, 4, 0, 2, 1, 1, 2, 2, 2, 1, - 2, 0, 2, 1, 3, 3, 3, 2, 3, 3, - 1, 1, 0, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, + 3, 2, 3, 2, 0, 2, 2, 2, 2, 2, + 2, 3, 4, 4, 4, 5, 3, 0, 3, 0, + 2, 3, 2, 1, 3, 0, 2, 2, 2, 2, + 2, 4, 3, 2, 4, 0, 2, 3, 1, 3, + 0, 2, 2, 2, 3, 3, 3, 1, 3, 0, + 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, + 2, 2, 4, 0, 2, 2, 2, 0, 2, 1, + 1, 2, 2, 2, 1, 2, 0, 2, 1, 3, + 3, 3, 2, 3, 3, 1, 1, 0, 1 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero +/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { - 6, 0, 99, 0, 3, 0, 6, 6, 94, 95, - 0, 1, 0, 0, 0, 0, 112, 0, 0, 0, + 6, 0, 104, 0, 3, 0, 6, 6, 99, 100, + 0, 1, 0, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 14, 18, 15, 16, 20, 17, 19, - 0, 21, 0, 7, 33, 24, 33, 25, 54, 64, - 8, 69, 22, 87, 78, 9, 26, 87, 23, 10, - 0, 100, 2, 73, 13, 0, 96, 0, 113, 0, - 97, 0, 0, 0, 110, 111, 0, 0, 0, 103, - 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 74, 82, 50, 83, 29, 31, 0, 107, 0, - 0, 66, 0, 0, 11, 12, 0, 0, 0, 0, - 92, 0, 0, 0, 46, 0, 39, 38, 34, 35, - 0, 37, 36, 0, 0, 92, 0, 58, 59, 55, - 57, 56, 65, 53, 52, 70, 72, 68, 71, 67, - 89, 90, 88, 79, 81, 77, 80, 76, 106, 108, - 109, 105, 104, 28, 85, 0, 101, 0, 101, 101, - 101, 0, 0, 0, 86, 62, 101, 0, 101, 0, - 0, 0, 40, 93, 0, 0, 101, 48, 45, 27, - 0, 61, 0, 91, 102, 41, 42, 43, 0, 0, - 47, 60, 63, 44, 49 + 21, 0, 22, 0, 7, 34, 25, 34, 26, 55, + 65, 8, 70, 23, 93, 79, 9, 27, 88, 24, + 10, 0, 105, 2, 74, 13, 0, 101, 0, 118, + 0, 102, 0, 0, 0, 115, 116, 0, 0, 0, + 108, 103, 0, 0, 0, 0, 0, 0, 0, 88, + 0, 0, 75, 83, 51, 84, 30, 32, 0, 112, + 0, 0, 67, 0, 0, 11, 12, 0, 0, 0, + 0, 97, 0, 0, 0, 47, 0, 40, 39, 35, + 36, 0, 38, 37, 0, 0, 97, 0, 59, 60, + 56, 58, 57, 66, 54, 53, 71, 73, 69, 72, + 68, 106, 95, 0, 94, 80, 82, 78, 81, 77, + 90, 91, 89, 111, 113, 114, 110, 109, 29, 86, + 0, 106, 0, 106, 106, 106, 0, 0, 0, 87, + 63, 106, 0, 106, 0, 96, 0, 0, 41, 98, + 0, 0, 106, 49, 46, 28, 0, 62, 0, 107, + 92, 42, 43, 44, 0, 0, 48, 61, 64, 45, + 50 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 3, 4, 5, 32, 33, 107, 34, 35, 36, - 37, 73, 108, 109, 152, 180, 38, 39, 123, 40, - 75, 119, 76, 41, 127, 42, 77, 6, 43, 44, - 135, 45, 79, 46, 47, 48, 110, 111, 78, 112, - 147, 148, 49, 7, 161, 68, 69, 59 + -1, 3, 4, 5, 33, 34, 108, 35, 36, 37, + 38, 74, 109, 110, 157, 186, 39, 40, 124, 41, + 76, 120, 77, 42, 128, 43, 78, 6, 44, 45, + 137, 46, 80, 47, 48, 49, 111, 112, 81, 113, + 79, 134, 152, 153, 50, 7, 165, 69, 70, 60 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -89 +#define YYPACT_NINF -90 static const yytype_int16 yypact[] = { - 3, 4, -89, 20, -89, 100, -89, 7, -89, -89, - -8, -89, 17, 4, 28, 4, 37, 36, 4, 68, - 87, -18, 69, -89, -89, -89, -89, -89, -89, -89, - 128, -89, 138, -89, -89, -89, -89, -89, -89, -89, - -89, -89, -89, -89, -89, -89, -89, -89, -89, -89, - 127, -89, -89, 110, -89, 126, -89, 136, -89, 137, - -89, 147, 150, 152, -89, -89, -18, -18, 171, -14, - -89, 153, 157, 34, 67, 180, 233, 220, 207, 220, - 154, -89, -89, -89, -89, -89, -89, 0, -89, -18, - -18, 110, 44, 44, -89, -89, 163, 174, 182, 4, - 4, -18, 194, 44, -89, 219, -89, -89, -89, -89, - 223, -89, -89, 203, 4, 4, 215, -89, -89, -89, - -89, -89, -89, -89, -89, -89, -89, -89, -89, -89, - -89, -89, -89, -89, -89, -89, -89, -89, -89, 213, - -89, -89, -89, -89, -89, -18, 232, 227, 232, -5, - 232, 44, 35, 234, -89, -89, 232, 235, 232, 224, - -18, 236, -89, -89, 237, 238, 232, 216, -89, -89, - 240, -89, 241, -89, 71, -89, -89, -89, 242, 4, - -89, -89, -89, -89, -89 + 4, 42, -90, 96, -90, 111, -90, 15, -90, -90, + 75, -90, 82, 42, 104, 42, 110, 107, 42, 115, + 125, -4, 121, -90, -90, -90, -90, -90, -90, -90, + -90, 162, -90, 163, -90, -90, -90, -90, -90, -90, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, 139, -90, -90, 138, -90, 142, -90, 143, -90, + 152, -90, 164, 167, 168, -90, -90, -4, -4, 77, + -18, -90, 177, 185, 33, 71, 195, 247, 236, -2, + 236, 171, -90, -90, -90, -90, -90, -90, 41, -90, + -4, -4, 138, 97, 97, -90, -90, 186, 187, 194, + 42, 42, -4, 196, 97, -90, 219, -90, -90, -90, + -90, 210, -90, -90, 204, 42, 42, 199, -90, -90, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, 222, -90, 223, -90, -90, -90, -90, -90, -90, + -90, -90, -90, -90, 215, -90, -90, -90, -90, -90, + -4, 222, 228, 222, -5, 222, 97, 35, 229, -90, + -90, 222, 232, 222, -4, -90, 135, 233, -90, -90, + 234, 235, 222, 240, -90, -90, 237, -90, 239, -13, + -90, -90, -90, -90, 244, 42, -90, -90, -90, -90, + -90 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -89, -89, 255, 267, -89, 47, -57, -89, -89, -89, - -89, 239, -89, -89, -89, -89, -89, -89, -89, 130, - -89, -89, -89, -89, -89, -89, -89, -89, -89, -89, - -89, 181, -89, -89, -89, -89, -89, 199, 229, 16, - 162, -1, 74, -7, 103, -65, -88, -89 + -90, -90, 269, 271, -90, 23, -70, -90, -90, -90, + -90, 243, -90, -90, -90, -90, -90, -90, -90, -48, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, -20, -90, -90, -90, -90, -90, 206, 205, -68, + -90, -90, 169, -1, 27, -7, 118, -66, -89, -90 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -85 + number is the opposite. If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -86 static const yytype_int16 yytable[] = { - 10, 87, 88, 53, 141, 142, 1, 64, 65, 160, - 1, 66, 55, 92, 57, 151, 67, 61, 118, 93, - 11, 131, 2, 131, 139, 140, 89, 90, 138, 8, - 9, 89, 90, 2, -30, 96, 149, 51, -30, -30, - -30, -30, -30, -30, -30, -30, 97, 54, -30, -30, - 98, -30, 99, 100, 101, 102, 103, 104, 56, 105, - 167, 91, 58, 166, 106, 168, 60, -32, 96, 64, - 65, -32, -32, -32, -32, -32, -32, -32, -32, 97, - 159, -32, -32, 98, -32, 99, 100, 101, 102, 103, - 104, 121, 105, 62, 132, 174, 132, 106, 146, 70, - -5, 12, 89, 90, 13, 14, 15, 16, 17, 18, - 19, 20, 63, 156, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 122, 125, 30, 133, -4, 12, 71, - 31, 13, 14, 15, 16, 17, 18, 19, 20, 72, - 51, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 124, 129, 30, 137, -84, 96, 81, 31, -84, -84, - -84, -84, -84, -84, -84, -84, 82, 83, -84, -84, - 98, -84, -84, -84, -84, -84, -84, 84, 184, 105, - 85, 96, 86, 94, 130, -51, -51, 95, -51, -51, - -51, -51, 97, 143, -51, -51, 98, 113, 114, 115, - 116, 2, 89, 90, 144, 105, 145, 126, 96, 134, - 117, -75, -75, -75, -75, -75, -75, -75, -75, 150, - 153, -75, -75, 98, 13, 14, 15, 16, 17, 18, - 19, 20, 105, 155, 21, 22, 154, 130, 14, 15, - 158, 17, 18, 19, 20, 90, 160, 21, 22, 179, - 31, 163, 164, 165, 173, 89, 90, 162, 128, 170, - 136, 172, 52, 31, 169, 171, 175, 176, 177, 178, - 181, 182, 183, 50, 120, 74, 80, 157 + 10, 88, 89, 54, 146, 147, 119, 1, 122, 164, + 93, 141, 56, 142, 58, 156, 94, 62, 1, 90, + 91, 131, 65, 66, 144, 145, 67, 90, 91, 132, + 127, 68, 136, -31, 97, 2, 154, -31, -31, -31, + -31, -31, -31, -31, -31, 98, 52, -31, -31, 99, + -31, 100, 101, 102, 103, 104, -31, 105, 129, 106, + 138, 173, 92, 141, 107, 142, 174, 172, 8, 9, + 143, -33, 97, 90, 91, -33, -33, -33, -33, -33, + -33, -33, -33, 98, 166, -33, -33, 99, -33, 100, + 101, 102, 103, 104, -33, 105, 11, 106, 179, 151, + 123, 126, 107, 135, 125, 130, 2, 139, 2, 90, + 91, -5, 12, 55, 161, 13, 14, 15, 16, 17, + 18, 19, 20, 65, 66, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 57, 59, 31, 61, -4, + 12, 63, 32, 13, 14, 15, 16, 17, 18, 19, + 20, 64, 71, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 72, 73, 31, 180, 90, 91, 52, + 32, -85, 97, 82, 83, -85, -85, -85, -85, -85, + -85, -85, -85, 84, 190, -85, -85, 99, -85, -85, + -85, -85, -85, -85, -85, 85, 97, 106, 86, 87, + -52, -52, 140, -52, -52, -52, -52, 98, 95, -52, + -52, 99, 114, 115, 116, 117, 96, 148, 149, 150, + 158, 106, 155, 159, 97, 163, 118, -76, -76, -76, + -76, -76, -76, -76, -76, 160, 164, -76, -76, 99, + 13, 14, 15, 16, 17, 18, 19, 20, 91, 106, + 21, 22, 14, 15, 140, 17, 18, 19, 20, 168, + 175, 21, 22, 177, 181, 182, 183, 32, 187, 167, + 188, 169, 170, 171, 185, 189, 53, 51, 32, 176, + 75, 178, 121, 0, 133, 162, 0, 0, 0, 0, + 184 }; -static const yytype_uint8 yycheck[] = +#define yypact_value_is_default(yystate) \ + ((yystate) == (-90)) + +#define yytable_value_is_error(yytable_value) \ + YYID (0) + +static const yytype_int16 yycheck[] = { - 1, 66, 67, 10, 92, 93, 3, 25, 26, 14, - 3, 29, 13, 27, 15, 103, 34, 18, 75, 33, - 0, 78, 30, 80, 89, 90, 31, 32, 28, 25, - 26, 31, 32, 30, 0, 1, 101, 30, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 30, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 30, 25, - 25, 68, 25, 151, 30, 30, 30, 0, 1, 25, - 26, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 145, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 75, 25, 25, 78, 160, 80, 30, 99, 30, - 0, 1, 31, 32, 4, 5, 6, 7, 8, 9, - 10, 11, 25, 114, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 76, 77, 25, 79, 0, 1, 1, - 30, 4, 5, 6, 7, 8, 9, 10, 11, 1, - 30, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 76, 77, 25, 79, 0, 1, 30, 30, 4, 5, - 6, 7, 8, 9, 10, 11, 30, 30, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 30, 179, 25, - 30, 1, 30, 30, 30, 5, 6, 30, 8, 9, - 10, 11, 12, 30, 14, 15, 16, 17, 18, 19, - 20, 30, 31, 32, 30, 25, 24, 77, 1, 79, - 30, 4, 5, 6, 7, 8, 9, 10, 11, 25, - 1, 14, 15, 16, 4, 5, 6, 7, 8, 9, - 10, 11, 25, 30, 14, 15, 13, 30, 5, 6, - 25, 8, 9, 10, 11, 32, 14, 14, 15, 33, - 30, 148, 149, 150, 30, 31, 32, 30, 77, 156, - 79, 158, 7, 30, 30, 30, 30, 30, 30, 166, - 30, 30, 30, 6, 75, 36, 47, 115 + 1, 67, 68, 10, 93, 94, 76, 3, 76, 14, + 28, 81, 13, 81, 15, 104, 34, 18, 3, 32, + 33, 23, 26, 27, 90, 91, 30, 32, 33, 31, + 78, 35, 80, 0, 1, 31, 102, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 31, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 78, 26, + 80, 26, 69, 133, 31, 133, 31, 156, 26, 27, + 29, 0, 1, 32, 33, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 150, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 0, 26, 164, 100, + 77, 78, 31, 80, 77, 78, 31, 80, 31, 32, + 33, 0, 1, 31, 115, 4, 5, 6, 7, 8, + 9, 10, 11, 26, 27, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 31, 26, 26, 31, 0, + 1, 26, 31, 4, 5, 6, 7, 8, 9, 10, + 11, 26, 31, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 1, 1, 26, 31, 32, 33, 31, + 31, 0, 1, 31, 31, 4, 5, 6, 7, 8, + 9, 10, 11, 31, 185, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 31, 1, 26, 31, 31, + 5, 6, 31, 8, 9, 10, 11, 12, 31, 14, + 15, 16, 17, 18, 19, 20, 31, 31, 31, 25, + 1, 26, 26, 13, 1, 26, 31, 4, 5, 6, + 7, 8, 9, 10, 11, 31, 14, 14, 15, 16, + 4, 5, 6, 7, 8, 9, 10, 11, 33, 26, + 14, 15, 5, 6, 31, 8, 9, 10, 11, 31, + 31, 14, 15, 31, 31, 31, 31, 31, 31, 151, + 31, 153, 154, 155, 34, 31, 7, 6, 31, 161, + 37, 163, 76, -1, 79, 116, -1, -1, -1, -1, + 172 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 30, 36, 37, 38, 62, 78, 25, 26, - 76, 0, 1, 4, 5, 6, 7, 8, 9, 10, + 0, 3, 31, 37, 38, 39, 63, 81, 26, 27, + 79, 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 25, 30, 39, 40, 42, 43, 44, 45, 51, 52, - 54, 58, 60, 63, 64, 66, 68, 69, 70, 77, - 38, 30, 37, 78, 30, 76, 30, 76, 25, 82, - 30, 76, 25, 25, 25, 26, 29, 34, 80, 81, - 30, 1, 1, 46, 46, 55, 57, 61, 73, 67, - 73, 30, 30, 30, 30, 30, 30, 80, 80, 31, - 32, 78, 27, 33, 30, 30, 1, 12, 16, 18, - 19, 20, 21, 22, 23, 25, 30, 41, 47, 48, - 71, 72, 74, 17, 18, 19, 20, 30, 41, 56, - 72, 74, 40, 53, 77, 40, 54, 59, 66, 77, - 30, 41, 74, 40, 54, 65, 66, 77, 28, 80, - 80, 81, 81, 30, 30, 24, 76, 75, 76, 80, - 25, 81, 49, 1, 13, 30, 76, 75, 25, 80, - 14, 79, 30, 79, 79, 79, 81, 25, 30, 30, - 79, 30, 79, 30, 80, 30, 30, 30, 79, 33, - 50, 30, 30, 30, 76 + 23, 26, 31, 40, 41, 43, 44, 45, 46, 52, + 53, 55, 59, 61, 64, 65, 67, 69, 70, 71, + 80, 39, 31, 38, 81, 31, 79, 31, 79, 26, + 85, 31, 79, 26, 26, 26, 27, 30, 35, 83, + 84, 31, 1, 1, 47, 47, 56, 58, 62, 76, + 68, 74, 31, 31, 31, 31, 31, 31, 83, 83, + 32, 33, 81, 28, 34, 31, 31, 1, 12, 16, + 18, 19, 20, 21, 22, 24, 26, 31, 42, 48, + 49, 72, 73, 75, 17, 18, 19, 20, 31, 42, + 57, 73, 75, 41, 54, 80, 41, 55, 60, 67, + 80, 23, 31, 74, 77, 41, 55, 66, 67, 80, + 31, 42, 75, 29, 83, 83, 84, 84, 31, 31, + 25, 79, 78, 79, 83, 26, 84, 50, 1, 13, + 31, 79, 78, 26, 14, 82, 83, 82, 31, 82, + 82, 82, 84, 26, 31, 31, 82, 31, 82, 83, + 31, 31, 31, 31, 82, 34, 51, 31, 31, 31, + 79 }; #define yyerrok (yyerrstatus = 0) @@ -796,9 +808,18 @@ static const yytype_uint8 yystos[] = /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ #define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif #define YYRECOVERING() (!!yyerrstatus) @@ -808,7 +829,6 @@ do \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ @@ -850,19 +870,10 @@ while (YYID (0)) #endif -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ +/* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif @@ -1054,7 +1065,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -1157,115 +1167,142 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = 0; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - Assume YYFAIL is not used. It's too flawed to consider. See + <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html> + for details. YYERROR is fine as it does not invoke this + function. + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } - if (yysize_overflow) - return YYSIZE_MAXIMUM; + yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | @@ -1292,7 +1329,7 @@ yydestruct (yymsg, yytype, yyvaluep) switch (yytype) { - case 52: /* "choice_entry" */ + case 53: /* "choice_entry" */ { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -1302,7 +1339,7 @@ yydestruct (yymsg, yytype, yyvaluep) }; break; - case 58: /* "if_entry" */ + case 59: /* "if_entry" */ { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -1312,7 +1349,7 @@ yydestruct (yymsg, yytype, yyvaluep) }; break; - case 64: /* "menu_entry" */ + case 65: /* "menu_entry" */ { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -1328,6 +1365,7 @@ yydestruct (yymsg, yytype, yyvaluep) } } + /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus @@ -1354,10 +1392,9 @@ YYSTYPE yylval; int yynerrs; - -/*-------------------------. -| yyparse or yypush_parse. | -`-------------------------*/ +/*----------. +| yyparse. | +`----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ @@ -1381,8 +1418,6 @@ yyparse () #endif #endif { - - int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; @@ -1537,7 +1572,7 @@ yybackup: /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -1568,8 +1603,8 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } @@ -1624,65 +1659,65 @@ yyreduce: { case 10: - { zconf_error("unexpected end statement"); ;} + { zconf_error("unexpected end statement"); } break; case 11: - { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;} + { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); } break; case 12: { zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name); -;} +} break; case 13: - { zconf_error("invalid statement"); ;} + { zconf_error("invalid statement"); } break; - case 27: + case 28: - { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;} + { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); } break; - case 28: + case 29: - { zconf_error("invalid option"); ;} + { zconf_error("invalid option"); } break; - case 29: + case 30: { struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); sym->flags |= SYMBOL_OPTIONAL; menu_add_entry(sym); printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); -;} +} break; - case 30: + case 31: { menu_end_entry(); printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 31: + case 32: { struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); sym->flags |= SYMBOL_OPTIONAL; menu_add_entry(sym); printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); -;} +} break; - case 32: + case 33: { if (current_entry->prompt) @@ -1691,28 +1726,28 @@ yyreduce: zconfprint("warning: menuconfig statement without prompt"); menu_end_entry(); printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 40: + case 41: { menu_set_type((yyvsp[(1) - (3)].id)->stype); printd(DEBUG_PARSE, "%s:%d:type(%u)\n", zconf_curname(), zconf_lineno(), (yyvsp[(1) - (3)].id)->stype); -;} +} break; - case 41: + case 42: { menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 42: + case 43: { menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr)); @@ -1721,48 +1756,48 @@ yyreduce: printd(DEBUG_PARSE, "%s:%d:default(%u)\n", zconf_curname(), zconf_lineno(), (yyvsp[(1) - (4)].id)->stype); -;} +} break; - case 43: + case 44: { menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 44: + case 45: { menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr)); printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 47: + case 48: { - struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string))); + const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string))); if (id && id->flags & TF_OPTION) menu_add_option(id->token, (yyvsp[(3) - (3)].string)); else zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string)); free((yyvsp[(2) - (3)].string)); -;} +} break; - case 48: + case 49: - { (yyval.string) = NULL; ;} + { (yyval.string) = NULL; } break; - case 49: + case 50: - { (yyval.string) = (yyvsp[(2) - (2)].string); ;} + { (yyval.string) = (yyvsp[(2) - (2)].string); } break; - case 50: + case 51: { struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); @@ -1770,35 +1805,35 @@ yyreduce: menu_add_entry(sym); menu_add_expr(P_CHOICE, NULL, NULL); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 51: + case 52: { (yyval.menu) = menu_add_menu(); -;} +} break; - case 52: + case 53: { if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); } -;} +} break; - case 60: + case 61: { menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 61: + case 62: { if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) { @@ -1808,18 +1843,18 @@ yyreduce: (yyvsp[(1) - (3)].id)->stype); } else YYERROR; -;} +} break; - case 62: + case 63: { current_entry->sym->flags |= SYMBOL_OPTIONAL; printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 63: + case 64: { if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) { @@ -1828,195 +1863,213 @@ yyreduce: zconf_curname(), zconf_lineno()); } else YYERROR; -;} +} break; - case 66: + case 67: { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); menu_add_entry(NULL); menu_add_dep((yyvsp[(2) - (3)].expr)); (yyval.menu) = menu_add_menu(); -;} +} break; - case 67: + case 68: { if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); } -;} +} break; - case 73: + case 74: { menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); -;} +} break; - case 74: + case 75: { menu_add_entry(NULL); menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 75: + case 76: { (yyval.menu) = menu_add_menu(); -;} +} break; - case 76: + case 77: { if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) { menu_end_menu(); printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); } -;} +} break; - case 82: + case 83: { printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); zconf_nextfile((yyvsp[(2) - (3)].string)); -;} +} break; - case 83: + case 84: { menu_add_entry(NULL); menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL); printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 84: + case 85: { menu_end_entry(); -;} +} break; - case 85: + case 86: { printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); zconf_starthelp(); -;} +} break; - case 86: + case 87: { current_entry->help = (yyvsp[(2) - (2)].string); -;} +} break; - case 91: + case 92: { menu_add_dep((yyvsp[(3) - (4)].expr)); printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); -;} +} break; - case 93: + case 96: + + { + menu_add_visibility((yyvsp[(2) - (2)].expr)); +} + break; + + case 98: { menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr)); -;} +} break; - case 96: + case 101: - { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + { (yyval.id) = (yyvsp[(1) - (2)].id); } break; - case 97: + case 102: - { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + { (yyval.id) = (yyvsp[(1) - (2)].id); } break; - case 98: + case 103: - { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + { (yyval.id) = (yyvsp[(1) - (2)].id); } break; - case 101: + case 106: - { (yyval.expr) = NULL; ;} + { (yyval.expr) = NULL; } break; - case 102: + case 107: - { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} + { (yyval.expr) = (yyvsp[(2) - (2)].expr); } break; - case 103: + case 108: - { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;} + { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); } break; - case 104: + case 109: - { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); } break; - case 105: + case 110: - { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); } break; - case 106: + case 111: - { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} + { (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; - case 107: + case 112: - { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;} + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); } break; - case 108: + case 113: - { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; - case 109: + case 114: - { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); } break; - case 110: + case 115: - { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;} + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); } break; - case 111: + case 116: - { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); } break; - case 112: + case 117: - { (yyval.string) = NULL; ;} + { (yyval.string) = NULL; } break; default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -2044,6 +2097,10 @@ yyreduce: | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { @@ -2051,37 +2108,36 @@ yyerrlab: #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -2140,7 +2196,7 @@ yyerrlab1: for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -2199,8 +2255,13 @@ yyexhaustedlab: yyreturn: if (yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); @@ -2236,24 +2297,15 @@ void conf_parse(const char *name) sym_init(); _menu_init(); - modules_sym = sym_lookup(NULL, 0); - modules_sym->type = S_BOOLEAN; - modules_sym->flags |= SYMBOL_AUTO; rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); -#if YYDEBUG if (getenv("ZCONF_DEBUG")) zconfdebug = 1; -#endif zconfparse(); if (zconfnerrs) exit(1); - if (!modules_sym->prop) { - struct property *prop; - - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); - } + if (!modules_sym) + modules_sym = sym_find( "n" ); rootmenu.prompt->text = _(rootmenu.prompt->text); rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); @@ -2262,7 +2314,7 @@ void conf_parse(const char *name) for_all_symbols(i, sym) { if (sym_check_deps(sym)) zconfnerrs++; - } + } if (zconfnerrs) exit(1); sym_set_change_count(1); @@ -2278,11 +2330,12 @@ static const char *zconf_tokenname(int token) case T_IF: return "if"; case T_ENDIF: return "endif"; case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; } return "<token>"; } -static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) { if (id->token != endtoken) { zconf_error("unexpected '%s' within %s block", @@ -2327,9 +2380,7 @@ static void zconf_error(const char *err, ...) static void zconferror(const char *err) { -#if YYDEBUG fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); -#endif } static void print_quoted_string(FILE *out, const char *str) @@ -2478,7 +2529,7 @@ void zconfdump(FILE *out) } } -#include "lex.zconf.c" +#include "zconf.lex.c" #include "util.c" #include "confdata.c" #include "expr.c" diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index 2abd3c7ff15..0f683cfa53e 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -11,7 +11,6 @@ #include <string.h> #include <stdbool.h> -#define LKC_DIRECT_LINK #include "lkc.h" #define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) @@ -25,18 +24,14 @@ extern int zconflex(void); static void zconfprint(const char *err, ...); static void zconf_error(const char *err, ...); static void zconferror(const char *err); -static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); struct symbol *symbol_hash[SYMBOL_HASHSIZE]; static struct menu *current_menu, *current_entry; -#define YYDEBUG 0 -#if YYDEBUG -#define YYERROR_VERBOSE -#endif %} -%expect 28 +%expect 30 %union { @@ -45,7 +40,7 @@ static struct menu *current_menu, *current_entry; struct symbol *symbol; struct expr *expr; struct menu *menu; - struct kconf_id *id; + const struct kconf_id *id; } %token <id>T_MAINMENU @@ -68,6 +63,7 @@ static struct menu *current_menu, *current_entry; %token <id>T_DEFAULT %token <id>T_SELECT %token <id>T_RANGE +%token <id>T_VISIBLE %token <id>T_OPTION %token <id>T_ON %token <string> T_WORD @@ -123,7 +119,7 @@ stmt_list: ; option_name: - T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT + T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE ; common_stmt: @@ -228,7 +224,7 @@ symbol_option_list: /* empty */ | symbol_option_list T_WORD symbol_option_arg { - struct kconf_id *id = kconf_id_lookup($2, strlen($2)); + const struct kconf_id *id = kconf_id_lookup($2, strlen($2)); if (id && id->flags & TF_OPTION) menu_add_option(id->token, $3); else @@ -359,7 +355,7 @@ menu: T_MENU prompt T_EOL printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); }; -menu_entry: menu depends_list +menu_entry: menu visibility_list depends_list { $$ = menu_add_menu(); }; @@ -430,6 +426,19 @@ depends: T_DEPENDS T_ON expr T_EOL printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); }; +/* visibility option */ + +visibility_list: + /* empty */ + | visibility_list visible + | visibility_list T_EOL +; + +visible: T_VISIBLE if_expr +{ + menu_add_visibility($2); +}; + /* prompt statement */ prompt_stmt_opt: @@ -484,24 +493,15 @@ void conf_parse(const char *name) sym_init(); _menu_init(); - modules_sym = sym_lookup(NULL, 0); - modules_sym->type = S_BOOLEAN; - modules_sym->flags |= SYMBOL_AUTO; rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); -#if YYDEBUG if (getenv("ZCONF_DEBUG")) zconfdebug = 1; -#endif zconfparse(); if (zconfnerrs) exit(1); - if (!modules_sym->prop) { - struct property *prop; - - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); - } + if (!modules_sym) + modules_sym = sym_find( "n" ); rootmenu.prompt->text = _(rootmenu.prompt->text); rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); @@ -510,7 +510,7 @@ void conf_parse(const char *name) for_all_symbols(i, sym) { if (sym_check_deps(sym)) zconfnerrs++; - } + } if (zconfnerrs) exit(1); sym_set_change_count(1); @@ -526,11 +526,12 @@ static const char *zconf_tokenname(int token) case T_IF: return "if"; case T_ENDIF: return "endif"; case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; } return "<token>"; } -static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) { if (id->token != endtoken) { zconf_error("unexpected '%s' within %s block", @@ -575,9 +576,7 @@ static void zconf_error(const char *err, ...) static void zconferror(const char *err) { -#if YYDEBUG fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); -#endif } static void print_quoted_string(FILE *out, const char *str) @@ -726,7 +725,7 @@ void zconfdump(FILE *out) } } -#include "lex.zconf.c" +#include "zconf.lex.c" #include "util.c" #include "confdata.c" #include "expr.c" |
