summaryrefslogtreecommitdiff
path: root/scripts
authorkergoth <kergoth>2002-10-31 17:11:35 (UTC)
committer kergoth <kergoth>2002-10-31 17:11:35 (UTC)
commitd955226c2197578f69c510282a4e9ad1ea8fe771 (patch) (side-by-side diff)
tree0d8f210dd012559df4e3432ccc8ce96e9bd15853 /scripts
parent16fcb285f9ba7c514fc3f2695768a82feeb7182b (diff)
downloadopie-d955226c2197578f69c510282a4e9ad1ea8fe771.zip
opie-d955226c2197578f69c510282a4e9ad1ea8fe771.tar.gz
opie-d955226c2197578f69c510282a4e9ad1ea8fe771.tar.bz2
Initial bits to start work on revamping the buildsystem
Diffstat (limited to 'scripts') (more/less context) (show whitespace changes)
-rw-r--r--scripts/kconfig/Makefile189
-rw-r--r--scripts/kconfig/Makefile.kernel85
-rw-r--r--scripts/kconfig/README17
-rw-r--r--scripts/kconfig/cml1.h36
-rw-r--r--scripts/kconfig/cml1.l213
-rw-r--r--scripts/kconfig/cml1.y2482
-rw-r--r--scripts/kconfig/conf.c565
-rw-r--r--scripts/kconfig/confdata.c360
-rw-r--r--scripts/kconfig/convert-all41
-rw-r--r--scripts/kconfig/example/miniconf.rb32
-rw-r--r--scripts/kconfig/example/query.rb34
-rw-r--r--scripts/kconfig/expr.c1054
-rw-r--r--scripts/kconfig/expr.h242
-rw-r--r--scripts/kconfig/expr1.c333
-rw-r--r--scripts/kconfig/extconf.rb5
-rw-r--r--scripts/kconfig/fixup-all.diff925
-rw-r--r--scripts/kconfig/help.l78
-rw-r--r--scripts/kconfig/images.c292
-rw-r--r--scripts/kconfig/kconfig.i133
-rw-r--r--scripts/kconfig/kconfig_load.c35
-rw-r--r--scripts/kconfig/lkc.h106
-rw-r--r--scripts/kconfig/lkc_overview111
-rw-r--r--scripts/kconfig/lkc_proto.h38
-rw-r--r--scripts/kconfig/lkc_spec250
-rw-r--r--scripts/kconfig/mconf.c711
-rw-r--r--scripts/kconfig/menu.c309
-rw-r--r--scripts/kconfig/prepare-all.diff1883
-rw-r--r--scripts/kconfig/qconf.cc1073
-rw-r--r--scripts/kconfig/qconf.h201
-rw-r--r--scripts/kconfig/symbol.c618
-rw-r--r--scripts/kconfig/zconf.l323
-rw-r--r--scripts/kconfig/zconf.y651
-rw-r--r--scripts/lxdialog/BIG.FAT.WARNING4
-rw-r--r--scripts/lxdialog/Makefile44
-rw-r--r--scripts/lxdialog/checklist.c369
-rw-r--r--scripts/lxdialog/colors.h161
-rw-r--r--scripts/lxdialog/dialog.h184
-rw-r--r--scripts/lxdialog/inputbox.c240
-rwxr-xr-xscripts/lxdialog/lxdialogbin0 -> 37159 bytes
-rw-r--r--scripts/lxdialog/lxdialog.c226
-rw-r--r--scripts/lxdialog/menubox.c443
-rw-r--r--scripts/lxdialog/msgbox.c85
-rw-r--r--scripts/lxdialog/textbox.c556
-rw-r--r--scripts/lxdialog/util.c359
-rw-r--r--scripts/lxdialog/yesno.c118
45 files changed, 16214 insertions, 0 deletions
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
new file mode 100644
index 0000000..ed57c6f
--- a/dev/null
+++ b/scripts/kconfig/Makefile
@@ -0,0 +1,189 @@
+VERSION=1.2
+CC=gcc
+CXX=g++
+CFLAGS=-O2 -Wall -g -fPIC
+CXXFLAGS=$(CFLAGS) -I$(QTDIR)/include
+LDFLAGS=
+LXXFLAGS=$(LDFLAGS) -L$(QTDIR)/lib -Wl,-rpath,$(QTDIR)/lib
+LEX=flex
+YACC=bison
+YFLAGS=-d -t -v
+ifndef QTDIR
+QTDIR=/usr/share/qt
+endif
+MOC=$(wildcard $(QTDIR)/bin/moc)
+
+parse_SRC=zconf.y
+conf_SRC=conf.c $(parse_SRC)
+mconf_SRC=mconf.c $(parse_SRC)
+qconf_SRC=qconf.cc
+lkcc_SRC=cml1.y cml1.l help.l cml1.h expr1.c
+HDR=expr.h lkc.h lkc_proto.h qconf.h
+OTHER=README lkc_spec lkc_overview Makefile.kernel convert-all prepare-all.diff fixup-all.diff \
+ kconfig.i extconf.rb example
+INST=zconf.y zconf.l confdata.c expr.c symbol.c menu.c conf.c mconf.c qconf.cc kconfig_load.c images.c $(parse_SRC) $(HDR)
+INSTGEN=lex.zconf.c zconf.tab.c zconf.tab.h
+
+#DEBUG=1
+ifdef DEBUG
+CFLAGS+=-DLKC_DIRECT_LINK
+qconf_SRC+=$(parse_SRC)
+else
+qconf_SRC+=kconfig_load.c
+endif
+
+SRC=$(conf_SRC) $(mconf_SRC) $(qconf_SRC) $(lkcc_SRC)
+CSRC=$(filter %.c, $(SRC))
+YSRC=$(filter %.y, $(SRC))
+LSRC=$(filter %.l, $(SRC))
+
+parse_OBJ=$(filter %.o, \
+ $(patsubst %.c,%.o, \
+ $(patsubst %.y,%.tab.o, \
+ $(patsubst %.l,lex.%.o, \
+ $(parse_SRC)))))
+conf_OBJ=$(filter %.o, \
+ $(patsubst %.c,%.o, \
+ $(patsubst %.y,%.tab.o, \
+ $(patsubst %.l,lex.%.o, \
+ $(conf_SRC)))))
+mconf_OBJ=$(filter %.o, \
+ $(patsubst %.c,%.o, \
+ $(patsubst %.y,%.tab.o, \
+ $(patsubst %.l,lex.%.o, \
+ $(mconf_SRC)))))
+qconf_OBJ=$(filter %.o, \
+ $(patsubst %.c,%.o, \
+ $(patsubst %.cc,%.o, \
+ $(patsubst %.y,%.tab.o, \
+ $(patsubst %.l,lex.%.o, \
+ $(qconf_SRC))))))
+lkcc_OBJ=$(filter %.o, \
+ $(patsubst %.c,%.o, \
+ $(patsubst %.y,%.tab.o, \
+ $(patsubst %.l,lex.%.o, \
+ $(lkcc_SRC)))))
+OBJ=$(conf_OBJ) $(mconf_OBJ) $(qconf_OBJ) $(lkcc_OBJ)
+
+ifeq ($(MOC),)
+all: lkcc conf mconf
+else
+all: lkcc conf mconf qconf libkconfig.so
+endif
+
+lex.help.c: help.l
+lex.help.o: lex.help.c cml1.h expr.h
+lex.cml1.c: cml1.l
+lex.cml1.o: lex.cml1.c cml1.tab.h cml1.h expr.h
+cml1.tab.c: cml1.y
+cml1.tab.h: cml1.y
+cml1.tab.o: cml1.tab.c cml1.h expr.h
+expr1.o: expr1.c expr.h
+
+lkc_deps := lkc.h lkc_proto.h lkc_defs.h expr.h
+
+zconf.tab.c: zconf.y
+zconf.tab.h: zconf.y
+lex.zconf.c: zconf.l
+zconf.tab.o: zconf.tab.c lex.zconf.c confdata.c expr.c symbol.c menu.c $(lkc_deps)
+#lex.zconf.o: lex.zconf.c zconf.tab.h $(lkc_deps)
+#confdata.o: confdata.c $(lkc_deps)
+#expr.o: expr.c $(lkc_deps)
+#symbol.o: symbol.c $(lkc_deps)
+#menu.o: menu.c $(lkc_deps)
+kconfig_load.o: kconfig_load.c $(lkc_deps)
+conf.o: conf.c $(lkc_deps)
+mconf.o: mconf.c $(lkc_deps)
+qconf.moc: qconf.h
+qconf.o: qconf.cc qconf.moc images.c $(lkc_deps)
+
+mconf: $(mconf_OBJ)
+ $(CC) $(LDFLAGS) $^ -o $@
+
+conf: $(conf_OBJ)
+ $(CC) $(LDFLAGS) $^ -o $@
+
+ifeq ($(MOC),)
+qconf:
+ @echo Unable to find the QT installation. Please make sure that the
+ @echo QT development package is correctly installed and the QTDIR
+ @echo environment variable is set to the correct location.
+ @false
+else
+qconf: $(qconf_OBJ)
+ $(CXX) $(LXXFLAGS) $^ -lqt -o $@
+endif
+
+lkcc: $(lkcc_OBJ)
+ $(CC) $(LDFLAGS) $^ -o $@
+
+libkconfig.so: $(parse_OBJ)
+ $(CC) -shared $^ -o $@
+
+lkc_defs.h: lkc_proto.h
+ sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
+
+clean:
+ rm -f $(OBJ) lkcc conf qconf mconf *.moc lex.* *.tab.? *.output
+
+tgz:
+ mkdir tmp
+ mkdir tmp/lkc-$(VERSION)
+ cp -ra Makefile $(sort $(SRC) $(HDR) $(OTHER) $(INST)) tmp/lkc-$(VERSION)
+ tar -cpvz -C tmp -f lkc-$(VERSION).tar.gz lkc-$(VERSION)
+ rm -rf tmp
+
+%.tab.c %.tab.h: %.y
+ $(YACC) $(YFLAGS) -b $* -p $* $<
+
+lex.%.c: %.l
+ $(LEX) $(LFLAGS) -P$* $<
+
+%.moc: %.h
+ $(QTDIR)/bin/moc -i $< -o $@
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o: %.cc
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+ifdef KERNELSRC
+install: lkcc $(INSTGEN)
+ set -x; mkdir $(KERNELSRC)/scripts/kconfig; \
+ cp $(sort $(INST)) $(KERNELSRC)/scripts/kconfig; \
+ for f in $(INSTGEN); do cp $$f $(KERNELSRC)/scripts/kconfig/$${f}_shipped; done; \
+ cp Makefile.kernel $(KERNELSRC)/scripts/kconfig/Makefile; \
+ LKCSRC=$$PWD; export LKCSRC; \
+ cd $(KERNELSRC); \
+ patch -p0 -N < $$LKCSRC/prepare-all.diff; \
+ sh $$LKCSRC/convert-all; \
+ patch -p0 -N < $$LKCSRC/fixup-all.diff
+
+# cp Makefile $(KERNELSRC)/scripts/kconfig/Makefile; \
+
+uninstall:
+ patch -p0 -N -R -d $(KERNELSRC) < prepare-all.diff; \
+ cd $(KERNELSRC); \
+ find -name "Kconfig*" | xargs rm; \
+ rm -rf scripts/kconfig log.*
+else
+install:
+ @echo "Please use KERNELSRC=<path/to/linux-kernel> to install"
+endif
+
+ruby: .ruby libkconfig.so .ruby/kconfig.so
+
+.ruby:
+ mkdir .ruby
+
+.ruby/kconfig_wrap.c: kconfig.i kconfig_load.c expr.h lkc_proto.h
+ swig -ruby -o $@ $<
+
+.ruby/Makefile: extconf.rb
+ cd .ruby; ruby ../extconf.rb
+
+.ruby/kconfig.so: .ruby/kconfig_wrap.c .ruby/Makefile
+ make -C .ruby
+
+.PHONY: all tgz clean ruby
diff --git a/scripts/kconfig/Makefile.kernel b/scripts/kconfig/Makefile.kernel
new file mode 100644
index 0000000..beb4dcf
--- a/dev/null
+++ b/scripts/kconfig/Makefile.kernel
@@ -0,0 +1,85 @@
+#################
+#
+# Shared Makefile for the various lkc executables:
+# conf: Used for defconfig, oldconfig and related targets
+# mconf: Used for the mconfig target.
+# Utilizes the lxdialog package
+# qconf: Used for the xconfig target
+# Based on QT which needs to be installed to compile it
+#
+
+# object files used by all lkc flavours
+libkconfig-objs := zconf.tab.o
+
+host-progs := conf mconf qconf
+conf-objs := conf.o libkconfig.so
+mconf-objs := mconf.o libkconfig.so
+
+qconf-objs := kconfig_load.o
+qconf-cxxobjs := qconf.o
+
+clean-files := libkconfig.so lkc_defs.h qconf.moc .tmp_qtcheck \
+ zconf.tab.c zconf.tab.h lex.zconf.c
+
+include $(TOPDIR)/Rules.make
+
+# QT needs some extra effort...
+ifndef QTDIR
+QTDIR := /usr/share/qt
+endif
+
+# Executable to generate the .moc file
+MOC=$(wildcard $(QTDIR)/bin/moc)
+
+# generated files seem to need this to find local include files
+HOSTCFLAGS_lex.zconf.o := -I$(src)
+HOSTCFLAGS_zconf.tab.o := -I$(src)
+
+HOSTLOADLIBES_qconf := -L$(QTDIR)/lib -Wl,-rpath,$(QTDIR)/lib -lqt -ldl
+HOSTCXXFLAGS_qconf.o := -I$(QTDIR)/include
+
+$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o: $(obj)/zconf.tab.h
+
+$(obj)/qconf.o: $(obj)/.tmp_qtcheck
+
+$(obj)/.tmp_qtcheck:
+ifeq ($(MOC),)
+ @echo Unable to find the QT installation. Please make sure that the
+ @echo QT development package is correctly installed and the QTDIR
+ @echo environment variable is set to the correct location.
+ @false
+else
+ @touch $@
+endif
+
+$(obj)/zconf.tab.o: $(obj)/lex.zconf.c
+
+$(obj)/kconfig_load.o: $(obj)/lkc_defs.h
+
+$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h
+
+$(obj)/%.moc: $(src)/%.h
+ $(MOC) -i $< -o $@
+
+$(obj)/lkc_defs.h: $(src)/lkc_proto.h
+ sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/'
+
+
+###
+# The following requires flex/bison
+# 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: $(obj)/zconf.y
+$(obj)/zconf.tab.h: $(obj)/zconf.tab.c
+
+%.tab.c: %.y
+ bison -t -d -v -b $* -p $(notdir $*) $<
+
+lex.%.c: %.l
+ flex -P$(notdir $*) -o$@ $<
+
+endif
diff --git a/scripts/kconfig/README b/scripts/kconfig/README
new file mode 100644
index 0000000..6be26e4
--- a/dev/null
+++ b/scripts/kconfig/README
@@ -0,0 +1,17 @@
+This package requires flex, bison and qt to compile (actually it's
+possible without qt, but you'll miss most of the fun :) ).
+On most systems a simple 'make' should be enough, if you have qt
+installed in unusual location either set the QTDIR environment variable
+or issue 'make QTDIR=<path>'.
+
+'make install KERNELSRC=<path/to/linux/kernel> should be enough to
+install the package. The path must point to recent kernel sources,
+which will be converted to use this package. With 'make uninstall
+KERNELSRC=...' the package can be removed from the kernel again.
+
+lkc include a SWIG interface file. 'make ruby' builds a extension
+library for ruby in the .ruby dir.
+
+Have fun, Roman
+
+Please send all your comments to zippel@linux-m68k.org
diff --git a/scripts/kconfig/cml1.h b/scripts/kconfig/cml1.h
new file mode 100644
index 0000000..4a6d977
--- a/dev/null
+++ b/scripts/kconfig/cml1.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef CML1_H
+#define CML1_H
+
+#include <stdio.h>
+#ifndef YYBISON
+#include "cml1.tab.h"
+#endif
+#define CML1
+#define WORD T_WORD
+#define prop stmt
+#define property statement
+#include "expr.h"
+
+struct symbol *lookup_symbol(char *name, int type);
+struct symbol *lookup_symbol_ref(char *name);
+
+void new_string(void);
+void append_string(const char *str, int size);
+extern char *text;
+
+extern int cml1debug;
+extern int cml1parse(void);
+extern void helplex(char *help);
+
+extern void scan_init(char *name);
+extern void print_files(FILE *out, const char *name);
+extern void optimize_config(void);
+
+void fprint_expr(FILE *out, struct expr *e, int prevtoken);
+
+#endif /* CML1_H */
diff --git a/scripts/kconfig/cml1.l b/scripts/kconfig/cml1.l
new file mode 100644
index 0000000..d6c33a0
--- a/dev/null
+++ b/scripts/kconfig/cml1.l
@@ -0,0 +1,213 @@
+%option nounput backup nostdinit noyywrap full ecs
+%option 8bit backup nodefault perf-report perf-report
+%x STRING
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "cml1.h"
+
+char *text;
+static char *text_ptr;
+static int text_size, text_asize;
+
+struct buffer {
+ struct buffer *parent;
+ YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+int lineno(void)
+{
+ if (current_buf)
+ return current_file->lineno;
+ else
+ return 0;
+}
+
+void scan_init(char *file)
+{
+ struct buffer *buf = malloc(sizeof(*buf));
+ memset(buf, 0, sizeof(*buf));
+
+ yyin = fopen(file, "r");
+ if (!yyin) {
+ printf("can't find file %s\n", file);
+ exit(1);
+ }
+ current_buf = buf;
+
+ current_file = lookup_file(file);
+ current_file->lineno = 0;
+ current_file->flags = FILE_BUSY;
+}
+
+void scan_nextfile(char *name)
+{
+ struct file *file = lookup_file(name);
+ struct buffer *buf = malloc(sizeof(*buf));
+ memset(buf, 0, sizeof(*buf));
+
+ current_buf->state = YY_CURRENT_BUFFER;
+ yyin = fopen(name, "r");
+ if (!yyin) {
+ printf("can't find file %s\n", name);
+ exit(1);
+ }
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+ buf->parent = current_buf;
+ current_buf = buf;
+
+ if (file->flags & FILE_BUSY) {
+ printf("recursive scan (%s)?\n", name);
+ exit(1);
+ }
+ file->flags |= FILE_BUSY;
+ file->lineno = 0;
+ file->parent = current_file;
+ current_file = file;
+}
+
+#define START_STRSIZE 16
+
+void new_string(void)
+{
+ text = malloc(START_STRSIZE);
+ text_asize = START_STRSIZE;
+ text_ptr = text;
+ text_size = 0;
+ *text_ptr = 0;
+}
+
+void append_string(const char *str, int size)
+{
+ int new_size = text_size + size + 1;
+ if (new_size > text_asize) {
+ text = realloc(text, new_size);
+ text_asize = new_size;
+ text_ptr = text + text_size;
+ }
+ memcpy(text_ptr, str, size);
+ text_ptr += size;
+ text_size += size;
+ *text_ptr = 0;
+}
+
+void alloc_string(const char *str, int size)
+{
+ text = malloc(size + 1);
+ memcpy(text, str, size);
+ text[size] = 0;
+}
+
+%}
+%%
+ int str = 0;
+
+\"|\' {
+ str = yytext[0];
+ new_string();
+ BEGIN(STRING);
+}
+<STRING>{
+ [^'"\n\\]+ {
+ append_string(yytext, yyleng);
+ }
+ \'|\" {
+ if (str == yytext[0]) {
+ BEGIN(INITIAL);
+ cml1lval.string = text;
+ //printf("s:%s", text);
+ return str == '"' ? T_WORD_DQUOTE : T_WORD_QUOTE;
+ } else
+ append_string(yytext, 1);
+ }
+ \\[ \t]*\n append_string(yytext+yyleng-1, 1); current_file->lineno++;
+ \\[ \t]* append_string(yytext+1, yyleng-1);
+ \\. append_string(yytext+1, 1);
+ \n {
+ printf(":%d: open string!\n", current_file->lineno+1);
+ exit(0);
+ }
+ <<EOF>> {
+ printf(":%d: open string!\n", current_file->lineno+1);
+ exit(0);
+ }
+}
+mainmenu_name[ \t] return T_MAINMENU_NAME;
+mainmenu_option[ \t] return T_MAINMENU_OPTION;
+next_comment/[ \t\n] return T_NEXT_COMMENT;
+endmenu/[ \t\n] return T_ENDMENU;
+comment[ \t] return T_COMMENT;
+bool[ \t] return T_BOOL;
+hex[ \t] return T_HEX;
+int[ \t] return T_INT;
+string[ \t] return T_STRING;
+tristate[ \t] return T_TRISTATE;
+define_bool[ \t] return T_DEFINE_BOOL;
+define_hex[ \t] return T_DEFINE_HEX;
+define_int[ \t] return T_DEFINE_INT;
+define_string[ \t] return T_DEFINE_STRING;
+define_tristate[ \t] return T_DEFINE_TRISTATE;
+dep_bool[ \t] return T_DEP_BOOL;
+dep_mbool[ \t] return T_DEP_MBOOL;
+dep_tristate[ \t] return T_DEP_TRISTATE;
+unset[ \t] return T_UNSET;
+choice[ \t] return T_CHOICE;
+source[ \t] return T_SOURCE;
+if[ \t] return T_IF;
+else/[ \t\n] return T_ELSE;
+fi/[ \t\n] return T_FI;
+then/[ \t\n] return T_THEN;
+\[ return '[';
+\] return ']';
+; return ';';
+!= return T_UNEQUAL;
+= return '=';
+! return '!';
+-a return T_AND;
+-o return T_OR;
+#[^\n]* {
+ /* comment */
+ current_file->lineno++;
+ alloc_string(yytext, yyleng);
+ cml1lval.string = text;
+ return T_SH_COMMENT;
+}
+[ \t]+ /* space */
+\\\n current_file->lineno++; /* ignore */
+\n {
+ current_file->lineno++;
+ return '\n';
+}
+[[:alnum:]$/][[:graph:]]* {
+ alloc_string(yytext, yyleng);
+ cml1lval.string = text;
+ //printf("w:%s", text);
+ return T_WORD;
+}
+. {
+ printf("%s:%d: invalid character 0x%x(%c)\n", current_file->name, current_file->lineno+1, yytext[0], yytext[0]);
+ exit(1);
+}
+<<EOF>> {
+ if (current_buf->parent) {
+ struct buffer *buf = current_buf;
+ current_buf = buf->parent;
+ current_file->flags |= FILE_SCANNED;
+ current_file->flags &= ~FILE_BUSY;
+ current_file = current_file->parent;
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(current_buf->state);
+ free(buf);
+ } else
+ yyterminate();
+}
+%%
diff --git a/scripts/kconfig/cml1.y b/scripts/kconfig/cml1.y
new file mode 100644
index 0000000..42c4216
--- a/dev/null
+++ b/scripts/kconfig/cml1.y
@@ -0,0 +1,2482 @@
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define PRINTD 0x0001
+#define DEBUG_PARSE 0x0002
+#define DEBUG_OPT 0x0004
+#define DEBUG_OPT1 0x0008
+#define DEBUG_OPT2 0x0010
+#define DEBUG_OPT3 0x0020
+#define DEBUG_OPT4 0x0040
+#define DEBUG_OPT5 0x0080
+#define DEBUG_DEP 0x0100
+
+int cdebug = PRINTD;//DEBUG_OPT|-1;
+
+#define YYERROR_VERBOSE
+%}
+
+%union
+{
+ char *string;
+ struct expr *expr;
+ struct symbol *symbol;
+ struct statement *stmt;
+}
+
+%token <string> T_WORD
+%token <string> T_WORD_QUOTE
+%token <string> T_WORD_DQUOTE
+%token T_MAINMENU_NAME
+%token T_MAINMENU_OPTION
+%token T_NEXT_COMMENT
+%token T_ENDMENU
+%token T_COMMENT
+%token T_BOOL
+%token T_HEX
+%token T_INT
+%token T_STRING
+%token T_TRISTATE
+%token T_DEFINE_BOOL
+%token T_DEFINE_HEX
+%token T_DEFINE_INT
+%token T_DEFINE_STRING
+%token T_DEFINE_TRISTATE
+%token T_DEP_BOOL
+%token T_DEP_MBOOL
+%token T_DEP_TRISTATE
+%token T_UNSET
+%token T_CHOICE
+%token T_SOURCE
+%token T_IF
+%token T_ELSE
+%token T_FI
+%token T_THEN
+%token T_UNEQUAL
+%token <string> T_SH_COMMENT
+
+%type <string> prompt
+%type <string> word
+%type <string> menu_comment
+%type <symbol> symbol
+%type <symbol> symbol_ref
+%type <symbol> symbol_other
+%type <stmt> statement
+%type <expr> expr
+%type <expr> dep
+%type <expr> deps
+%type <stmt> comment_opt
+
+%left T_OR
+%left T_AND
+%nonassoc '!'
+%left '=' T_UNEQUAL
+
+%{
+#include "cml1.h"
+
+extern int cml1lex(void);
+static void cml1error(const char *err);
+extern int lineno(void);
+extern void scan_nextfile(char *file);
+
+struct statement *create_stmt(int token);
+struct statement *add_stmt(struct symbol *sym, int token,
+ char *prompt, struct symbol *def);
+void print_expr(int mask, struct expr *e, int prevtoken);
+void print_dep(int mask, struct statement *stmt);
+
+void eliminate_eq(int token, struct expr **ep1, struct expr **ep2);
+static inline int expr_is_yes(struct expr *e);
+static inline int expr_is_no(struct expr *e);
+struct expr *trans_dep_bool(struct expr *e);
+struct expr *trans_bool_expr(struct expr *e);
+struct expr *fixup_expr(struct expr *e);
+struct expr *trans_expr(struct expr *e);
+void extract_eq(int token, struct expr **ep, struct expr **ep1, struct expr **ep2);
+struct expr *extract_eq_and(struct expr **ep1, struct expr **ep2);
+struct expr *extract_eq_or(struct expr **ep1, struct expr **ep2);
+struct expr *optimize_expr_or(struct expr *e);
+struct expr *eliminate_dups(struct expr *e);
+struct expr *eliminate_yn(struct expr *e);
+void eliminate_dep(struct symbol *sym, struct expr *dep);
+int contains_expr(struct expr *dep, struct expr *e);
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+#define fprintd(f, mask, fmt...) if (cdebug & (mask)) fprintf(f, fmt)
+
+static struct expr *if_expr;
+static struct menu root_menu;
+static struct menu *current_menu = &root_menu;
+
+struct symbol *symbol_hash[257];
+%}
+%%
+input: line
+;
+
+line: /* empty */
+;
+
+line: line statement
+;
+
+line: line '\n'
+;
+
+statement: T_SH_COMMENT
+{
+ $$ = create_stmt(T_SH_COMMENT);
+ $$->text = $1;
+};
+
+statement: T_MAINMENU_NAME prompt '\n'
+{
+ $$ = create_stmt(T_MAINMENU_NAME);
+ $$->text = $2;
+ printd(DEBUG_PARSE, "%d:mainmenu_name: %s\n", lineno(), $2);
+};
+
+statement: T_COMMENT prompt '\n'
+{
+ $$ = create_stmt(T_COMMENT);
+ $$->text = $2;
+ $$->dep = trans_expr(fixup_expr(expr_copy(if_expr)));
+ printd(DEBUG_PARSE, "%d:comment: %s\n", lineno(), $2);
+};
+
+statement: T_BOOL prompt symbol dep '\n'
+{
+ $$ = add_stmt($3, T_BOOL, $2, NULL);
+ printd(DEBUG_PARSE, "%d:bool: %s %s\n", lineno(), $2, $3->name);
+ if ($4) {
+ printf("%s:%d: warning ignoring dependencies\n", current_file->name, current_file->lineno);
+ expr_free($4);
+ }
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_HEX prompt symbol symbol_other '\n'
+{
+ $$ = add_stmt($3, T_HEX, $2, NULL);
+ add_stmt($3, T_DEFINE_HEX, NULL, $4);
+ printd(DEBUG_PARSE, "%d:hex: %s %s %s\n", lineno(), $2, $3->name, $4->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_INT prompt symbol symbol_other '\n'
+{
+ $$ = add_stmt($3, T_INT, $2, NULL);
+ add_stmt($3, T_DEFINE_INT, NULL, $4);
+ printd(DEBUG_PARSE, "%d:int: %s %s %s\n", lineno(), $2, $3->name, $4->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_STRING prompt symbol symbol_other '\n'
+{
+ $$ = add_stmt($3, T_STRING, $2, NULL);
+ add_stmt($3, T_DEFINE_STRING, NULL, $4);
+ printd(DEBUG_PARSE, "%d:string: %s %s %s\n", lineno(), $2, $3->name, $4->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_TRISTATE prompt symbol dep '\n'
+{
+ $$ = add_stmt($3, T_TRISTATE, $2, NULL);
+ printd(DEBUG_PARSE, "%d:tristate: %s %s\n", lineno(), $2, $3->name);
+ if ($4) {
+ printf("%s:%d: warning ignoring dependencies\n", current_file->name, current_file->lineno);
+ expr_free($4);
+ }
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_DEFINE_BOOL symbol symbol_ref comment_opt '\n'
+{
+ $$ = add_stmt($2, T_DEFINE_BOOL, NULL, $3);
+ printd(DEBUG_PARSE, "%d:define_bool: %s %s\n", lineno(), $2->name, $3->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_DEFINE_HEX symbol symbol_other '\n'
+{
+ $$ = add_stmt($2, T_DEFINE_HEX, NULL, $3);
+ printd(DEBUG_PARSE, "%d:define_hex: %s %s\n", lineno(), $2->name, $3->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_DEFINE_INT symbol symbol_other comment_opt '\n'
+{
+ $$ = add_stmt($2, T_DEFINE_INT, NULL, $3);
+ printd(DEBUG_PARSE, "%d:define_int: %s %s\n", lineno(), $2->name, $3->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_DEFINE_STRING symbol symbol_other '\n'
+{
+ $$ = add_stmt($2, T_DEFINE_STRING, NULL, $3);
+ printd(DEBUG_PARSE, "%d:define_string: %s %s\n", lineno(), $2->name, $3->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_DEFINE_TRISTATE symbol symbol_ref '\n'
+{
+ $$ = add_stmt($2, T_DEFINE_TRISTATE, NULL, $3);
+ printd(DEBUG_PARSE, "%d:define_tristate: %s %s\n", lineno(), $2->name, $3->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_DEP_BOOL prompt symbol dep '\n'
+{
+ $$ = add_stmt($3, T_DEP_BOOL, $2, NULL);
+ if (!($$->dep2 = $4))
+ printf("%s:%d: warning dep_bool without dependencies\n", current_file->name, current_file->lineno);
+ printd(DEBUG_PARSE, "%d:dep_bool: %s %s\n", lineno(), $2, $3->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_DEP_MBOOL prompt symbol dep '\n'
+{
+ $$ = add_stmt($3, T_DEP_MBOOL, $2, NULL);
+ if (!($$->dep2 = $4))
+ printf("%s:%d: warning dep_mbool without dependencies\n", current_file->name, current_file->lineno);
+ printd(DEBUG_PARSE, "%d:dep_mbool: %s %s\n", lineno(), $2, $3->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_DEP_TRISTATE prompt symbol dep '\n'
+{
+ $$ = add_stmt($3, T_DEP_TRISTATE, $2, NULL);
+ if (!($$->dep2 = $4))
+ printf("%s:%d: warning dep_tristate without dependencies\n", current_file->name, current_file->lineno);
+ printd(DEBUG_PARSE, "%d:dep_tristate: %s %s\n", lineno(), $2, $3->name);
+ print_dep(DEBUG_PARSE, $$);
+};
+
+statement: T_UNSET deps '\n'
+{
+ //add_stmt($2, T_UNSET, NULL, NULL);
+ printd(DEBUG_PARSE, "%d:unset\n", lineno());
+ print_dep(DEBUG_PARSE, NULL);
+};
+
+statement: T_CHOICE prompt word word '\n'
+{
+ struct statement *stmt;
+ struct symbol *sym;
+ struct expr **depp;
+ char *ptr, *name, *def, end;
+
+ printd(DEBUG_PARSE, "%d:choice: %s %s %s\n", lineno(), $2, $3, $4);
+ $$ = create_stmt('^');
+ $$->text = $2;
+ ptr = $3;
+ depp = &$$->dep;
+ do {
+ while (isspace(*ptr))
+ ptr++;
+ if (!*ptr)
+ break;
+ def = ptr;
+ while (*ptr && !isspace(*ptr))
+ ptr++;
+ *ptr++ = 0;
+ //def = lookup_symbol(name, SYMBOL_OTHER);
+ while (isspace(*ptr))
+ ptr++;
+ if (!*ptr)
+ break;
+ name = ptr;
+ while (*ptr && !isspace(*ptr))
+ ptr++;
+ end = *ptr;
+ *ptr++ = 0;
+ sym = lookup_symbol(name, SYMBOL_BOOLEAN);
+ if (!$$->def) {
+ if (!strncmp(def, $4, strlen($4)))
+ $$->def = sym;
+ }
+ sym->flags |= SYMBOL_CHOICE;
+ stmt = add_stmt(sym, T_BOOL, strdup(def), NULL);
+ if (!stmt->next) {
+ stmt->next = $$;
+ } else
+ printf("warning: unexpected stmt for choice symbol %s\n", sym->name);
+ *depp = expr_alloc_one('^', NULL);
+ (*depp)->right.sym = sym;
+ depp = &(*depp)->left.expr;
+ printd(DEBUG_PARSE, "added symbol: %s %s\n", sym->name, stmt->text);
+ } while (end);
+ print_dep(DEBUG_PARSE, NULL);
+};
+
+statement: T_IF '[' expr ']' semi_or_nl T_THEN comment_opt '\n'
+{
+ struct expr *e;
+ printd(DEBUG_PARSE, "%d:if ", lineno());
+ print_expr(DEBUG_PARSE, $3, 0);
+ printd(DEBUG_PARSE, "\n");
+ e = expr_alloc_one(T_IF, $3);
+ e->right.expr = if_expr;
+ if_expr = e;
+ $$ = NULL;
+};
+
+semi_or_nl: ';' | '\n'
+;
+
+statement: T_ELSE comment_opt '\n'
+{
+ printd(DEBUG_PARSE, "%d:else\n", lineno());
+ if_expr->token = T_ELSE;
+ $$ = NULL;
+};
+
+statement: T_FI comment_opt '\n'
+{
+ struct expr *e;
+ printd(DEBUG_PARSE, "%d:fi\n", lineno());
+ e = if_expr;
+ if (e) {
+ if_expr = e->right.expr;
+ expr_free(e->left.expr);
+ free(e);
+ } else
+ YYABORT;
+ $$ = NULL;
+};
+
+statement: T_MAINMENU_OPTION T_NEXT_COMMENT menu_comment '\n'
+{
+ printd(DEBUG_PARSE, "%d:mainmenu_option: %s\n", lineno(), $3);
+ $$ = create_stmt(T_MAINMENU_OPTION);
+ $$->text = $3;
+ $$->dep = trans_expr(fixup_expr(expr_copy(if_expr)));
+ current_menu = $$->menu;
+};
+
+menu_comment: '\n' T_COMMENT prompt { $$ = $3; }
+ | '\n' menu_comment { $$ = $2; }
+;
+
+statement: T_ENDMENU '\n'
+{
+ $$ = create_stmt(T_ENDMENU);
+ printd(DEBUG_PARSE, "%d:endmenu\n", lineno());
+ current_menu = current_menu->parent;
+};
+
+statement: T_SOURCE word '\n'
+{
+ static char helppath[256];
+ char *p;
+ $$ = create_stmt(T_SOURCE);
+ $$->text = $2;
+ printd(DEBUG_PARSE, "%d:source: %s\n", lineno(), $2);
+ strcpy(helppath, $2);
+ p = strrchr(helppath, '.');
+ if (p) {
+ strcpy(p, ".help");
+ helplex(helppath);
+ }
+ scan_nextfile($2);
+};
+
+comment_opt: /* empty */ { $$ = NULL; }
+ | T_SH_COMMENT
+{
+ $$ = create_stmt(T_SH_COMMENT);
+ $$->text = $1;
+};
+
+prompt: T_WORD_QUOTE
+ | T_WORD_DQUOTE
+;
+
+word: T_WORD
+ | T_WORD_QUOTE
+ | T_WORD_DQUOTE
+;
+
+dep: /* empty */ { $$ = NULL; }
+ | deps { $$ = $1; }
+;
+
+deps: symbol_ref { $$ = expr_alloc_symbol($1); }
+ | deps symbol_ref { $$ = expr_alloc_two('&', $1, expr_alloc_symbol($2)); }
+;
+
+symbol: T_WORD { $$ = lookup_symbol($1, SYMBOL_UNKNOWN); free($1); }
+;
+
+expr: symbol_ref '=' symbol_ref { $$ = expr_alloc_comp('=', $1, $3); }
+ | symbol_ref T_UNEQUAL symbol_ref { $$ = expr_alloc_comp(T_UNEQUAL, $1, $3); }
+ | '!' expr { $$ = expr_alloc_one('!', $2); }
+ | expr T_AND expr { $$ = expr_alloc_two(T_AND, $1, $3); }
+ | expr T_OR expr { $$ = expr_alloc_two(T_OR, $1, $3); }
+;
+
+symbol_ref: T_WORD { $$ = lookup_symbol_ref($1); free($1); }
+ | T_WORD_QUOTE { $$ = lookup_symbol_ref($1); free($1); }
+ | T_WORD_DQUOTE { $$ = lookup_symbol_ref($1); free($1); }
+;
+
+symbol_other: T_WORD { $$ = lookup_symbol($1, SYMBOL_OTHER); free($1); }
+ | T_WORD_QUOTE { $$ = lookup_symbol($1, SYMBOL_OTHER); free($1); }
+ | T_WORD_DQUOTE { $$ = lookup_symbol($1, SYMBOL_OTHER); free($1); }
+;
+
+%%
+
+static void yyerror(const char *err)
+{
+ printf("%s:%d: %s\n", current_file->name, current_file->lineno + 1, err);
+ exit(1);
+}
+
+void print_dep(int mask, struct statement *stmt)
+{
+ printd(mask, "dep: ");
+ if (stmt) {
+ if (stmt->dep2)
+ printd(mask, "[");
+ print_expr(mask, stmt->dep, 0);
+ if (stmt->dep2) {
+ printd(mask, " & ");
+ print_expr(mask, stmt->dep2, 0);
+ printd(mask, "]");
+ }
+ } else
+ print_expr(mask, if_expr, 0);
+ printd(mask, "\n");
+}
+
+struct symbol *lookup_symbol(char *name, int type)
+{
+ struct symbol *symbol;
+ char *ptr;
+ int hash = 0;
+
+ //printf("lookup: %s -> ", name);
+ if (type != SYMBOL_OTHER && !strncmp(name, "CONFIG_", 7)) {
+ name += 7;
+ } else {
+ //printf("Warning: Invalid symbol name '%s'\n", name);
+ type = SYMBOL_OTHER;
+ }
+
+ for (ptr = name; *ptr; ptr++)
+ hash += *ptr;
+
+ for (symbol = symbol_hash[hash&255]; symbol; symbol = symbol->next) {
+ if (!strcmp(symbol->name, name)) {
+ //printf("h:%p\n", symbol);
+ if (type == SYMBOL_BOOLEAN)
+ symbol->type = SYMBOL_BOOLEAN;
+ return symbol;
+ }
+ }
+
+ symbol = malloc(sizeof(*symbol));
+ memset(symbol, 0, sizeof(*symbol));
+ symbol->name = strdup(name);
+ symbol->type = type;
+
+ symbol->next = symbol_hash[hash&255];
+ symbol_hash[hash&255] = symbol;
+
+ //printf("n:%p\n", symbol);
+ return symbol;
+}
+
+struct symbol *lookup_symbol_ref(char *name)
+{
+ if (name[0] == 'y' && !name[1])
+ return &symbol_yes;
+ if (name[0] == 'm' && !name[1])
+ return &symbol_mod;
+ if (name[0] == 'n' && !name[1])
+ return &symbol_no;
+ if (name[0] == '$')
+ return lookup_symbol(name+1, SYMBOL_UNKNOWN);
+ return lookup_symbol(name, SYMBOL_OTHER);
+}
+
+struct statement *create_stmt(int token)
+{
+ struct statement *stmt;
+ struct menu *menu, **menup;
+
+ stmt = malloc(sizeof(*stmt));
+ memset(stmt, 0, sizeof(*stmt));
+ stmt->token = token;
+ stmt->file = current_file;
+ stmt->lineno = lineno();
+
+ if (!current_file->stmt)
+ current_file->stmt = stmt;
+ if (current_file->last_stmt)
+ current_file->last_stmt->next_pos = stmt;
+ current_file->last_stmt = stmt;
+
+ menu = malloc(sizeof(*menu));
+ memset(menu, 0, sizeof(*menu));
+ menu->prompt = stmt;
+ menu->parent = current_menu;
+ for (menup = &current_menu->list; *menup; menup = &(*menup)->next)
+ ;
+ *menup = menu;
+
+ stmt->menu = menu;
+
+ return stmt;
+}
+
+struct statement *add_stmt(struct symbol *sym, int token, char *prompt, struct symbol *def)
+{
+ struct statement *stmt = create_stmt(token);
+
+ stmt->dep = expr_copy(if_expr);
+ stmt->text = prompt;
+ stmt->def = def;
+
+ stmt->sym = sym;
+ stmt->next = sym->stmt;
+ sym->stmt = stmt;
+
+ return stmt;
+}
+
+void print_quoted_string(FILE *out, const char *str)
+{
+ const char *p;
+ int len;
+
+ putc('"', out);
+ while ((p = strchr(str, '"'))) {
+ len = p - str;
+ if (len)
+ fprintf(out, "%.*s", len, str);
+ fputs("\\\"", out);
+ str += len + 1;
+ }
+ fputs(str, out);
+ putc('"', out);
+}
+
+const char *skip_space(const char *p)
+{
+ while (*p == ' ')
+ p++;
+ return p;
+}
+
+void do_print_symbol(FILE *out, struct symbol *sym)
+{
+ struct statement *zero_stmt, *stmt, *stmt2;
+ struct expr *dep, *dep2;
+
+#define VALID_STMT(s) (s->token && s->token != '^' && s->menu && s->menu->parent == current_menu)
+
+ dep = NULL;
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ if (!VALID_STMT(stmt))
+ continue;
+ if (!dep) {
+ if (!stmt->dep)
+ break;
+ dep = stmt->dep;
+ stmt->dep = NULL;
+ } else {
+ struct expr *e = dep;
+ if (stmt->dep) {
+ dep = extract_eq_and(&e, &stmt->dep);
+ if (expr_is_yes(e)) {
+ expr_free(e);
+ continue;
+ }
+ } else
+ dep = NULL;
+ for (stmt2 = sym->stmt; stmt != stmt2; stmt2 = stmt2->next) {
+ if (!VALID_STMT(stmt2))
+ continue;
+ stmt2->dep = !stmt2->dep ? expr_copy(e) :
+ expr_alloc_two(T_AND, expr_copy(e), stmt2->dep);
+ }
+ expr_free(e);
+ if (!dep)
+ break;
+ }
+ }
+
+ zero_stmt = NULL;
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ if (!stmt->token)
+ zero_stmt = stmt;
+ if (VALID_STMT(stmt))
+ break;
+ }
+ if (!stmt) {
+ if (sym->flags & SYMBOL_PRINTED)
+ return;
+ if (!zero_stmt)
+ return;
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ if (stmt->token)
+ return;
+ }
+ stmt = zero_stmt;
+ }
+
+ fprintf(out, "config %s\n", sym->name);
+
+ switch (sym->type) {
+ case SYMBOL_BOOLEAN: fputs("\tbool", out); break;
+ case SYMBOL_TRISTATE: fputs("\ttristate", out); break;
+ case SYMBOL_INT: fputs("\tint", out); break;
+ case SYMBOL_HEX: fputs("\thex", out); break;
+ case SYMBOL_STRING: fputs("\tstring", out); break;
+ default: fputs("\t#unknown type?", out); break;
+ }
+
+ if (stmt->text) {
+ fputc(' ', out);
+ print_quoted_string(out, skip_space(stmt->text));
+ if (!expr_is_yes(stmt->dep)) {
+ fputs(" if ", out);
+ fprint_expr(out, stmt->dep, 0);
+ }
+ stmt->menu = NULL;
+ stmt = stmt->next;
+ }
+ fputc('\n', out);
+
+ if (sym->dep || dep) {
+ dep = expr_alloc_and(expr_copy(sym->dep), dep);
+ dep = eliminate_yn(dep);
+ if (current_menu->prompt && current_menu->prompt->dep) {
+ dep2 = expr_copy(current_menu->prompt->dep);
+ switch (sym->type) {
+ case SYMBOL_BOOLEAN: case SYMBOL_INT: case SYMBOL_HEX: case SYMBOL_STRING:
+ dep2 = trans_bool_expr(dep2);
+ break;
+ }
+ eliminate_eq(T_AND, &dep, &dep2);
+ dep = eliminate_yn(dep);
+#if 0
+ dep2 = eliminate_yn(dep2);
+ if (!expr_is_yes(dep2)) {
+ printf("Warning, I'm still confused (%s)?\n", sym->name);
+ print_expr(PRINTD, dep, 0);
+ printf(" - ");
+ print_expr(PRINTD, dep2, 0);
+ printf("\n");
+ }
+#endif
+ expr_free(dep2);
+ }
+ if (!expr_is_yes(dep)) {
+ fputs("\tdepends on ", out);
+ fprint_expr(out, eliminate_yn(dep), 0);
+ fputc('\n', out);
+ }
+ }
+ for (; stmt; stmt = stmt->next) {
+ if (!VALID_STMT(stmt))
+ continue;
+ if (stmt->text) {
+ ;
+ } else if (stmt->def) {
+ if (sym->flags & SYMBOL_CHOICE)
+ printf("Choice value %s has default value!\n", sym->name);
+ fputs( "\tdefault ", out);
+ switch (sym->type) {
+ case SYMBOL_BOOLEAN:
+ case SYMBOL_TRISTATE:
+ fputs(stmt->def->name, out);
+ break;
+ default:
+ print_quoted_string(out, stmt->def->name);
+ break;
+ }
+ if (!expr_is_yes(stmt->dep)) {
+ fputs(" if ", out);
+ fprint_expr(out, eliminate_yn(stmt->dep), 0);
+ }
+ fputc('\n', out);
+ stmt->menu = NULL;
+ }
+ }
+ if (sym->help && !(sym->flags & SYMBOL_PRINTED)) {
+ int len = strlen(sym->help);
+ char *p, *p2;
+ int cnt;
+
+ while (sym->help[--len] == '\n')
+ sym->help[len] = 0;
+ for (p = sym->help, cnt = 0; (p = strchr(p, '\n')); p++, cnt++)
+ ;
+ if (cnt >= 9)
+ fprintf(out, "\t---help---\n");
+ else
+ fprintf(out, "\thelp\n");
+ for (p = sym->help;; p = p2 + 1) {
+ while (*p == ' ')
+ p++;
+ if (*p == '\n') {
+ fputc('\n', out);
+ p2 = p;
+ continue;
+ }
+ p2 = strchr(p, '\n');
+ if (!p2)
+ break;
+ fprintf(out, "\t %.*s\n", p2 - p, p);
+ }
+ fprintf(out, "\t %s\n", p);
+ }
+ fputc('\n', out);
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ if (!VALID_STMT(stmt))
+ continue;
+ if (stmt->text) {
+ fprintf(out, "config %s\n", sym->name);
+ fputs( "\tprompt ", out);
+ print_quoted_string(out, skip_space(stmt->text));
+ fputc('\n', out);
+ dep2 = expr_alloc_and(expr_copy(dep), expr_copy(stmt->dep));
+ dep2 = eliminate_dups(dep2);
+ if (!expr_is_yes(dep2)) {
+ fputs("\tdepends on ", out);
+ fprint_expr(out, dep2, 0);
+ fputc('\n', out);
+ }
+ expr_free(dep2);
+ fputc('\n', out);
+ stmt->menu = NULL;
+ }
+ }
+ sym->flags |= SYMBOL_PRINTED;
+ expr_free(dep);
+}
+
+void print_choice(FILE *out, struct symbol *sym)
+{
+ struct statement *stmt;
+ struct expr *lst, *dep, *tmp, *tmp2;
+
+ if (sym->flags & SYMBOL_PRINTED)
+ return;
+
+ for (stmt = sym->stmt; stmt; stmt = stmt->next)
+ if (stmt->token == '^')
+ break;
+ if (!stmt)
+ //warn?
+ return;
+
+ fputs("choice\n", out);
+ if (stmt->text) {
+ fputs("\tprompt ", out);
+ print_quoted_string(out, skip_space(stmt->text));
+ fputc('\n', out);
+ }
+
+ dep = NULL;
+ for (lst = stmt->dep; lst; lst = lst->left.expr) {
+ sym = lst->right.sym;
+ if (sym == &symbol_no) {
+ fputs("\toptional\n", out);
+ continue;
+ }
+ if (!dep) {
+ if (!sym->dep)
+ break;
+ dep = sym->dep;
+ sym->dep = NULL;
+ } else {
+ tmp = dep;
+ if (sym->dep) {
+ dep = extract_eq_and(&tmp, &sym->dep);
+ if (expr_is_yes(tmp)) {
+ expr_free(tmp);
+ continue;
+ }
+ } else
+ dep = NULL;
+ for (tmp2 = stmt->dep; tmp2 != lst; tmp2 = tmp2->left.expr) {
+ sym = tmp2->right.sym;
+ if (sym == &symbol_no)
+ continue;
+ sym->dep = !sym->dep ? expr_copy(tmp) :
+ expr_alloc_two(T_AND, expr_copy(tmp), sym->dep);
+ sym->dep = eliminate_yn(sym->dep);
+ }
+ expr_free(tmp);
+ if (!dep)
+ break;
+ }
+ }
+ for (;lst; lst = lst->left.expr) {
+ sym = lst->right.sym;
+ if (sym == &symbol_no) {
+ fputs("\toptional\n", out);
+ continue;
+ }
+ }
+ if (!expr_is_yes(dep)) {
+ fputs("\tdepends on ", out);
+ fprint_expr(out, dep, 0);
+ fputc('\n', out);
+ }
+ if (stmt->def)
+ fprintf(out, "\tdefault %s\n", stmt->def->name);
+
+ fputc('\n', out);
+
+ for (lst = stmt->dep; lst; lst = lst->left.expr) {
+ sym = lst->right.sym;
+ if (sym == &symbol_no)
+ continue;
+ do_print_symbol(out, sym);
+ sym->flags |= SYMBOL_PRINTED;
+ }
+
+ fputs("endchoice\n\n", out);
+}
+
+void print_symbols(FILE *out, struct symbol *sym)
+{
+ //if (sym->flags & SYMBOL_PRINTED)
+ // return;
+ //sym->flags |= SYMBOL_PRINTED;
+
+ if (sym->flags & SYMBOL_CHOICE) {
+ print_choice(out, sym);
+ return;
+ }
+ do_print_symbol(out, sym);
+}
+
+char *gen_filename(const char *name)
+{
+ static char newname[128];
+ char *p;
+
+ strcpy(newname, name);
+ p = strrchr(newname, '/');
+ if (!p)
+ p = newname;
+ else
+ p++;
+#if 0
+ p = strrchr(p, '.');
+ if (!p)
+ p = newname + strlen(newname);
+ strcpy(p, ".new");
+#else
+#if 0
+ memcpy(p, "Build", 5);
+ memmove(p + 5, p + 6, strlen(p) - 5);
+ p = strrchr(p, '.');
+ if (!p)
+ p = newname + strlen(newname);
+ strcpy(p, ".conf");
+#else
+ memmove(p + 1, p, strlen(p) + 1);
+ p[0] = 'K';
+ p[1] = 'c';
+ p = strrchr(p, '.');
+ *p = 0;
+#endif
+#endif
+ return newname;
+}
+
+void print_files(FILE *all_out, const char *name)
+{
+ struct file *file;
+ FILE *out = all_out;
+ struct symbol *sym;
+ struct statement *stmt;
+ struct expr *dep1, *dep2;
+ char *p;
+
+ print_type = 0;
+
+ file = lookup_file(name);
+ if (!file) {
+ fprintf(stderr, "# file %s not found!\n\n", file->name);
+ return;
+ } else if (file->flags & FILE_PRINTED) {
+ fprintf(stderr, "# file %s skipped\n\n", file->name);
+ return;
+ }
+
+ if (!out) {
+ p = gen_filename(file->name);
+ strcat(p, ".lkc");
+ out = fopen(p, "w");
+ if (!out) {
+ printf("unable to open %s for writing!\n", p);
+ exit(1);
+ }
+ }
+
+ if (all_out)
+ fprintf(all_out, "# file %s\n\n", file->name);
+ file->flags |= FILE_PRINTED;
+
+ for (stmt = file->stmt; stmt; stmt = stmt->next_pos) {
+ sym = stmt->sym;
+ if (!sym) {
+ switch (stmt->token) {
+ case T_MAINMENU_NAME:
+ fputs("\nmainmenu ", out);
+ print_quoted_string(out, skip_space(stmt->text));
+ fputs("\n\n", out);
+ break;
+ case T_COMMENT:
+ fputs("comment ", out);
+ print_quoted_string(out, skip_space(stmt->text));
+ stmt->dep = eliminate_dups(trans_expr(stmt->dep));
+ dep1 = expr_copy(stmt->dep);
+ if (dep1 && current_menu->prompt && current_menu->prompt->dep) {
+ dep2 = expr_copy(current_menu->prompt->dep);
+ eliminate_eq(T_AND, &dep1, &dep2);
+ dep1 = eliminate_yn(dep1);
+ dep2 = eliminate_yn(dep2);
+ if (!expr_is_yes(dep2)) {
+ printf("Warning, I'm confused!\n");
+ }
+ expr_free(dep2);
+ }
+ if (!expr_is_yes(dep1)) {
+ dep1 = trans_bool_expr(dep1);
+ fputs("\n\tdepends on ", out);
+ fprint_expr(out, dep1, 0);
+ }
+ expr_free(dep1);
+ fputs("\n\n", out);
+ break;
+ case T_SH_COMMENT:
+ fprintf(out, "%s\n", stmt->text);
+ break;
+ case T_MAINMENU_OPTION:
+ fputs("\nmenu ", out);
+ print_quoted_string(out, skip_space(stmt->text));
+ stmt->dep = eliminate_dups(trans_expr(stmt->dep));
+ dep1 = expr_copy(stmt->dep);
+ if (dep1 && current_menu->prompt && current_menu->prompt->dep) {
+ dep2 = expr_copy(current_menu->prompt->dep);
+ eliminate_eq(T_AND, &dep1, &dep2);
+ dep1 = eliminate_yn(dep1);
+ dep2 = eliminate_yn(dep2);
+ if (!expr_is_yes(dep2)) {
+ printf("Warning, I'm confused!\n");
+ }
+ expr_free(dep2);
+ }
+ if (!expr_is_yes(dep1)) {
+ fputs("\n\tdepends on ", out);
+ fprint_expr(out, dep1, 0);
+ }
+ expr_free(dep1);
+ fputs("\n\n", out);
+ current_menu = stmt->menu;
+ break;
+ case T_ENDMENU:
+ fputs("endmenu\n\n", out);
+ current_menu = current_menu->parent;
+ break;
+ case T_SOURCE:
+ fprintf(out, "%ssource ", all_out ? "#" : "");
+ print_quoted_string(out, gen_filename(stmt->text));
+ fputs("\n\n", out);
+ print_files(all_out, stmt->text);
+ break;
+ }
+ } else
+ print_symbols(out, sym);
+ }
+
+ if (all_out)
+ fprintf(out, "# fileend %s\n\n", file->name);
+}
+
+static int trans_count;
+
+void eliminate_eq(int token, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+
+ if (e1->token == token) {
+ eliminate_eq(token, &e1->left.expr, &e2);
+ eliminate_eq(token, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->token == token) {
+ eliminate_eq(token, &e1, &e2->left.expr);
+ eliminate_eq(token, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1->token == T_WORD && e2->token == T_WORD &&
+ e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO)))
+ return;
+ if (!expr_eq(e1, e2))
+ return;
+ trans_count++;
+ expr_free(e1); expr_free(e2);
+ switch (token) {
+ case T_OR:
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ break;
+ case T_AND:
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ break;
+ }
+#undef e1
+#undef e2
+}
+
+int expr_eq(struct expr *e1, struct expr *e2)
+{
+ int res, old_count;
+
+ if (e1->token != e2->token)
+ return 0;
+ switch (e1->token) {
+ case '=':
+ case T_UNEQUAL:
+ return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
+ case T_WORD:
+ return e1->left.sym == e2->left.sym;
+ case '!':
+ return expr_eq(e1->left.expr, e2->left.expr);
+ case T_AND:
+ case T_OR:
+ e1 = expr_copy(e1);
+ e2 = expr_copy(e2);
+ old_count = trans_count;
+ eliminate_eq(e1->token, &e1, &e2);
+ e1 = eliminate_yn(e1);
+ e2 = eliminate_yn(e2);
+ res = (e1->token == T_WORD &&
+ e2->token == T_WORD &&
+ e1->left.sym == e2->left.sym);
+ expr_free(e1);
+ expr_free(e2);
+ trans_count = old_count;
+ return res;
+ }
+ print_expr(PRINTD, e1, 0);
+ printf(" = ");
+ print_expr(PRINTD, e2, 0);
+ printf(" ?\n");
+ return 0;
+}
+
+/*
+ * dep_bool FOO -> FOO=y
+ */
+struct expr *trans_dep_bool(struct expr *e)
+{
+ switch (e->token) {
+ case '&':
+ case T_AND:
+ e->left.expr = trans_dep_bool(e->left.expr);
+ e->right.expr = trans_dep_bool(e->right.expr);
+ break;
+ case T_WORD:
+ if (e->left.sym->type == SYMBOL_TRISTATE) {
+ e->token = '=';
+ e->right.sym = &symbol_yes;
+ }
+ break;
+ }
+ return e;
+}
+
+/*
+ * bool FOO!=n => FOO
+ */
+struct expr *trans_bool_expr(struct expr *e)
+{
+ if (!e)
+ return NULL;
+ switch (e->token) {
+ case T_AND:
+ case T_OR:
+ case '!':
+ e->left.expr = trans_bool_expr(e->left.expr);
+ e->right.expr = trans_bool_expr(e->right.expr);
+ break;
+ case T_UNEQUAL:
+ // FOO!=n -> FOO
+ if (e->left.sym->type == SYMBOL_TRISTATE) {
+ if (e->right.sym == &symbol_no) {
+ e->token = T_WORD;
+ e->right.sym = NULL;
+ }
+ }
+ break;
+ }
+ return e;
+}
+
+struct expr *fixup_expr(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (!e)
+ return NULL;
+
+ switch (e->token) {
+ case T_IF:
+ // if expr if expr ... -> expr && expr ...
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, " -> ");
+ tmp = e->left.expr;
+ if (!e->right.expr) {
+ free(e);
+ e = fixup_expr(tmp);
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, "\n");
+ return e;
+ }
+ e->left.expr = e->right.expr;
+ e->right.expr = tmp;
+ e->token = T_AND;
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, "\n");
+ break;
+ case T_ELSE:
+ // if expr else expr ... -> expr && !expr ...
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, " -> ");
+ e->token = '!';
+ if (!e->right.expr) {
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, "\n");
+ break;
+ }
+ tmp = e;
+ e = expr_alloc_two(T_AND, e->right.expr, e);
+ tmp->right.expr = NULL;
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, "\n");
+ break;
+ case '&':
+ // expr & expr -> expr && expr
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, " -> ");
+ e->token = T_AND;
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, "\n");
+ break;
+ case '=':
+ case T_UNEQUAL:
+ if (!(e->left.sym->flags & SYMBOL_CONST))
+ return e;
+ if (e->right.sym->flags & SYMBOL_CONST) {
+ if (e->left.sym == e->right.sym) {
+ e->left.sym = e->token == '=' ? &symbol_yes : &symbol_no;
+ } else {
+ e->left.sym = e->token != '=' ? &symbol_yes : &symbol_no;
+ }
+ e->token = T_WORD;
+ e->right.sym = NULL;
+ } else {
+ // y/n/m = sym -> sym = y/n/m
+ struct symbol *sym;
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, " -> ");
+ sym = e->left.sym;
+ e->left.sym = e->right.sym;
+ e->right.sym = sym;
+ print_expr(DEBUG_OPT1, e, 0);
+ printd(DEBUG_OPT1, "\n");
+ }
+ return e;
+ case T_WORD:
+ case '^':
+ return e;
+ }
+ e->left.expr = fixup_expr(e->left.expr);
+ e->right.expr = fixup_expr(e->right.expr);
+ return e;
+}
+
+struct expr *join_or(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->token != '=' && e1->token != T_UNEQUAL && e1->token != T_WORD && e1->token != '!')
+ return NULL;
+ if (e2->token != '=' && e2->token != T_UNEQUAL && e2->token != T_WORD && e2->token != '!')
+ return NULL;
+ if (e1->token == '!') {
+ tmp = e1->left.expr;
+ if (tmp->token != '=' && tmp->token != T_UNEQUAL && tmp->token != T_WORD)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->token == '!') {
+ if (e2->left.expr->token != T_WORD)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != SYMBOL_BOOLEAN && sym1->type != SYMBOL_TRISTATE)
+ return NULL;
+ if (sym1->type == SYMBOL_TRISTATE) {
+ if (e1->token == '=' && e2->token == '=' &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='m') -> (a!='n')
+ return expr_alloc_comp(T_UNEQUAL, sym1, &symbol_no);
+ }
+ if (e1->token == '=' && e2->token == '=' &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='n') -> (a!='m')
+ return expr_alloc_comp(T_UNEQUAL, sym1, &symbol_mod);
+ }
+ if (e1->token == '=' && e2->token == '=' &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
+ // (a='m') || (a='n') -> (a!='y')
+ return expr_alloc_comp(T_UNEQUAL, sym1, &symbol_yes);
+ }
+ }
+ if (sym1->type == SYMBOL_BOOLEAN && sym1 == sym2) {
+ if ((e1->token == '!' && e1->left.expr->token == T_WORD && e2->token == T_WORD) ||
+ (e2->token == '!' && e2->left.expr->token == T_WORD && e1->token == T_WORD))
+ return expr_alloc_symbol(&symbol_yes);
+ }
+
+ printf("optimize ");
+ print_expr(PRINTD, e1, 0);
+ printf(" || ");
+ print_expr(PRINTD, e2, 0);
+ printf(" ?\n");
+ return NULL;
+}
+
+struct expr *join_and(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->token != '=' && e1->token != T_UNEQUAL && e1->token != T_WORD && e1->token != '!')
+ return NULL;
+ if (e2->token != '=' && e2->token != T_UNEQUAL && e2->token != T_WORD && e2->token != '!')
+ return NULL;
+ if (e1->token == '!') {
+ tmp = e1->left.expr;
+ if (tmp->token != '=' && tmp->token != T_UNEQUAL && tmp->token != T_WORD)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->token == '!') {
+ if (e2->left.expr->token != T_WORD)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != SYMBOL_BOOLEAN && sym1->type != SYMBOL_TRISTATE)
+ return NULL;
+
+ if ((e1->token == T_WORD && e2->token == '=' && e2->right.sym == &symbol_yes) ||
+ (e2->token == T_WORD && e1->token == '=' && e1->right.sym == &symbol_yes))
+ // (a) && (a='y') -> (a='y')
+ return expr_alloc_comp('=', sym1, &symbol_yes);
+
+ if ((e1->token == T_WORD && e2->token == T_UNEQUAL && e2->right.sym == &symbol_no) ||
+ (e2->token == T_WORD && e1->token == T_UNEQUAL && e1->right.sym == &symbol_no))
+ // (a) && (a!='n') -> (a)
+ return expr_alloc_symbol(sym1);
+
+ if (sym1->type == SYMBOL_TRISTATE) {
+ if (e1->token == '=' && e2->token == T_UNEQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e1->right.sym;
+ if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e2->right.sym ? expr_alloc_comp('=', sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->token == T_UNEQUAL && e2->token == '=') {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e2->right.sym;
+ if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e1->right.sym ? expr_alloc_comp('=', sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->token == T_UNEQUAL && e2->token == T_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='n') -> (a='m')
+ return expr_alloc_comp('=', sym1, &symbol_mod);
+
+ if (e1->token == T_UNEQUAL && e2->token == T_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='m') -> (a='n')
+ return expr_alloc_comp('=', sym1, &symbol_no);
+
+ if (e1->token == T_UNEQUAL && e2->token == T_UNEQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
+ // (a!='m') && (a!='n') -> (a='m')
+ return expr_alloc_comp('=', sym1, &symbol_yes);
+
+ if ((e1->token == T_WORD && e2->token == '=' && e2->right.sym == &symbol_mod) ||
+ (e2->token == T_WORD && e1->token == '=' && e1->right.sym == &symbol_mod) ||
+ (e1->token == T_WORD && e2->token == T_UNEQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->token == T_WORD && e1->token == T_UNEQUAL && e1->right.sym == &symbol_yes))
+ return NULL;
+ }
+ printf("optimize ");
+ print_expr(PRINTD, e1, 0);
+ printf(" && ");
+ print_expr(PRINTD, e2, 0);
+ printf(" ?\n");
+ return NULL;
+}
+
+void eliminate_dups1(int token, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp;
+
+ if (e1->token == token) {
+ eliminate_dups1(token, &e1->left.expr, &e2);
+ eliminate_dups1(token, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->token == token) {
+ eliminate_dups1(token, &e1, &e2->left.expr);
+ eliminate_dups1(token, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->token) {
+ case T_OR: case T_AND:
+ eliminate_dups1(e1->token, &e1, &e1);
+ }
+
+ switch (token) {
+ case T_OR:
+ tmp = join_or(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ case T_AND:
+ tmp = join_and(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ }
+#undef e1
+#undef e2
+}
+
+void eliminate_dups2(int token, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp, *tmp1, *tmp2;
+
+ if (e1->token == token) {
+ eliminate_dups2(token, &e1->left.expr, &e2);
+ eliminate_dups2(token, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->token == token) {
+ eliminate_dups2(token, &e1, &e2->left.expr);
+ eliminate_dups2(token, &e1, &e2->right.expr);
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->token) {
+ case T_OR:
+ eliminate_dups2(e1->token, &e1, &e1);
+ // (FOO || BAR) && (!FOO && !BAR) -> n
+ tmp1 = trans_expr(expr_alloc_one('!', expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = extract_eq_and(&tmp1, &tmp2);
+ if (expr_is_yes(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_no);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ case T_AND:
+ eliminate_dups2(e1->token, &e1, &e1);
+ // (FOO && BAR) || (!FOO || !BAR) -> y
+ tmp1 = trans_expr(expr_alloc_one('!', expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = extract_eq_or(&tmp1, &tmp2);
+ if (expr_is_no(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *eliminate_dups(struct expr *e)
+{
+ int oldcount;
+ if (!e)
+ return e;
+
+ oldcount = trans_count;
+ while (1) {
+ trans_count = 0;
+ switch (e->token) {
+ case T_OR: case T_AND:
+ eliminate_dups1(e->token, &e, &e);
+ eliminate_dups2(e->token, &e, &e);
+ }
+ if (!trans_count)
+ break;
+ e = eliminate_yn(e);
+ }
+ trans_count = oldcount;
+ return e;
+}
+
+struct expr *eliminate_yn(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (e) switch (e->token) {
+ case T_AND:
+ e->left.expr = eliminate_yn(e->left.expr);
+ e->right.expr = eliminate_yn(e->right.expr);
+ if (e->left.expr->token == T_WORD) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->token = T_WORD;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ if (e->right.expr->token == T_WORD) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->token = T_WORD;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ break;
+ case T_OR:
+ e->left.expr = eliminate_yn(e->left.expr);
+ e->right.expr = eliminate_yn(e->right.expr);
+ if (e->left.expr->token == T_WORD) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->token = T_WORD;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ if (e->right.expr->token == T_WORD) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->token = T_WORD;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ break;
+ }
+ return e;
+}
+
+struct expr *trans_expr(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (!e)
+ return NULL;
+ switch (e->token) {
+ case '=':
+ case T_UNEQUAL:
+ case T_WORD:
+ case '^':
+ break;
+ default:
+ e->left.expr = trans_expr(e->left.expr);
+ e->right.expr = trans_expr(e->right.expr);
+ }
+
+ switch (e->token) {
+ case '=':
+ if (e->left.sym->type != SYMBOL_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ e->token = '!';
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
+ e->token = T_WORD;
+ e->left.sym = &symbol_no;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ e->token = T_WORD;
+ e->right.sym = NULL;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ break;
+ }
+ break;
+ case T_UNEQUAL:
+ if (e->left.sym->type != SYMBOL_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ e->token = T_WORD;
+ e->right.sym = NULL;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
+ e->token = T_WORD;
+ e->left.sym = &symbol_yes;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ e->token = '!';
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ break;
+ }
+ break;
+ case '!':
+ switch (e->left.expr->token) {
+ case '!':
+ // !!a -> a
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ tmp = e->left.expr->left.expr;
+ free(e->left.expr);
+ free(e);
+ e = tmp;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ e = trans_expr(e);
+ break;
+ case '=':
+ case T_UNEQUAL:
+ // !a='x' -> a!='x'
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ if (e->token == '=')
+ e->token = T_UNEQUAL;
+ else
+ e->token = '=';
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ break;
+ case T_OR:
+ // !(a || b) -> !a && !b
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ tmp = e->left.expr;
+ e->token = T_AND;
+ e->right.expr = expr_alloc_one('!', tmp->right.expr);
+ tmp->token = '!';
+ tmp->right.expr = NULL;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ e = trans_expr(e);
+ break;
+ case T_AND:
+ // !(a && b) -> !a || !b
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ tmp = e->left.expr;
+ e->token = T_OR;
+ e->right.expr = expr_alloc_one('!', tmp->right.expr);
+ tmp->token = '!';
+ tmp->right.expr = NULL;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ e = trans_expr(e);
+ break;
+ case T_WORD:
+ if (e->left.expr->left.sym == &symbol_yes) {
+ // !'y' -> 'n'
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->token = T_WORD;
+ e->left.sym = &symbol_no;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_no) {
+ // !'n' -> 'y'
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, " -> ");
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->token = T_WORD;
+ e->left.sym = &symbol_yes;
+ print_expr(DEBUG_OPT2, e, 0);
+ printd(DEBUG_OPT2, "\n");
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ return e;
+}
+
+struct expr *extract_eq_and(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ extract_eq(T_AND, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = eliminate_yn(*ep1);
+ *ep2 = eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+struct expr *extract_eq_or(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ extract_eq(T_OR, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = eliminate_yn(*ep1);
+ *ep2 = eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+void extract_eq(int token, struct expr **ep, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ if (e1->token == token) {
+ extract_eq(token, ep, &e1->left.expr, &e2);
+ extract_eq(token, ep, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->token == token) {
+ extract_eq(token, ep, ep1, &e2->left.expr);
+ extract_eq(token, ep, ep1, &e2->right.expr);
+ return;
+ }
+ if (expr_eq(e1, e2)) {
+ *ep = *ep ? expr_alloc_two(token, *ep, e1) : e1;
+ expr_free(e2);
+ if (token == T_AND) {
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ } else if (token == T_OR) {
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ }
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *optimize_expr_or(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (!e || e->token != T_OR)
+ return e;
+
+ e->left.expr = optimize_expr_or(e->left.expr);
+ e->right.expr = optimize_expr_or(e->right.expr);
+
+ tmp = extract_eq_and(&e->left.expr, &e->right.expr);
+ if (!tmp)
+ return e;
+ return expr_alloc_two(T_AND, tmp, e);
+}
+
+int contains_expr(struct expr *dep, struct expr *e)
+{
+ if (!dep)
+ return 0;
+ if (dep->token == T_AND)
+ return contains_expr(dep->left.expr, e) || contains_expr(dep->right.expr, e);
+ return expr_eq(dep, e);
+}
+
+struct expr *trans_comp_expr(struct expr *e, int token, struct symbol *sym)
+{
+ struct expr *e1, *e2;
+
+ switch (e->token) {
+ case T_AND:
+ e1 = trans_comp_expr(e->left.expr, '=', sym);
+ e2 = trans_comp_expr(e->right.expr, '=', sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(T_AND, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(T_OR, e1, e2);
+ if (token == T_UNEQUAL)
+ e = expr_alloc_one('!', e);
+ return e;
+ case T_OR:
+ e1 = trans_comp_expr(e->left.expr, '=', sym);
+ e2 = trans_comp_expr(e->right.expr, '=', sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(T_OR, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(T_AND, e1, e2);
+ if (token == T_UNEQUAL)
+ e = expr_alloc_one('!', e);
+ return e;
+ case '!':
+ switch (token) {
+ case '=':
+ return trans_comp_expr(e->left.expr, T_UNEQUAL, sym);
+ case T_UNEQUAL:
+ return trans_comp_expr(e->left.expr, '=', sym);
+ }
+ break;
+ case T_UNEQUAL:
+ case '=':
+ if (token == '=') {
+ if (sym == &symbol_yes)
+ return expr_copy(e);
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_no);
+ if (sym == &symbol_no)
+ return expr_alloc_one('!', expr_copy(e));
+ } else {
+ if (sym == &symbol_yes)
+ return expr_alloc_one('!', expr_copy(e));
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_yes);
+ if (sym == &symbol_no)
+ return expr_copy(e);
+ }
+ break;
+ case T_WORD:
+ return expr_alloc_comp(token, e->left.sym, sym);
+ }
+ return NULL;
+}
+
+void eliminate_dep(struct symbol *sym, struct expr *dep)
+{
+ struct symbol *sym2;
+ struct expr *dep2;
+
+ if (dep->token == T_AND) {
+ eliminate_dep(sym, dep->left.expr);
+ eliminate_dep(sym, dep->right.expr);
+ }
+#if 0
+ if (dep->token == T_WORD ||
+ (sym->type == SYMBOL_BOOLEAN &&
+ ((dep->token == T_UNEQUAL && dep->right.sym == &symbol_no) ||
+ (dep->token == '=' && dep->right.sym == &symbol_yes)))) {
+ sym2 = dep->left.sym;
+ if (sym2->dep) {
+ if (!sym2->dep2)
+ eliminate_dep(sym2, sym2->dep);
+ sym->dep2 = !sym->dep2 ? expr_copy(sym2->dep2)
+ : expr_alloc_two(T_AND, expr_copy(sym2->dep2), sym->dep2);
+ }
+ }
+#else
+ switch (dep->token) {
+ case T_WORD:
+ case T_UNEQUAL:
+ case '=':
+ sym2 = dep->left.sym;
+ if (sym2->type != SYMBOL_BOOLEAN && sym2->type != SYMBOL_TRISTATE)
+ break;
+ if (!sym2->dep)
+ break;
+ if (!sym2->dep2)
+ eliminate_dep(sym2, sym2->dep);
+ if (dep->token == T_WORD) {
+ if (sym2->type == SYMBOL_BOOLEAN)
+ dep2 = trans_comp_expr(sym2->dep2, T_UNEQUAL, &symbol_no);
+ else
+ dep2 = expr_copy(sym2->dep2);
+ } else {
+ //if ((dep->token == T_UNEQUAL && dep->right.sym == &symbol_no) ||
+ // (sym2->type == SYMBOL_BOOLEAN &&
+ // dep->token == '=' && dep->right.sym == &symbol_yes))
+ if ((dep->token == '=' && dep->right.sym == &symbol_yes) ||
+ (sym2->type == SYMBOL_BOOLEAN &&
+ dep->token == T_UNEQUAL && dep->right.sym == &symbol_no))
+ dep2 = trans_comp_expr(sym2->dep2, dep->token, dep->right.sym);
+ else
+ break;
+ }
+ dep2 = eliminate_yn(trans_expr(fixup_expr(dep2)));
+ sym->dep2 = !sym->dep2 ? dep2 : expr_alloc_two(T_AND, dep2, sym->dep2);
+ }
+#endif
+ if (sym->dep == dep) {
+ printd(DEBUG_DEP, "el: %s (", sym->name);
+ print_expr(DEBUG_DEP, sym->dep, 0);
+ printd(DEBUG_DEP, ")\n");
+ if (sym->dep2) {
+ print_expr(DEBUG_DEP, sym->dep2, 0); printd(DEBUG_DEP, "\n");
+ sym->dep2 = eliminate_yn(eliminate_dups(sym->dep2));
+ switch (sym->type) {
+ case SYMBOL_BOOLEAN: case SYMBOL_INT: case SYMBOL_HEX: case SYMBOL_STRING:
+ sym->dep2 = trans_bool_expr(sym->dep2);
+ break;
+ }
+ print_expr(DEBUG_DEP, sym->dep2, 0); printd(DEBUG_DEP, "\n");
+ sym->dep = expr_alloc_two(T_AND, expr_copy(sym->dep2), sym->dep);
+ sym->dep = eliminate_dups(sym->dep);
+ print_expr(DEBUG_DEP, sym->dep, 0); printd(DEBUG_DEP, "\n");
+ dep = expr_copy(sym->dep2);
+ eliminate_eq(T_AND, &dep, &sym->dep);
+ sym->dep = eliminate_yn(sym->dep);
+ sym->dep2 = expr_alloc_two(T_AND, sym->dep2, expr_copy(sym->dep));
+ } else
+ sym->dep2 = expr_copy(sym->dep);
+ printd(DEBUG_DEP, " -> ");
+ print_expr(DEBUG_DEP, sym->dep2, 0);
+ printd(DEBUG_DEP, " -> ");
+ print_expr(DEBUG_DEP, sym->dep, 0);
+ printd(DEBUG_DEP, "\n");
+ }
+}
+
+struct symbol * dep_check_symbol(struct symbol *sym);
+
+struct symbol *dep_check_expr(struct expr *e)
+{
+ struct symbol *sym;
+ if (!e)
+ return 0;
+ switch (e->token) {
+ case T_WORD:
+ case T_WORD_QUOTE:
+ case T_WORD_DQUOTE:
+ return dep_check_symbol(e->left.sym);
+ case '=':
+ case T_UNEQUAL:
+ sym = dep_check_symbol(e->left.sym);
+ if (sym)
+ return sym;
+ return dep_check_symbol(e->right.sym);
+ case T_OR:
+ case T_AND:
+ sym = dep_check_expr(e->left.expr);
+ if (sym)
+ return sym;
+ return dep_check_expr(e->right.expr);
+ case '!':
+ return dep_check_expr(e->left.expr);
+ }
+ printf("how to check %d?\n", e->token);
+ return NULL;
+}
+
+struct symbol *dep_check_symbol(struct symbol *sym)
+{
+ struct statement *stmt, *stmt2;
+ struct symbol *sym2;
+ struct expr *e1, *e2;
+
+ if (sym->flags & SYMBOL_CHECK) {
+ printf("recursive dependency: %s", sym->name);
+ return sym;
+ }
+
+ sym->flags |= SYMBOL_CHECK;
+ sym2 = dep_check_expr(sym->dep);
+ if (sym2) {
+ printf(" %s", sym->name);
+ if (sym->type != sym2->type)
+ goto out;
+ switch (sym->type) {
+ case SYMBOL_TRISTATE:
+ e1 = expr_alloc_comp(T_UNEQUAL, sym, &symbol_yes);
+ e2 = expr_alloc_comp(T_UNEQUAL, sym2, &symbol_yes);
+ break;
+ case SYMBOL_BOOLEAN:
+ e1 = expr_alloc_one('!', expr_alloc_symbol(sym));
+ e2 = expr_alloc_one('!', expr_alloc_symbol(sym2));
+ break;
+ default:
+ goto out;
+ }
+ if (contains_expr(sym->dep, e2) && contains_expr(sym2->dep, e1)) {
+ printf(" (choice(%d) detected)", sym->type);
+ sym->flags |= SYMBOL_CHOICE;
+ eliminate_eq(T_AND, &sym->dep, &e2);
+ sym->dep = eliminate_yn(sym->dep);
+ sym2->flags |= SYMBOL_CHOICE;
+ eliminate_eq(T_AND, &sym2->dep, &e1);
+ sym2->dep = eliminate_yn(sym2->dep);
+ stmt = malloc(sizeof(*stmt));
+ memset(stmt, 0, sizeof(*stmt));
+ stmt->token = '^';
+ stmt->text = "change me!";
+ stmt->dep = expr_alloc_one('^', NULL);
+ stmt->dep->right.sym = sym;
+ stmt->dep = expr_alloc_one('^', stmt->dep);
+ stmt->dep->right.sym = sym2;
+ stmt->dep = expr_alloc_one('^', stmt->dep);
+ stmt->dep->right.sym = &symbol_no;
+ for (stmt2 = sym->stmt; stmt2->next; stmt2 = stmt2->next)
+ ;
+ if (stmt2->token == '^')
+ printf("warning: symbol %s has dup choice statement?\n", sym->name);
+ else
+ stmt2->next = stmt;
+ for (stmt2 = sym2->stmt; stmt2->next; stmt2 = stmt2->next)
+ ;
+ if (stmt2->token == '^')
+ printf("warning: symbol %s has dup choice statement?\n", sym->name);
+ else
+ stmt2->next = stmt;
+ }
+ expr_free(e1);
+ expr_free(e2);
+ }
+ if (!sym2) for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ if (!stmt->token || stmt->token == '^')
+ continue;
+ sym2 = dep_check_expr(stmt->dep);
+ if (sym2) {
+ printf(" %s", sym->name);
+ break;
+ }
+ }
+out:
+ sym->flags &= ~SYMBOL_CHECK;
+
+ return sym2;
+}
+
+const char *sym_typename(int type)
+{
+ switch (type) {
+ case SYMBOL_UNKNOWN: return "unknown";
+ case SYMBOL_BOOLEAN: return "bool";
+ case SYMBOL_TRISTATE: return "tristate";
+ case SYMBOL_INT: return "integer";
+ case SYMBOL_HEX: return "hex";
+ case SYMBOL_STRING: return "string";
+ case SYMBOL_OTHER: return "other";
+ default: return "???";
+ }
+}
+
+void optimize_config(void)
+{
+ struct symbol *sym;
+ struct statement *stmt, *stmt2, **stmtp;
+ struct expr *e;
+ int i;
+
+ for_all_symbols(i, sym) {
+ again:
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ switch (stmt->token) {
+ case '^':
+ case T_BOOL:
+ case T_DEP_BOOL:
+ case T_DEP_MBOOL:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_BOOLEAN;
+ if (sym->type != SYMBOL_BOOLEAN)
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_BOOLEAN));
+ if (sym->type == SYMBOL_TRISTATE) {
+ printf("%s:%d:Force stmt to dep_tristate\n",
+ stmt->file->name, stmt->lineno);
+ stmt->token = T_DEP_TRISTATE;
+ }
+ break;
+ case T_DEFINE_BOOL:
+ if (stmt->def == &symbol_mod) {
+ printf("%s:%d:warning: symbol %s set to 'm', force stmt to define_tristate\n",
+ stmt->file->name, stmt->lineno, sym->name);
+ stmt->token = T_DEFINE_TRISTATE;
+ }
+ break;
+ case T_HEX:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_HEX;
+ if (sym->type != SYMBOL_HEX)
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_HEX));
+ break;
+ case T_INT:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_INT;
+ if (sym->type != SYMBOL_INT)
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_INT));
+ break;
+ case T_STRING:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_STRING;
+ if (sym->type != SYMBOL_STRING)
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_STRING));
+ break;
+ case T_TRISTATE:
+ case T_DEP_TRISTATE:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_TRISTATE;
+ if (sym->type != SYMBOL_TRISTATE) {
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s), force symbol to tristate\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_TRISTATE));
+ sym->type = SYMBOL_TRISTATE;
+ goto again;
+ }
+ break;
+ }
+ }
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ switch (stmt->token) {
+ case T_DEFINE_BOOL:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_BOOLEAN;
+ if (sym->type != SYMBOL_BOOLEAN)
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_BOOLEAN));
+ if (sym->type == SYMBOL_TRISTATE) {
+ printf("%s:%d:Force stmt to define_tristate\n",
+ stmt->file->name, stmt->lineno);
+ stmt->token = T_DEFINE_TRISTATE;
+ }
+ break;
+ case T_DEFINE_TRISTATE:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_TRISTATE;
+ if (sym->type != SYMBOL_TRISTATE) {
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s), force symbol to tristate\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_TRISTATE));
+ sym->type = SYMBOL_TRISTATE;
+ goto again;
+ }
+ break;
+ case T_DEFINE_HEX:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_HEX;
+ if (sym->type != SYMBOL_HEX)
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_HEX));
+ break;
+ case T_DEFINE_INT:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_INT;
+ if (sym->type != SYMBOL_INT)
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_INT));
+ break;
+ case T_DEFINE_STRING:
+ if (sym->type == SYMBOL_UNKNOWN)
+ sym->type = SYMBOL_STRING;
+ if (sym->type != SYMBOL_STRING)
+ printf("%s:%d:warning: symbol %s has conflicting types (%s,%s)\n",
+ stmt->file->name, stmt->lineno, sym->name,
+ sym_typename(sym->type), sym_typename(SYMBOL_STRING));
+ break;
+ }
+ }
+ }
+ for_all_symbols(i, sym) {
+ printd(DEBUG_OPT1, "o1: %s\n", sym->name);
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ print_expr(DEBUG_OPT1, stmt->dep, 0);
+ printd(DEBUG_OPT1, " & ");
+ print_expr(DEBUG_OPT1, stmt->dep2, 0);
+ printd(DEBUG_OPT1, "\n");
+ if (stmt->dep || stmt->dep2) {
+ struct expr *e = stmt->dep2;
+ if (stmt->token == T_DEP_BOOL) {
+ e = trans_dep_bool(e);
+ stmt->token = T_DEP_MBOOL;
+ }
+ if (stmt->dep && e) {
+ stmt->dep = expr_alloc_two(T_AND, stmt->dep, e);
+ } else if (e)
+ stmt->dep = e;
+ stmt->dep2 = NULL;
+ switch (stmt->token) {
+ case T_DEP_MBOOL: stmt->token = T_BOOL; break;
+ case T_DEP_TRISTATE: stmt->token = T_TRISTATE; break;
+ }
+ }
+ stmt->dep = fixup_expr(stmt->dep);
+ print_expr(DEBUG_OPT1, stmt->dep, 0);
+ printd(DEBUG_OPT1, "\n");
+ }
+ }
+ for_all_symbols(i, sym) {
+ printd(DEBUG_OPT3, "o3: %s\n", sym->name);
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ print_expr(DEBUG_OPT3, stmt->dep, 0);
+ printd(DEBUG_OPT3, "\n");
+ stmt->dep = eliminate_dups(trans_expr(stmt->dep));
+ switch (sym->type) {
+ case SYMBOL_BOOLEAN: case SYMBOL_INT: case SYMBOL_HEX: case SYMBOL_STRING:
+ stmt->dep = trans_bool_expr(stmt->dep);
+ break;
+ }
+ print_expr(DEBUG_OPT3, stmt->dep, 0);
+ printd(DEBUG_OPT3, "\n");
+ }
+ }
+ for_all_symbols(i, sym) {
+ sym->dep = eliminate_yn(sym->dep);
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ stmt->dep = eliminate_yn(stmt->dep);
+ if (expr_is_no(stmt->dep)) {
+ printf("%s:%d: stmt can never be reached, removed!\n", stmt->file->name, stmt->lineno);
+ stmt->token = 0;
+ }
+ }
+ }
+ for_all_symbols(i, sym) {
+ stmtp = &sym->stmt;
+ stmt = *stmtp;
+ if (!stmt) {
+ printf("undefined symbol %s\n", sym->name);
+ continue;
+ }
+ //if (sym->flags & SYMBOL_CHOICE)
+ // continue;
+ while (stmt) {
+ if (!stmt->token || stmt->token == '^') {
+ stmtp = &stmt->next;
+ stmt = *stmtp;
+ continue;
+ }
+#if 1
+ if ((stmt->token == T_DEFINE_BOOL || stmt->token == T_DEFINE_TRISTATE) &&
+ (stmt->def == &symbol_no || expr_is_no(stmt->dep))) {
+ stmt->token = 0;
+ stmt->def = NULL;
+ expr_free(stmt->dep);
+ stmt->dep = NULL;
+ continue;
+ }
+#endif
+ //if (stmt->text && stmt != sym->stmt) {
+ // if (sym->stmt->text)
+ // printf("warning: another stmt with prompt for %s????\n", sym->name);
+ // *stmtp = stmt->next;
+ // stmt->next = sym->stmt;
+ // sym->stmt = stmt;
+ //}
+ for (stmt2 = stmt->next; stmt2; stmt2 = stmt2->next) {
+ if (stmt->token != stmt2->token || stmt->def != stmt2->def ||
+ stmt->menu->parent != stmt2->menu->parent)
+ continue;
+ if (stmt->text) {
+ if (strcmp(skip_space(stmt->text), skip_space(stmt2->text))) {
+ printf("warning: prompts differ for %s?\n", sym->name);
+ continue;
+ }
+ }
+ if (!stmt->dep)
+ stmt->dep = expr_alloc_symbol(&symbol_yes);
+ if (!stmt2->dep)
+ stmt2->dep = expr_alloc_symbol(&symbol_yes);
+ stmt->dep = optimize_expr_or(expr_alloc_two(T_OR, stmt->dep, stmt2->dep));
+ stmt2->token = 0;
+ free((void *)stmt2->text);
+ stmt2->text = NULL;
+ stmt2->def = NULL;
+ stmt2->dep = NULL;
+ }
+ if (stmt->text && stmt != sym->stmt) {
+ *stmtp = stmt->next;
+ stmt->next = sym->stmt;
+ sym->stmt = stmt;
+ } else
+ stmtp = &stmt->next;
+ stmt = *stmtp;
+ }
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ if (!stmt->token || stmt->token == '^')
+ continue;
+ if (!sym->dep) {
+ if (!stmt->dep)
+ break;
+ sym->dep = stmt->dep;
+ stmt->dep = NULL;
+ } else {
+ e = sym->dep;
+ if (stmt->dep) {
+ sym->dep = extract_eq_and(&e, &stmt->dep);
+ if (expr_is_yes(e)) {
+ expr_free(e);
+ continue;
+ }
+ } else
+ sym->dep = NULL;
+ for (stmt2 = sym->stmt; stmt != stmt2; stmt2 = stmt2->next) {
+ if (!stmt2->token || stmt2->token == '^')
+ continue;
+ stmt2->dep = !stmt2->dep ? expr_copy(e) :
+ expr_alloc_two(T_AND, expr_copy(e), stmt2->dep);
+ }
+ expr_free(e);
+ if (!sym->dep)
+ break;
+ }
+ }
+#if 0
+ for (stmt1 = sym->stmt; stmt1; stmt1 = stmt1->next)
+ if (stmt1->token && stmt1->token != '^')
+ break;
+ if (stmt1 && !expr_is_yes(stmt1->dep)) {
+ e = trans_expr(expr_alloc_one('!', stmt1->dep));
+ stmt1->dep = NULL;
+ for (stmt = stmt1->next; stmt; stmt = stmt->next) {
+ if (!stmt->token || stmt->token == '^')
+ continue;
+ if (stmt->dep) {
+ tmp = extract_eq_and(&e, &stmt->dep);
+ if (expr_is_yes(e)) {
+ expr_free(e);
+ e = tmp;
+ continue;
+ }
+ if (tmp) {
+ e = expr_alloc_two(T_AND, expr_copy(tmp), e);
+ stmt->dep = expr_alloc_two(T_AND, tmp, stmt->dep);
+ }
+ }
+ for (stmt2 = stmt1->next; stmt != stmt2; stmt2 = stmt2->next) {
+ if (!stmt2->token || stmt2->token == '^')
+ continue;
+ stmt2->dep = !stmt2->dep ? expr_copy(e) :
+ expr_alloc_two(T_AND, expr_copy(e), stmt2->dep);
+ }
+ stmt1->dep = trans_expr(expr_alloc_one('!', e));
+ break;
+ }
+ if (!stmt1->dep) {
+ e = trans_expr(expr_alloc_one('!', e));
+ //sym->dep = sym->dep ? expr_alloc_two(T_AND, sym->dep, e) : e;
+ stmt1->dep = e;
+ }
+ }
+ for (stmtp = &sym->stmt; *stmtp; stmtp = &stmt->next) {
+ stmt = *stmtp;
+ if (!stmt->token || stmt->token == '^')
+ continue;
+ if (!stmt->dep || stmt->text)
+ continue;
+ for (stmt2 = stmt->next; stmt2; stmt2 = stmt2->next) {
+ trans_count = 0;
+ if (!stmt2->dep || stmt2->text)
+ continue;
+ e = trans_expr(expr_alloc_one('!', expr_copy(stmt->dep)));
+ tmp = extract_eq_and(&e, &stmt2->dep);
+ if (expr_is_yes(e)) {
+ expr_free(e);
+ expr_free(tmp);
+ continue;
+ }
+ if (tmp)
+ stmt2->dep = expr_alloc_two(T_AND, tmp, stmt2->dep);
+ e = trans_expr(expr_alloc_one('!', expr_copy(stmt2->dep)));
+ tmp = extract_eq_and(&e, &stmt->dep);
+ if (expr_is_yes(e)) {
+ expr_free(e);
+ expr_free(tmp);
+ while (stmt->next != stmt2)
+ stmt = stmt->next;
+ stmt->next = *stmtp;
+ *stmtp = stmt2;
+ stmt = stmt->next;
+ stmt2 = stmt->next;
+ stmt->next = (*stmtp)->next;
+ (*stmtp)->next = stmt2;
+ continue;
+ }
+ if (tmp)
+ stmt->dep = expr_alloc_two(T_AND, tmp, stmt->dep);
+ }
+ }
+#endif
+ }
+ for_all_symbols(i, sym) {
+ printd(DEBUG_OPT4, "o4: %s\n", sym->name);
+ print_expr(DEBUG_OPT4, sym->dep, 0); printd(DEBUG_OPT4, "\n");
+ sym->dep = eliminate_dups(sym->dep);
+ sym->dep = eliminate_yn(sym->dep);
+ print_expr(DEBUG_OPT4, sym->dep, 0); printd(DEBUG_OPT4, "\n");
+ for (stmt = sym->stmt; stmt; stmt = stmt->next) {
+ print_expr(DEBUG_OPT4, stmt->dep, 0); printd(DEBUG_OPT4, "\n");
+ stmt->dep = eliminate_dups(stmt->dep);
+ stmt->dep = eliminate_yn(stmt->dep);
+ print_expr(DEBUG_OPT4, stmt->dep, 0); printd(DEBUG_OPT4, "\n");
+ }
+ }
+ for_all_symbols(i, sym) {
+ if (dep_check_symbol(sym))
+ printf("\n");
+ }
+ for_all_symbols(i, sym) {
+ if (sym->dep && !sym->dep2) {
+ printd(DEBUG_OPT5, "o5: %s\n", sym->name);
+ print_expr(DEBUG_OPT5, sym->dep, 0); printd(DEBUG_OPT5, "\n");
+ eliminate_dep(sym, sym->dep);
+ print_expr(DEBUG_OPT5, sym->dep, 0); printd(DEBUG_OPT5, "\n");
+ }
+ }
+}
+
+int main(int ac, char **av)
+{
+ FILE *out = NULL;
+ char name[128];
+ struct symbol *sym;
+ struct statement *stmt;
+
+ if (ac > 2)
+ cml1debug = 1;
+ helplex("Documentation/Configure.help");
+ sprintf(name, "arch/%s/Config.help", av[1]);
+ helplex(name);
+ sprintf(name, "arch/%s/config.in", av[1]);
+ scan_init(name);
+ sym = lookup_symbol("CONFIG_ARCH", SYMBOL_STRING);
+ stmt = add_stmt(sym, T_DEFINE_STRING, NULL, lookup_symbol(av[1], SYMBOL_OTHER));
+ stmt->menu = NULL;
+ cml1parse();
+ optimize_config();
+#if 0
+ out = fopen("config.new", "w");
+ if (!out) {
+ printf("unable to open config.new!\n");
+ exit(1);
+ }
+#endif
+ print_files(out, name);
+
+ return 0;
+}
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
new file mode 100644
index 0000000..74c94c2
--- a/dev/null
+++ b/scripts/kconfig/conf.c
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static void conf(struct menu *menu);
+static void check_conf(struct menu *menu);
+
+enum {
+ ask_all,
+ ask_new,
+ ask_silent,
+ set_default,
+ set_yes,
+ set_mod,
+ set_no,
+ set_random
+} input_mode = ask_all;
+
+static int indent = 1;
+static int valid_stdin = 1;
+static int conf_cnt;
+static char line[128];
+static struct menu *rootEntry;
+
+static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
+
+#if 0
+static void printc(int ch)
+{
+ static int sep = 0;
+
+ if (!sep) {
+ putchar('[');
+ sep = 1;
+ } else if (ch)
+ putchar('/');
+ if (!ch) {
+ putchar(']');
+ putchar(' ');
+ sep = 0;
+ } else
+ putchar(ch);
+}
+#endif
+
+static void printo(const char *o)
+{
+ static int sep = 0;
+
+ if (!sep) {
+ putchar('(');
+ sep = 1;
+ } else if (o) {
+ putchar(',');
+ putchar(' ');
+ }
+ if (!o) {
+ putchar(')');
+ putchar(' ');
+ sep = 0;
+ } else
+ printf("%s", o);
+}
+
+static void strip(char *str)
+{
+ char *p = str;
+ int l;
+
+ while ((isspace(*p)))
+ p++;
+ l = strlen(p);
+ if (p != str)
+ memmove(str, p, l + 1);
+ if (!l)
+ return;
+ p = str + l - 1;
+ while ((isspace(*p)))
+ *p-- = 0;
+}
+
+static void conf_askvalue(struct symbol *sym, const char *def)
+{
+ enum symbol_type type = sym_get_type(sym);
+ tristate val;
+
+ if (!sym_has_value(sym))
+ printf("(NEW) ");
+
+ line[0] = '\n';
+ line[1] = 0;
+
+ switch (input_mode) {
+ case ask_new:
+ case ask_silent:
+ if (sym_has_value(sym)) {
+ printf("%s\n", def);
+ return;
+ }
+ if (!valid_stdin && input_mode == ask_silent) {
+ printf("aborted!\n\n");
+ printf("Console input/output is redirected. ");
+ printf("Run 'make oldconfig' to update configuration.\n\n");
+ exit(1);
+ }
+ case ask_all:
+ fgets(line, 128, stdin);
+ return;
+ case set_default:
+ printf("%s\n", def);
+ return;
+ default:
+ break;
+ }
+
+ switch (type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ printf("%s\n", def);
+ return;
+ default:
+ ;
+ }
+ switch (input_mode) {
+ case set_yes:
+ if (sym_tristate_within_range(sym, yes)) {
+ line[0] = 'y';
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ }
+ case set_mod:
+ if (type == S_TRISTATE) {
+ if (sym_tristate_within_range(sym, mod)) {
+ line[0] = 'm';
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ }
+ } else {
+ if (sym_tristate_within_range(sym, yes)) {
+ line[0] = 'y';
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ }
+ }
+ case set_no:
+ if (sym_tristate_within_range(sym, no)) {
+ line[0] = 'n';
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ }
+ case set_random:
+ do {
+ val = (tristate)(random() % 3);
+ } while (!sym_tristate_within_range(sym, val));
+ switch (val) {
+ case no: line[0] = 'n'; break;
+ case mod: line[0] = 'm'; break;
+ case yes: line[0] = 'y'; break;
+ }
+ line[1] = '\n';
+ line[2] = 0;
+ break;
+ default:
+ break;
+ }
+ printf("%s", line);
+}
+
+int conf_string(struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ const char *def, *help;
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", menu->prompt->text);
+ printf("(%s) ", sym->name);
+ def = sym_get_string_value(sym);
+ if (sym_get_string_value(sym))
+ printf("[%s] ", def);
+ conf_askvalue(sym, def);
+ switch (line[0]) {
+ case '\n':
+ break;
+ case '?':
+ /* print help */
+ if (line[1] == 0) {
+ help = nohelp_text;
+ if (menu->sym->help)
+ help = menu->sym->help;
+ printf("\n%s\n", menu->sym->help);
+ def = NULL;
+ break;
+ }
+ default:
+ line[strlen(line)-1] = 0;
+ def = line;
+ }
+ if (def && sym_set_string_value(sym, def))
+ return 0;
+ }
+}
+
+static int conf_sym(struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ int type;
+ tristate oldval, newval;
+ const char *help;
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", menu->prompt->text);
+ if (sym->name)
+ printf("(%s) ", sym->name);
+ type = sym_get_type(sym);
+ putchar('[');
+ oldval = sym_get_tristate_value(sym);
+ switch (oldval) {
+ case no:
+ putchar('N');
+ break;
+ case mod:
+ putchar('M');
+ break;
+ case yes:
+ putchar('Y');
+ break;
+ }
+ if (oldval != no && sym_tristate_within_range(sym, no))
+ printf("/n");
+ if (oldval != mod && sym_tristate_within_range(sym, mod))
+ printf("/m");
+ if (oldval != yes && sym_tristate_within_range(sym, yes))
+ printf("/y");
+ if (sym->help)
+ printf("/?");
+ printf("] ");
+ conf_askvalue(sym, sym_get_string_value(sym));
+ strip(line);
+
+ switch (line[0]) {
+ case 'n':
+ case 'N':
+ newval = no;
+ if (!line[1] || !strcmp(&line[1], "o"))
+ break;
+ continue;
+ case 'm':
+ case 'M':
+ newval = mod;
+ if (!line[1])
+ break;
+ continue;
+ case 'y':
+ case 'Y':
+ newval = yes;
+ if (!line[1] || !strcmp(&line[1], "es"))
+ break;
+ continue;
+ case 0:
+ newval = oldval;
+ break;
+ case '?':
+ goto help;
+ default:
+ continue;
+ }
+ if (sym_set_tristate_value(sym, newval))
+ return 0;
+help:
+ help = nohelp_text;
+ if (sym->help)
+ help = sym->help;
+ printf("\n%s\n", help);
+ }
+}
+
+static int conf_choice(struct menu *menu)
+{
+ struct symbol *sym, *def_sym;
+ struct menu *cmenu, *def_menu;
+ const char *help;
+ int type, len;
+ bool is_new;
+
+ sym = menu->sym;
+ type = sym_get_type(sym);
+ is_new = !sym_has_value(sym);
+ if (sym_is_changable(sym)) {
+ conf_sym(menu);
+ sym_calc_value(sym);
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ return 1;
+ case mod:
+ return 0;
+ case yes:
+ break;
+ }
+ } else {
+ sym->def = sym->curr;
+ if (S_TRI(sym->curr) == mod) {
+ printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
+ return 0;
+ }
+ }
+
+ while (1) {
+ printf("%*s%s ", indent - 1, "", menu_get_prompt(menu));
+ def_sym = sym_get_choice_value(sym);
+ def_menu = NULL;
+ for (cmenu = menu->list; cmenu; cmenu = cmenu->next) {
+ if (!menu_is_visible(cmenu))
+ continue;
+ printo(menu_get_prompt(cmenu));
+ if (cmenu->sym == def_sym)
+ def_menu = cmenu;
+ }
+ printo(NULL);
+ if (def_menu)
+ printf("[%s] ", menu_get_prompt(def_menu));
+ else {
+ printf("\n");
+ return 1;
+ }
+ switch (input_mode) {
+ case ask_new:
+ case ask_silent:
+ case ask_all:
+ conf_askvalue(sym, menu_get_prompt(def_menu));
+ strip(line);
+ break;
+ default:
+ line[0] = 0;
+ printf("\n");
+ }
+ if (line[0] == '?' && !line[1]) {
+ help = nohelp_text;
+ if (menu->sym->help)
+ help = menu->sym->help;
+ printf("\n%s\n", help);
+ continue;
+ }
+ if (line[0]) {
+ len = strlen(line) - 1;
+ line[len] = 0;
+
+ def_menu = NULL;
+ for (cmenu = menu->list; cmenu; cmenu = cmenu->next) {
+ if (!cmenu->sym || !menu_is_visible(cmenu))
+ continue;
+ if (!strncmp(line, menu_get_prompt(cmenu), len)) {
+ def_menu = cmenu;
+ break;
+ }
+ }
+ }
+ if (def_menu) {
+ sym_set_choice_value(sym, def_menu->sym);
+ if (def_menu->list) {
+ indent += 2;
+ conf(def_menu->list);
+ indent -= 2;
+ }
+ return 1;
+ }
+ }
+}
+
+static void conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (prop) {
+ const char *prompt;
+
+ switch (prop->type) {
+ case P_MENU:
+ if (input_mode == ask_silent && rootEntry != menu) {
+ check_conf(menu);
+ return;
+ }
+ case P_COMMENT:
+ prompt = menu_get_prompt(menu);
+ if (prompt)
+ printf("%*c\n%*c %s\n%*c\n",
+ indent, '*',
+ indent, '*', prompt,
+ indent, '*');
+ default:
+ ;
+ }
+ }
+
+ if (!sym)
+ goto conf_childs;
+
+ if (sym_is_choice(sym)) {
+ conf_choice(menu);
+ if (S_TRI(sym->curr) != mod)
+ return;
+ goto conf_childs;
+ }
+
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ conf_string(menu);
+ break;
+ default:
+ conf_sym(menu);
+ break;
+ }
+
+conf_childs:
+ if (sym)
+ indent += 2;
+ for (child = menu->list; child; child = child->next)
+ conf(child);
+ if (sym)
+ indent -= 2;
+}
+
+static void check_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct menu *child;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ if (!sym)
+ goto conf_childs;
+
+ if (sym_is_choice(sym)) {
+ if (!sym_has_value(sym)) {
+ if (!conf_cnt++)
+ printf("*\n* Restart config...\n*\n");
+ rootEntry = menu_get_parent_menu(menu);
+ conf(rootEntry);
+ }
+ if (sym_get_tristate_value(sym) != mod)
+ return;
+ goto conf_childs;
+ }
+
+ if (!sym_has_value(sym)) {
+ if (!conf_cnt++)
+ printf("*\n* Restart config...\n*\n");
+ rootEntry = menu_get_parent_menu(menu);
+ conf(rootEntry);
+ }
+
+conf_childs:
+ for (child = menu->list; child; child = child->next)
+ check_conf(child);
+}
+
+int main(int ac, char **av)
+{
+ const char *name;
+ struct stat tmpstat;
+
+ if (ac > 1 && av[1][0] == '-') {
+ switch (av[1][1]) {
+ case 'o':
+ input_mode = ask_new;
+ break;
+ case 's':
+ input_mode = ask_silent;
+ valid_stdin = isatty(0) && isatty(1) && isatty(2);
+ break;
+ case 'd':
+ input_mode = set_default;
+ break;
+ case 'n':
+ input_mode = set_no;
+ break;
+ case 'm':
+ input_mode = set_mod;
+ break;
+ case 'y':
+ input_mode = set_yes;
+ break;
+ case 'r':
+ input_mode = set_random;
+ srandom(time(NULL));
+ break;
+ case 'h':
+ case '?':
+ printf("%s [-o|-s] config\n", av[0]);
+ exit(0);
+ }
+ name = av[2];
+ } else
+ name = av[1];
+ conf_parse(name);
+ //zconfdump(stdout);
+ switch (input_mode) {
+ case set_default:
+ name = conf_get_default_confname();
+ if (conf_read(name)) {
+ printf("***\n"
+ "*** Can't find default configuration \"%s\"!\n"
+ "***\n", name);
+ exit(1);
+ }
+ break;
+ case ask_silent:
+ if (stat(".config", &tmpstat)) {
+ printf("***\n"
+ "*** You have not yet configured your kernel!\n"
+ "***\n"
+ "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
+ "*** \"make menuconfig\" or \"make xconfig\").\n"
+ "***\n");
+ exit(1);
+ }
+ case ask_all:
+ case ask_new:
+ conf_read(NULL);
+ break;
+ default:
+ break;
+ }
+
+ if (input_mode != ask_silent) {
+ rootEntry = &rootmenu;
+ conf(&rootmenu);
+ if (input_mode == ask_all) {
+ input_mode = ask_silent;
+ valid_stdin = 1;
+ }
+ }
+ do {
+ conf_cnt = 0;
+ check_conf(&rootmenu);
+ } while (conf_cnt);
+ conf_write(NULL);
+ return 0;
+}
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
new file mode 100644
index 0000000..0f5fd97
--- a/dev/null
+++ b/scripts/kconfig/confdata.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+const char conf_def_filename[] = ".config";
+char conf_filename[PATH_MAX+1];
+
+const char conf_defname[] = "arch/$ARCH/defconfig";
+
+const char *conf_confnames[] = {
+ ".config",
+ "/lib/modules/$UNAME_RELEASE/.config",
+ "/etc/kernel-config",
+ "/boot/config-$UNAME_RELEASE",
+ conf_defname,
+ NULL,
+};
+
+static char *conf_expand_value(const char *in)
+{
+ struct symbol *sym;
+ const char *src;
+ static char res_value[SYMBOL_MAXLENGTH];
+ char *dst, name[SYMBOL_MAXLENGTH];
+
+ res_value[0] = 0;
+ dst = name;
+ while ((src = strchr(in, '$'))) {
+ strncat(res_value, in, src - in);
+ src++;
+ dst = name;
+ while (isalnum(*src) || *src == '_')
+ *dst++ = *src++;
+ *dst = 0;
+ sym = sym_lookup(name, 0);
+ sym_calc_value(sym);
+ strcat(res_value, sym_get_string_value(sym));
+ in = src;
+ }
+ strcat(res_value, in);
+
+ return res_value;
+}
+
+char *conf_get_default_confname(void)
+{
+ return conf_expand_value(conf_defname);
+}
+
+int conf_read(const char *name)
+{
+ FILE *in = NULL;
+ char line[128];
+ char *p, *p2;
+ int lineno = 0;
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *e;
+ int i;
+
+ if (name) {
+ in = fopen(name, "r");
+ if (in)
+ strcpy(conf_filename, name);
+ } else {
+ const char **names = conf_confnames;
+ while ((name = *names++)) {
+ name = conf_expand_value(name);
+ in = fopen(name, "r");
+ if (in) {
+ printf("#\n"
+ "# using defaults found in %s\n"
+ "#\n", name);
+ break;
+ }
+ }
+ }
+
+ if (!in)
+ return 1;
+
+ for_all_symbols(i, sym) {
+ sym->flags |= SYMBOL_NEW;
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ if (S_VAL(sym->def)) {
+ free(S_VAL(sym->def));
+ S_VAL(sym->def) = NULL;
+ }
+ default:
+ ;
+ }
+ }
+
+ while (fgets(line, 128, in)) {
+ lineno++;
+ switch (line[0]) {
+ case '#':
+ if (memcmp(line + 2, "CONFIG_", 7))
+ continue;
+ p = strchr(line + 9, ' ');
+ if (!p)
+ continue;
+ *p++ = 0;
+ if (strncmp(p, "is not set", 10))
+ continue;
+ //printf("%s -> n\n", line + 9);
+ sym = sym_lookup(line + 9, 0);
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ sym->def = symbol_no.curr;
+ sym->flags &= ~SYMBOL_NEW;
+ break;
+ default:
+ ;
+ }
+ break;
+ case 'C':
+ if (memcmp(line, "CONFIG_", 7))
+ continue;
+ p = strchr(line + 7, '=');
+ if (!p)
+ continue;
+ *p++ = 0;
+ p2 = strchr(p, '\n');
+ if (p2)
+ *p2 = 0;
+ //printf("%s -> %s\n", line + 7, p);
+ sym = sym_find(line + 7);
+ if (!sym) {
+ fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 7);
+ break;
+ }
+ switch (sym->type) {
+ case S_BOOLEAN:
+ sym->def = symbol_yes.curr;
+ sym->flags &= ~SYMBOL_NEW;
+ break;
+ case S_TRISTATE:
+ if (p[0] == 'm')
+ sym->def = symbol_mod.curr;
+ else
+ sym->def = symbol_yes.curr;
+ sym->flags &= ~SYMBOL_NEW;
+ break;
+ case S_STRING:
+ if (*p++ != '"')
+ break;
+ for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
+ if (*p2 == '"') {
+ *p2 = 0;
+ break;
+ }
+ memmove(p2, p2 + 1, strlen(p2));
+ }
+ case S_INT:
+ case S_HEX:
+ if (sym_string_valid(sym, p)) {
+ S_VAL(sym->def) = strdup(p);
+ sym->flags &= ~SYMBOL_NEW;
+ } else
+ fprintf(stderr, "%s:%d:symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
+ break;
+ default:
+ ;
+ }
+ if (sym_is_choice_value(sym)) {
+ prop = sym_get_choice_prop(sym);
+ switch (S_TRI(sym->def)) {
+ case mod:
+ if (S_TRI(prop->def->def) == yes)
+ /* warn? */;
+ break;
+ case yes:
+ if (S_TRI(prop->def->def) != no)
+ /* warn? */;
+ S_VAL(prop->def->def) = sym;
+ break;
+ case no:
+ break;
+ }
+ S_TRI(prop->def->def) = S_TRI(sym->def);
+ }
+ break;
+ case '\n':
+ break;
+ default:
+ continue;
+ }
+ }
+ fclose(in);
+
+ for_all_symbols(i, sym) {
+ if (!sym_is_choice(sym))
+ continue;
+ prop = sym_get_choice_prop(sym);
+ sym->flags &= ~SYMBOL_NEW;
+ for (e = prop->dep; e; e = e->left.expr)
+ sym->flags |= e->right.sym->flags & SYMBOL_NEW;
+ }
+
+ sym_change_count = 1;
+
+ return 0;
+}
+
+int conf_write(const char *name)
+{
+ FILE *out, *out_h;
+ struct symbol *sym;
+ struct menu *menu;
+ char oldname[128];
+ int type, l;
+ const char *str;
+
+ out = fopen(".tmpconfig", "w");
+ if (!out)
+ return 1;
+ out_h = fopen(".tmpconfig.h", "w");
+ if (!out_h)
+ return 1;
+ fprintf(out, "#\n"
+ "# Automatically generated make config: don't edit\n"
+ "#\n");
+ fprintf(out_h, "/*\n"
+ " * Automatically generated C config: don't edit\n"
+ " */\n"
+ "#define AUTOCONF_INCLUDED\n");
+
+ if (!sym_change_count)
+ sym_clear_all_valid();
+
+ menu = rootmenu.list;
+ while (menu) {
+ sym = menu->sym;
+ if (!sym) {
+ if (!menu_is_visible(menu))
+ goto next;
+ str = menu_get_prompt(menu);
+ fprintf(out, "\n"
+ "#\n"
+ "# %s\n"
+ "#\n", str);
+ fprintf(out_h, "\n"
+ "/*\n"
+ " * %s\n"
+ " */\n", str);
+ } else if (!(sym->flags & SYMBOL_CHOICE)) {
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_WRITE))
+ goto next;
+ sym->flags &= ~SYMBOL_WRITE;
+ type = sym->type;
+ if (type == S_TRISTATE) {
+ sym_calc_value(modules_sym);
+ if (S_TRI(modules_sym->curr) == no)
+ type = S_BOOLEAN;
+ }
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (sym_get_tristate_value(sym)) {
+ case no:
+ fprintf(out, "# CONFIG_%s is not set\n", sym->name);
+ fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
+ break;
+ case mod:
+ fprintf(out, "CONFIG_%s=m\n", sym->name);
+ fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
+ break;
+ case yes:
+ fprintf(out, "CONFIG_%s=y\n", sym->name);
+ fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
+ break;
+ }
+ break;
+ case S_STRING:
+ // fix me
+ str = sym_get_string_value(sym);
+ fprintf(out, "CONFIG_%s=\"", sym->name);
+ fprintf(out_h, "#define CONFIG_%s \"", sym->name);
+ do {
+ l = strcspn(str, "\"\\");
+ if (l) {
+ fwrite(str, l, 1, out);
+ fwrite(str, l, 1, out_h);
+ }
+ str += l;
+ while (*str == '\\' || *str == '"') {
+ fprintf(out, "\\%c", *str);
+ fprintf(out_h, "\\%c", *str);
+ str++;
+ }
+ } while (*str);
+ fputs("\"\n", out);
+ fputs("\"\n", out_h);
+ break;
+ case S_HEX:
+ str = sym_get_string_value(sym);
+ if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
+ fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+ fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
+ break;
+ }
+ case S_INT:
+ str = sym_get_string_value(sym);
+ fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+ fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
+ break;
+ }
+ }
+
+ next:
+ if (menu->list) {
+ menu = menu->list;
+ continue;
+ }
+ if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+ fclose(out);
+ fclose(out_h);
+
+ if (!name) {
+ rename(".tmpconfig.h", "include/linux/autoconf.h");
+ name = conf_def_filename;
+ file_write_dep(NULL);
+ } else
+ unlink(".tmpconfig.h");
+
+ sprintf(oldname, "%s.old", name);
+ rename(name, oldname);
+ if (rename(".tmpconfig", name))
+ return 1;
+ strcpy(conf_filename, name);
+
+ sym_change_count = 0;
+
+ return 0;
+}
diff --git a/scripts/kconfig/convert-all b/scripts/kconfig/convert-all
new file mode 100644
index 0000000..53e52c5
--- a/dev/null
+++ b/scripts/kconfig/convert-all
@@ -0,0 +1,41 @@
+set -x
+#find \( -name "[Cc]onfig" -o -name "[Cc]onfig_*" \) -a ! -name "[Cc]onfig*.in" -a -type f -exec rm {} \;
+find -name "Kconfig*" -exec rm {} \;
+for a in alpha arm cris i386 ia64 m68k mips mips64 parisc ppc ppc64 s390 s390x sh sparc sparc64 um x86_64; do
+ $LKCSRC/lkcc $a >& log.$a
+ find -name "*.lkc" -exec mv {} {}-$a \;
+done
+set +x
+if false; then
+ #check differences between generated configs for archs
+ for c in `find -name "[cC]onfig.in"`; do
+ cn=`echo $c | sed 's,\(.*\)[cC]onfig\.in,\1Build.conf,'`
+ c1=''
+ for ca in $cn-*; do
+ if [ "$c1" = "" ]; then
+ echo "skip $ca"
+ c1=$ca
+ else
+ echo $ca
+ diff -u $c1 $ca
+ fi
+ done
+ done
+ exit 0
+fi
+rm *.lkc-*
+for a in alpha arm cris i386 ia64 m68k mips mips64 parisc ppc ppc64 s390 s390x sh sparc sparc64 um x86_64; do
+ for c in `find arch/$a -name "*.lkc-$a"`; do
+ cn=`echo $c | sed 's,\(.*\)\.lkc-.*,\1,'`
+ mv -v $c $cn
+ done
+done
+for c in `find -name "*.lkc-i386"`; do
+ cn=`echo $c | sed 's,\(.*\)\.lkc-.*,\1,'`
+ mv -v $c $cn
+ rm $cn.lkc-*
+done
+for c in `find -name "*.lkc-*"`; do
+ cn=`echo $c | sed 's,\(.*\)\.lkc-.*,\1,'`
+ mv -v $c $cn
+done
diff --git a/scripts/kconfig/example/miniconf.rb b/scripts/kconfig/example/miniconf.rb
new file mode 100644
index 0000000..e687fbb
--- a/dev/null
+++ b/scripts/kconfig/example/miniconf.rb
@@ -0,0 +1,32 @@
+require "kconfig"
+
+include Kconfig
+
+conf_parse("arch/i386/Kconfig")
+conf_read(nil)
+
+def conf(menu)
+ return unless menu.isVisible?
+ prompt = menu.prompt
+ if prompt.type == P_COMMENT || prompt.type == P_MENU
+ print "* #{prompt.text}\n"
+ end
+ sym = menu.sym
+ if sym
+ begin
+ print "#{prompt.text} (#{sym.get_string})? "
+ unless sym.isChangable?
+ print "\n"
+ break
+ end
+ val = gets.strip
+ end until val.empty? || sym.set_string(val)
+ end
+ menu.each do |child|
+ conf(child)
+ end
+end
+
+conf(Kconfig.rootmenu)
+
+conf_write(nil)
diff --git a/scripts/kconfig/example/query.rb b/scripts/kconfig/example/query.rb
new file mode 100644
index 0000000..2f47880
--- a/dev/null
+++ b/scripts/kconfig/example/query.rb
@@ -0,0 +1,34 @@
+require "kconfig"
+
+include Kconfig
+
+conf_parse("arch/i386/Kconfig")
+conf_read(nil)
+
+sym = Kconfig::Symbol.find(ARGV[0])
+if !sym
+ print "Symbol #{ARGV[0]} not found!\n"
+ exit
+end
+
+sym.calc_value
+print "symbol: #{sym.name}\n"
+print " type: #{Kconfig::Symbol.type_name(sym.type)}\n"
+print " value: #{sym.get_string}\n"
+print " choice\n" if sym.isChoice?
+print " choice value\n" if sym.isChoiceValue?
+print " properties:\n" if sym.prop
+sym.each do |prop|
+ case prop.type
+ when P_PROMPT
+ print " prompt: #{prop.text}\n"
+ when P_DEFAULT
+ prop.def.calc_value
+ print " default: #{prop.def.get_string}\n"
+ when P_CHOICE
+ print " choice reference\n"
+ else
+ print " unknown property: #{Property.type_name(prop.type)}\n"
+ end
+ print " dep: #{prop.visible.expr}\n" if prop.visible.expr
+end
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
new file mode 100644
index 0000000..d1af2a5
--- a/dev/null
+++ b/scripts/kconfig/expr.c
@@ -0,0 +1,1054 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+struct expr *expr_alloc_symbol(struct symbol *sym)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->type = E_SYMBOL;
+ e->left.sym = sym;
+ return e;
+}
+
+struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->type = type;
+ e->left.expr = ce;
+ return e;
+}
+
+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));
+ e->type = type;
+ e->left.expr = e1;
+ e->right.expr = e2;
+ return 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));
+ e->type = type;
+ e->left.sym = s1;
+ e->right.sym = s2;
+ return e;
+}
+
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
+{
+ if (!e1)
+ return e2;
+ return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
+}
+
+struct expr *expr_copy(struct expr *org)
+{
+ struct expr *e;
+
+ if (!org)
+ return NULL;
+
+ e = malloc(sizeof(*org));
+ memcpy(e, org, sizeof(*org));
+ switch (org->type) {
+ case E_SYMBOL:
+ e->left = org->left;
+ break;
+ case E_NOT:
+ e->left.expr = expr_copy(org->left.expr);
+ break;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ e->left.sym = org->left.sym;
+ e->right.sym = org->right.sym;
+ break;
+ case E_AND:
+ case E_OR:
+ case E_CHOICE:
+ e->left.expr = expr_copy(org->left.expr);
+ e->right.expr = expr_copy(org->right.expr);
+ break;
+ default:
+ printf("can't copy type %d\n", e->type);
+ free(e);
+ e = NULL;
+ break;
+ }
+
+ return e;
+}
+
+void expr_free(struct expr *e)
+{
+ if (!e)
+ return;
+
+ switch (e->type) {
+ case E_SYMBOL:
+ break;
+ case E_NOT:
+ expr_free(e->left.expr);
+ return;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ break;
+ case E_OR:
+ case E_AND:
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ break;
+ default:
+ printf("how to free type %d?\n", e->type);
+ break;
+ }
+ free(e);
+}
+
+static int trans_count;
+
+#define e1 (*ep1)
+#define e2 (*ep2)
+
+static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+ if (e1->type == type) {
+ __expr_eliminate_eq(type, &e1->left.expr, &e2);
+ __expr_eliminate_eq(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ __expr_eliminate_eq(type, &e1, &e2->left.expr);
+ __expr_eliminate_eq(type, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+ e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO)))
+ return;
+ if (!expr_eq(e1, e2))
+ return;
+ trans_count++;
+ expr_free(e1); expr_free(e2);
+ switch (type) {
+ case E_OR:
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ break;
+ case E_AND:
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ break;
+ default:
+ ;
+ }
+}
+
+void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
+{
+ if (!e1 || !e2 || e1->type != e2->type)
+ return;
+ __expr_eliminate_eq(e1->type, ep1, ep2);
+ e1 = expr_eliminate_yn(e1);
+ e2 = expr_eliminate_yn(e2);
+}
+
+#undef e1
+#undef e2
+
+int expr_eq(struct expr *e1, struct expr *e2)
+{
+ int res, old_count;
+
+ if (e1->type != e2->type)
+ return 0;
+ switch (e1->type) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
+ case E_SYMBOL:
+ return e1->left.sym == e2->left.sym;
+ case E_NOT:
+ return expr_eq(e1->left.expr, e2->left.expr);
+ case E_AND:
+ case E_OR:
+ e1 = expr_copy(e1);
+ e2 = expr_copy(e2);
+ old_count = trans_count;
+ expr_eliminate_eq(&e1, &e2);
+ res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
+ e1->left.sym == e2->left.sym);
+ expr_free(e1);
+ expr_free(e2);
+ trans_count = old_count;
+ return res;
+ case E_CHOICE:
+ case E_NONE:
+ /* panic */;
+ }
+
+ print_expr(0, e1, 0);
+ printf(" = ");
+ print_expr(0, e2, 0);
+ printf(" ?\n");
+
+ return 0;
+}
+
+struct expr *expr_eliminate_yn(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (e) switch (e->type) {
+ case E_AND:
+ e->left.expr = expr_eliminate_yn(e->left.expr);
+ e->right.expr = expr_eliminate_yn(e->right.expr);
+ if (e->left.expr->type == E_SYMBOL) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ if (e->right.expr->type == E_SYMBOL) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.expr = NULL;
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ }
+ }
+ break;
+ case E_OR:
+ e->left.expr = expr_eliminate_yn(e->left.expr);
+ e->right.expr = expr_eliminate_yn(e->right.expr);
+ if (e->left.expr->type == E_SYMBOL) {
+ if (e->left.expr->left.sym == &symbol_no) {
+ free(e->left.expr);
+ tmp = e->right.expr;
+ *e = *(e->right.expr);
+ free(tmp);
+ return e;
+ } else if (e->left.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ if (e->right.expr->type == E_SYMBOL) {
+ if (e->right.expr->left.sym == &symbol_no) {
+ free(e->right.expr);
+ tmp = e->left.expr;
+ *e = *(e->left.expr);
+ free(tmp);
+ return e;
+ } else if (e->right.expr->left.sym == &symbol_yes) {
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.expr = NULL;
+ return e;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+/*
+ * bool FOO!=n => FOO
+ */
+struct expr *expr_trans_bool(struct expr *e)
+{
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_AND:
+ case E_OR:
+ case E_NOT:
+ e->left.expr = expr_trans_bool(e->left.expr);
+ e->right.expr = expr_trans_bool(e->right.expr);
+ break;
+ case E_UNEQUAL:
+ // FOO!=n -> FOO
+ if (e->left.sym->type == S_TRISTATE) {
+ if (e->right.sym == &symbol_no) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+/*
+ * e1 || e2 -> ?
+ */
+struct expr *expr_join_or(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+ return NULL;
+ if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+ return NULL;
+ if (e1->type == E_NOT) {
+ tmp = e1->left.expr;
+ if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->type == E_NOT) {
+ if (e2->left.expr->type != E_SYMBOL)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+ return NULL;
+ if (sym1->type == S_TRISTATE) {
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='m') -> (a!='n')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
+ }
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
+ // (a='y') || (a='n') -> (a!='m')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
+ }
+ if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
+ // (a='m') || (a='n') -> (a!='y')
+ return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
+ }
+ }
+ if (sym1->type == S_BOOLEAN && sym1 == sym2) {
+ if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
+ (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
+ return expr_alloc_symbol(&symbol_yes);
+ }
+
+ printf("optimize ");
+ print_expr(0, e1, 0);
+ printf(" || ");
+ print_expr(0, e2, 0);
+ printf(" ?\n");
+ return NULL;
+}
+
+struct expr *expr_join_and(struct expr *e1, struct expr *e2)
+{
+ struct expr *tmp;
+ struct symbol *sym1, *sym2;
+
+ if (expr_eq(e1, e2))
+ return expr_copy(e1);
+ if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
+ return NULL;
+ if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
+ return NULL;
+ if (e1->type == E_NOT) {
+ tmp = e1->left.expr;
+ if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
+ return NULL;
+ sym1 = tmp->left.sym;
+ } else
+ sym1 = e1->left.sym;
+ if (e2->type == E_NOT) {
+ if (e2->left.expr->type != E_SYMBOL)
+ return NULL;
+ sym2 = e2->left.expr->left.sym;
+ } else
+ sym2 = e2->left.sym;
+ if (sym1 != sym2)
+ return NULL;
+ if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
+ return NULL;
+
+ if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
+ // (a) && (a='y') -> (a='y')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
+ // (a) && (a!='n') -> (a)
+ return expr_alloc_symbol(sym1);
+
+ if (sym1->type == S_TRISTATE) {
+ if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e1->right.sym;
+ if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
+ // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
+ sym2 = e2->right.sym;
+ if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
+ return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
+ : expr_alloc_symbol(&symbol_no);
+ }
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='n') -> (a='m')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
+
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
+ (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
+ // (a!='y') && (a!='m') -> (a='n')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
+
+ if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
+ ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
+ (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
+ // (a!='m') && (a!='n') -> (a='m')
+ return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
+
+ if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
+ (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
+ (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
+ (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
+ return NULL;
+ }
+ printf("optimize ");
+ print_expr(0, e1, 0);
+ printf(" && ");
+ print_expr(0, e2, 0);
+ printf(" ?\n");
+ return NULL;
+}
+
+static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp;
+
+ if (e1->type == type) {
+ expr_eliminate_dups1(type, &e1->left.expr, &e2);
+ expr_eliminate_dups1(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_eliminate_dups1(type, &e1, &e2->left.expr);
+ expr_eliminate_dups1(type, &e1, &e2->right.expr);
+ return;
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->type) {
+ case E_OR: case E_AND:
+ expr_eliminate_dups1(e1->type, &e1, &e1);
+ default:
+ ;
+ }
+
+ switch (type) {
+ case E_OR:
+ tmp = expr_join_or(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ case E_AND:
+ tmp = expr_join_and(e1, e2);
+ if (tmp) {
+ expr_free(e1); expr_free(e2);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = tmp;
+ trans_count++;
+ }
+ break;
+ default:
+ ;
+ }
+#undef e1
+#undef e2
+}
+
+static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ struct expr *tmp, *tmp1, *tmp2;
+
+ if (e1->type == type) {
+ expr_eliminate_dups2(type, &e1->left.expr, &e2);
+ expr_eliminate_dups2(type, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_eliminate_dups2(type, &e1, &e2->left.expr);
+ expr_eliminate_dups2(type, &e1, &e2->right.expr);
+ }
+ if (e1 == e2)
+ return;
+
+ switch (e1->type) {
+ case E_OR:
+ expr_eliminate_dups2(e1->type, &e1, &e1);
+ // (FOO || BAR) && (!FOO && !BAR) -> n
+ tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = expr_extract_eq_and(&tmp1, &tmp2);
+ if (expr_is_yes(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_no);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ case E_AND:
+ expr_eliminate_dups2(e1->type, &e1, &e1);
+ // (FOO && BAR) || (!FOO || !BAR) -> y
+ tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1)));
+ tmp2 = expr_copy(e2);
+ tmp = expr_extract_eq_or(&tmp1, &tmp2);
+ if (expr_is_no(tmp1)) {
+ expr_free(e1);
+ e1 = expr_alloc_symbol(&symbol_yes);
+ trans_count++;
+ }
+ expr_free(tmp2);
+ expr_free(tmp1);
+ expr_free(tmp);
+ break;
+ default:
+ ;
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *expr_eliminate_dups(struct expr *e)
+{
+ int oldcount;
+ if (!e)
+ return e;
+
+ oldcount = trans_count;
+ while (1) {
+ trans_count = 0;
+ switch (e->type) {
+ case E_OR: case E_AND:
+ expr_eliminate_dups1(e->type, &e, &e);
+ expr_eliminate_dups2(e->type, &e, &e);
+ default:
+ ;
+ }
+ if (!trans_count)
+ break;
+ e = expr_eliminate_yn(e);
+ }
+ trans_count = oldcount;
+ return e;
+}
+
+struct expr *expr_transform(struct expr *e)
+{
+ struct expr *tmp;
+
+ if (!e)
+ return NULL;
+ switch (e->type) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ case E_SYMBOL:
+ case E_CHOICE:
+ break;
+ default:
+ e->left.expr = expr_transform(e->left.expr);
+ e->right.expr = expr_transform(e->right.expr);
+ }
+
+ switch (e->type) {
+ case E_EQUAL:
+ if (e->left.sym->type != S_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ e->type = E_NOT;
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ break;
+ }
+ break;
+ case E_UNEQUAL:
+ if (e->left.sym->type != S_BOOLEAN)
+ break;
+ if (e->right.sym == &symbol_no) {
+ e->type = E_SYMBOL;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_mod) {
+ printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ e->right.sym = NULL;
+ break;
+ }
+ if (e->right.sym == &symbol_yes) {
+ e->type = E_NOT;
+ e->left.expr = expr_alloc_symbol(e->left.sym);
+ e->right.sym = NULL;
+ break;
+ }
+ break;
+ case E_NOT:
+ switch (e->left.expr->type) {
+ case E_NOT:
+ // !!a -> a
+ tmp = e->left.expr->left.expr;
+ free(e->left.expr);
+ free(e);
+ e = tmp;
+ e = expr_transform(e);
+ break;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ // !a='x' -> a!='x'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
+ break;
+ case E_OR:
+ // !(a || b) -> !a && !b
+ tmp = e->left.expr;
+ e->type = E_AND;
+ e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+ tmp->type = E_NOT;
+ tmp->right.expr = NULL;
+ e = expr_transform(e);
+ break;
+ case E_AND:
+ // !(a && b) -> !a || !b
+ tmp = e->left.expr;
+ e->type = E_OR;
+ e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
+ tmp->type = E_NOT;
+ tmp->right.expr = NULL;
+ e = expr_transform(e);
+ break;
+ case E_SYMBOL:
+ if (e->left.expr->left.sym == &symbol_yes) {
+ // !'y' -> 'n'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_no;
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_mod) {
+ // !'m' -> 'm'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_mod;
+ break;
+ }
+ if (e->left.expr->left.sym == &symbol_no) {
+ // !'n' -> 'y'
+ tmp = e->left.expr;
+ free(e);
+ e = tmp;
+ e->type = E_SYMBOL;
+ e->left.sym = &symbol_yes;
+ break;
+ }
+ break;
+ default:
+ ;
+ }
+ break;
+ default:
+ ;
+ }
+ return e;
+}
+
+int expr_contains_symbol(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return 0;
+
+ switch (dep->type) {
+ case E_AND:
+ case E_OR:
+ return expr_contains_symbol(dep->left.expr, sym) ||
+ expr_contains_symbol(dep->right.expr, sym);
+ case E_SYMBOL:
+ return dep->left.sym == sym;
+ case E_EQUAL:
+ case E_UNEQUAL:
+ return dep->left.sym == sym ||
+ dep->right.sym == sym;
+ case E_NOT:
+ return expr_contains_symbol(dep->left.expr, sym);
+ default:
+ ;
+ }
+ return 0;
+}
+
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return false;
+
+ switch (dep->type) {
+ case E_AND:
+ return expr_depends_symbol(dep->left.expr, sym) ||
+ expr_depends_symbol(dep->right.expr, sym);
+ case E_SYMBOL:
+ return dep->left.sym == sym;
+ case E_EQUAL:
+ if (dep->left.sym == sym) {
+ if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
+ return true;
+ }
+ break;
+ case E_UNEQUAL:
+ if (dep->left.sym == sym) {
+ if (dep->right.sym == &symbol_no)
+ return true;
+ }
+ break;
+ default:
+ ;
+ }
+ return false;
+}
+
+struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ expr_extract_eq(E_AND, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2)
+{
+ struct expr *tmp = NULL;
+ expr_extract_eq(E_OR, &tmp, ep1, ep2);
+ if (tmp) {
+ *ep1 = expr_eliminate_yn(*ep1);
+ *ep2 = expr_eliminate_yn(*ep2);
+ }
+ return tmp;
+}
+
+void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2)
+{
+#define e1 (*ep1)
+#define e2 (*ep2)
+ if (e1->type == type) {
+ expr_extract_eq(type, ep, &e1->left.expr, &e2);
+ expr_extract_eq(type, ep, &e1->right.expr, &e2);
+ return;
+ }
+ if (e2->type == type) {
+ expr_extract_eq(type, ep, ep1, &e2->left.expr);
+ expr_extract_eq(type, ep, ep1, &e2->right.expr);
+ return;
+ }
+ if (expr_eq(e1, e2)) {
+ *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1;
+ expr_free(e2);
+ if (type == E_AND) {
+ e1 = expr_alloc_symbol(&symbol_yes);
+ e2 = expr_alloc_symbol(&symbol_yes);
+ } else if (type == E_OR) {
+ e1 = expr_alloc_symbol(&symbol_no);
+ e2 = expr_alloc_symbol(&symbol_no);
+ }
+ }
+#undef e1
+#undef e2
+}
+
+struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
+{
+ struct expr *e1, *e2;
+
+ if (!e) {
+ e = expr_alloc_symbol(sym);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ }
+ switch (e->type) {
+ case E_AND:
+ e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+ e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(E_AND, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(E_OR, e1, e2);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ case E_OR:
+ e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
+ e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
+ if (sym == &symbol_yes)
+ e = expr_alloc_two(E_OR, e1, e2);
+ if (sym == &symbol_no)
+ e = expr_alloc_two(E_AND, e1, e2);
+ if (type == E_UNEQUAL)
+ e = expr_alloc_one(E_NOT, e);
+ return e;
+ case E_NOT:
+ return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
+ case E_UNEQUAL:
+ case E_EQUAL:
+ if (type == E_EQUAL) {
+ if (sym == &symbol_yes)
+ return expr_copy(e);
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_no);
+ if (sym == &symbol_no)
+ return expr_alloc_one(E_NOT, expr_copy(e));
+ } else {
+ if (sym == &symbol_yes)
+ return expr_alloc_one(E_NOT, expr_copy(e));
+ if (sym == &symbol_mod)
+ return expr_alloc_symbol(&symbol_yes);
+ if (sym == &symbol_no)
+ return expr_copy(e);
+ }
+ break;
+ case E_SYMBOL:
+ return expr_alloc_comp(type, e->left.sym, sym);
+ case E_CHOICE:
+ case E_NONE:
+ /* panic */;
+ }
+ return NULL;
+}
+
+tristate expr_calc_value(struct expr *e)
+{
+ tristate val1, val2;
+ const char *str1, *str2;
+
+ if (!e)
+ return yes;
+
+ switch (e->type) {
+ case E_SYMBOL:
+ sym_calc_value(e->left.sym);
+ return S_TRI(e->left.sym->curr);
+ case E_AND:
+ val1 = expr_calc_value(e->left.expr);
+ val2 = expr_calc_value(e->right.expr);
+ return E_AND(val1, val2);
+ case E_OR:
+ val1 = expr_calc_value(e->left.expr);
+ val2 = expr_calc_value(e->right.expr);
+ return E_OR(val1, val2);
+ case E_NOT:
+ val1 = expr_calc_value(e->left.expr);
+ return E_NOT(val1);
+ case E_EQUAL:
+ sym_calc_value(e->left.sym);
+ sym_calc_value(e->right.sym);
+ str1 = sym_get_string_value(e->left.sym);
+ str2 = sym_get_string_value(e->right.sym);
+ return !strcmp(str1, str2) ? yes : no;
+ case E_UNEQUAL:
+ sym_calc_value(e->left.sym);
+ sym_calc_value(e->right.sym);
+ str1 = sym_get_string_value(e->left.sym);
+ str2 = sym_get_string_value(e->right.sym);
+ return !strcmp(str1, str2) ? no : yes;
+ default:
+ printf("expr_calc_value: %d?\n", e->type);
+ return no;
+ }
+}
+
+int expr_compare_type(enum expr_type t1, enum expr_type t2)
+{
+#if 0
+ return 1;
+#else
+ if (t1 == t2)
+ return 0;
+ switch (t1) {
+ case E_EQUAL:
+ case E_UNEQUAL:
+ if (t2 == E_NOT)
+ return 1;
+ case E_NOT:
+ if (t2 == E_AND)
+ return 1;
+ case E_AND:
+ if (t2 == E_OR)
+ return 1;
+ case E_OR:
+ if (t2 == E_CHOICE)
+ return 1;
+ case E_CHOICE:
+ if (t2 == 0)
+ return 1;
+ default:
+ return -1;
+ }
+ printf("[%dgt%d?]", t1, t2);
+ return 0;
+#endif
+}
+
+void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken)
+{
+ if (!e) {
+ fn(data, "y");
+ return;
+ }
+
+ if (expr_compare_type(prevtoken, e->type) > 0)
+ fn(data, "(");
+ switch (e->type) {
+ case E_SYMBOL:
+ if (e->left.sym->name)
+ fn(data, e->left.sym->name);
+ else
+ fn(data, "<choice>");
+ break;
+ case E_NOT:
+ fn(data, "!");
+ expr_print(e->left.expr, fn, data, E_NOT);
+ break;
+ case E_EQUAL:
+ fn(data, e->left.sym->name);
+ fn(data, "=");
+ fn(data, e->right.sym->name);
+ break;
+ case E_UNEQUAL:
+ fn(data, e->left.sym->name);
+ fn(data, "!=");
+ fn(data, e->right.sym->name);
+ break;
+ case E_OR:
+ expr_print(e->left.expr, fn, data, E_OR);
+ fn(data, " || ");
+ expr_print(e->right.expr, fn, data, E_OR);
+ break;
+ case E_AND:
+ expr_print(e->left.expr, fn, data, E_AND);
+ fn(data, " && ");
+ expr_print(e->right.expr, fn, data, E_AND);
+ break;
+ case E_CHOICE:
+ if (e->left.expr) {
+ expr_print(e->left.expr, fn, data, E_CHOICE);
+ fn(data, " ^ ");
+ }
+ fn(data, e->right.sym->name);
+ break;
+ default:
+ {
+ char buf[32];
+ sprintf(buf, "<unknown type %d>", e->type);
+ fn(data, buf);
+ break;
+ }
+ }
+ if (expr_compare_type(prevtoken, e->type) > 0)
+ fn(data, ")");
+}
+
+static void expr_print_file_helper(void *data, const char *str)
+{
+ fwrite(str, strlen(str), 1, data);
+}
+
+void expr_fprint(struct expr *e, FILE *out)
+{
+ expr_print(e, expr_print_file_helper, out, E_NONE);
+}
+
+void print_expr(int mask, struct expr *e, int prevtoken)
+{
+ if (!(cdebug & mask))
+ return;
+ expr_fprint(e, stdout);
+}
+
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
new file mode 100644
index 0000000..fd9c32a
--- a/dev/null
+++ b/scripts/kconfig/expr.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef EXPR_H
+#define EXPR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+struct file {
+ struct file *next;
+ struct file *parent;
+#ifdef CML1
+ struct statement *stmt;
+ struct statement *last_stmt;
+#endif
+ char *name;
+ int lineno;
+ int flags;
+};
+
+#define FILE_BUSY 0x0001
+#define FILE_SCANNED 0x0002
+#define FILE_PRINTED 0x0004
+
+typedef enum tristate {
+ no, mod, yes
+} tristate;
+
+enum expr_type {
+ E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL
+};
+
+union expr_data {
+ struct expr *expr;
+ struct symbol *sym;
+};
+
+struct expr {
+#ifdef CML1
+ int token;
+#else
+ enum expr_type type;
+#endif
+ union expr_data left, right;
+};
+
+#define E_TRI(ev) ((ev).tri)
+#define E_EXPR(ev) ((ev).expr)
+#define E_CALC(ev) (E_TRI(ev) = expr_calc_value(E_EXPR(ev)))
+
+#define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
+#define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
+#define E_NOT(dep) (2-(dep))
+
+struct expr_value {
+ struct expr *expr;
+ tristate tri;
+};
+
+#define S_VAL(sv) ((sv).value)
+#define S_TRI(sv) ((sv).tri)
+#define S_EQ(sv1, sv2) (S_VAL(sv1) == S_VAL(sv2) || !strcmp(S_VAL(sv1), S_VAL(sv2)))
+
+struct symbol_value {
+ void *value;
+ tristate tri;
+};
+
+enum symbol_type {
+ S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
+};
+
+struct symbol {
+ struct symbol *next;
+ char *name;
+ char *help;
+#ifdef CML1
+ int type;
+#else
+ enum symbol_type type;
+#endif
+ struct symbol_value curr, def;
+ tristate visible;
+ int flags;
+ struct property *prop;
+ struct expr *dep, *dep2;
+ struct menu *menu;
+};
+
+#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
+
+#ifdef CML1
+#define SYMBOL_UNKNOWN S_UNKNOWN
+#define SYMBOL_BOOLEAN S_BOOLEAN
+#define SYMBOL_TRISTATE S_TRISTATE
+#define SYMBOL_INT S_INT
+#define SYMBOL_HEX S_HEX
+#define SYMBOL_STRING S_STRING
+#define SYMBOL_OTHER S_OTHER
+#endif
+
+#define SYMBOL_YES 0x0001
+#define SYMBOL_MOD 0x0002
+#define SYMBOL_NO 0x0004
+#define SYMBOL_CONST 0x0007
+#define SYMBOL_CHECK 0x0008
+#define SYMBOL_CHOICE 0x0010
+#define SYMBOL_CHOICEVAL 0x0020
+#define SYMBOL_PRINTED 0x0040
+#define SYMBOL_VALID 0x0080
+#define SYMBOL_OPTIONAL 0x0100
+#define SYMBOL_WRITE 0x0200
+#define SYMBOL_CHANGED 0x0400
+#define SYMBOL_NEW 0x0800
+#define SYMBOL_AUTO 0x1000
+
+#define SYMBOL_MAXLENGTH 256
+#define SYMBOL_HASHSIZE 257
+#define SYMBOL_HASHMASK 0xff
+
+enum prop_type {
+ P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_ROOTMENU, P_DEFAULT, P_CHOICE
+};
+
+struct property {
+ struct property *next;
+ struct symbol *sym;
+#ifdef CML1
+ int token;
+#else
+ enum prop_type type;
+#endif
+ const char *text;
+ struct symbol *def;
+ struct expr_value visible;
+ struct expr *dep;
+ struct expr *dep2;
+ struct menu *menu;
+ struct file *file;
+ int lineno;
+#ifdef CML1
+ struct property *next_pos;
+#endif
+};
+
+#define for_all_properties(sym, st, tok) \
+ for (st = sym->prop; st; st = st->next) \
+ if (st->type == (tok))
+#define for_all_prompts(sym, st) for_all_properties(sym, st, P_PROMPT)
+#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
+#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
+
+struct menu {
+ struct menu *next;
+ struct menu *parent;
+ struct menu *list;
+ struct symbol *sym;
+ struct property *prompt;
+ struct expr *dep;
+ //char *help;
+ struct file *file;
+ int lineno;
+ //void *data;
+};
+
+#ifndef SWIG
+
+extern struct file *file_list;
+extern struct file *current_file;
+struct file *lookup_file(const char *name);
+
+extern struct symbol symbol_yes, symbol_no, symbol_mod;
+extern struct symbol *modules_sym;
+extern int cdebug;
+extern int print_type;
+struct expr *expr_alloc_symbol(struct symbol *sym);
+#ifdef CML1
+struct expr *expr_alloc_one(int token, struct expr *ce);
+struct expr *expr_alloc_two(int token, struct expr *e1, struct expr *e2);
+struct expr *expr_alloc_comp(int token, struct symbol *s1, struct symbol *s2);
+#else
+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 *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
+#endif
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
+struct expr *expr_copy(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);
+tristate expr_calc_value(struct expr *e);
+struct expr *expr_eliminate_yn(struct expr *e);
+struct expr *expr_trans_bool(struct expr *e);
+struct expr *expr_eliminate_dups(struct expr *e);
+struct expr *expr_transform(struct expr *e);
+int expr_contains_symbol(struct expr *dep, struct symbol *sym);
+bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
+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);
+
+void expr_fprint(struct expr *e, FILE *out);
+void print_expr(int mask, struct expr *e, int prevtoken);
+
+#ifdef CML1
+static inline int expr_is_yes(struct expr *e)
+{
+ return !e || (e->token == WORD && e->left.sym == &symbol_yes);
+}
+
+static inline int expr_is_no(struct expr *e)
+{
+ return e && (e->token == WORD && e->left.sym == &symbol_no);
+}
+#else
+static inline int expr_is_yes(struct expr *e)
+{
+ return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
+}
+
+static inline int expr_is_no(struct expr *e)
+{
+ return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
+}
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EXPR_H */
diff --git a/scripts/kconfig/expr1.c b/scripts/kconfig/expr1.c
new file mode 100644
index 0000000..8b45801
--- a/dev/null
+++ b/scripts/kconfig/expr1.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "cml1.h"
+
+struct file *file_list;
+struct file *current_file;
+
+struct symbol symbol_yes = {
+ name: "y",
+ curr: { "y", yes },
+ flags: SYMBOL_YES|SYMBOL_VALID,
+}, symbol_mod = {
+ name: "m",
+ curr: { "m", mod },
+ flags: SYMBOL_MOD|SYMBOL_VALID,
+}, symbol_no = {
+ name: "n",
+ curr: { "n", no },
+ flags: SYMBOL_NO|SYMBOL_VALID,
+}, symbol_empty = {
+ name: "",
+ curr: { "", no },
+ flags: SYMBOL_VALID,
+};
+
+struct expr *expr_alloc_symbol(struct symbol *sym)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->token = T_WORD;
+ e->left.sym = sym;
+ return e;
+}
+
+struct expr *expr_alloc_one(int token, struct expr *ce)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->token = token;
+ e->left.expr = ce;
+ return e;
+}
+
+struct expr *expr_alloc_two(int token, struct expr *e1, struct expr *e2)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->token = token;
+ e->left.expr = e1;
+ e->right.expr = e2;
+ return e;
+}
+
+struct expr *expr_alloc_comp(int token, struct symbol *s1, struct symbol *s2)
+{
+ struct expr *e = malloc(sizeof(*e));
+ memset(e, 0, sizeof(*e));
+ e->token = token;
+ e->left.sym = s1;
+ e->right.sym = s2;
+ return e;
+}
+
+struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
+{
+ if (!e1)
+ return e2;
+ return e2 ? expr_alloc_two(T_AND, e1, e2) : e1;
+}
+
+struct expr *expr_copy(struct expr *org)
+{
+ struct expr *e;
+
+ if (!org)
+ return NULL;
+
+ e = malloc(sizeof(*org));
+ memcpy(e, org, sizeof(*org));
+ switch (org->token) {
+ case T_WORD:
+ e->left = org->left;
+ break;
+ case '!':
+ e->left.expr = expr_copy(org->left.expr);
+ break;
+ case '=':
+ case T_UNEQUAL:
+ e->left.sym = org->left.sym;
+ e->right.sym = org->right.sym;
+ break;
+ case T_OR:
+ case T_AND:
+ case '&':
+ case '|':
+ case '^':
+ case T_IF:
+ case T_ELSE:
+ e->left.expr = expr_copy(org->left.expr);
+ e->right.expr = expr_copy(org->right.expr);
+ break;
+ default:
+ printf("can't copy token %d\n", e->token);
+ free(e);
+ e = NULL;
+ break;
+ }
+
+ return e;
+}
+
+void expr_free(struct expr *e)
+{
+ if (!e)
+ return;
+
+ switch (e->token) {
+ case T_WORD:
+ break;
+ case '!':
+ expr_free(e->left.expr);
+ return;
+ case '=':
+ case T_UNEQUAL:
+ break;
+ case '|':
+ case T_OR:
+ case T_AND:
+ case '&':
+ case T_IF:
+ case T_ELSE:
+ expr_free(e->left.expr);
+ expr_free(e->right.expr);
+ break;
+ default:
+ printf("how to free token %d?\n", e->token);
+ break;
+ }
+ free(e);
+}
+
+static inline int token_gt(int t1, int t2)
+{
+#if 0
+ return 1;
+#else
+ switch (t1) {
+ case '=':
+ case T_UNEQUAL:
+ if (t2 == '!')
+ return 1;
+ case '!':
+ if (t2 == T_AND || t2 == T_IF || t2 == T_ELSE || t2 == '&')
+ return 1;
+ case '&':
+ case T_IF:
+ case T_ELSE:
+ case T_AND:
+ if (t2 == T_OR || t2 == '|')
+ return 1;
+ case '|':
+ case T_OR:
+ if (t2 == '^')
+ return 1;
+ case '^':
+ if (t2 == 0)
+ return 1;
+ case 0:
+ return 0;
+ }
+ printf("[%dgt%d?]", t1, t2);
+ return 0;
+#endif
+}
+
+int print_type = 1;
+
+static void print_sym(FILE *out, struct symbol *sym)
+{
+ fprintf(out, "%s", sym->name);
+ if (print_type)
+ fprintf(out, "%s",
+ sym->type == SYMBOL_BOOLEAN ? "?" :
+ sym->type == SYMBOL_TRISTATE ? "??" :
+ sym->type == SYMBOL_HEX ? "h" :
+ sym->type == SYMBOL_INT ? "i" :
+ sym->type == SYMBOL_STRING ? "s" :
+ "");
+}
+
+void fprint_expr(FILE *out, struct expr *e, int prevtoken)
+{
+ if (!e) {
+ fprintf(out, "<none>");
+ return;
+ }
+
+ switch (e->token) {
+ case T_WORD:
+ print_sym(out, e->left.sym);
+ break;
+ case '!':
+ if (token_gt(prevtoken, '!'))
+ fprintf(out, "(");
+ fprintf(out, "!");
+ fprint_expr(out, e->left.expr, '!');
+ if (token_gt(prevtoken, '!'))
+ fprintf(out, ")");
+ break;
+ case '=':
+ if (token_gt(prevtoken, '='))
+ fprintf(out, "(");
+ print_sym(out, e->left.sym);
+ fprintf(out, "=");
+ print_sym(out, e->right.sym);
+ if (token_gt(prevtoken, '='))
+ fprintf(out, ")");
+ break;
+ case T_UNEQUAL:
+ if (token_gt(prevtoken, T_UNEQUAL))
+ fprintf(out, "(");
+ print_sym(out, e->left.sym);
+ fprintf(out, "!=");
+ print_sym(out, e->right.sym);
+ if (token_gt(prevtoken, T_UNEQUAL))
+ fprintf(out, ")");
+ break;
+ case T_OR:
+ if (token_gt(prevtoken, T_OR))
+ fprintf(out, "(");
+ fprint_expr(out, e->left.expr, T_OR);
+ fprintf(out, " || ");
+ fprint_expr(out, e->right.expr, T_OR);
+ if (token_gt(prevtoken, T_OR))
+ fprintf(out, ")");
+ break;
+ case T_AND:
+ if (token_gt(prevtoken, T_AND))
+ fprintf(out, "(");
+ fprint_expr(out, e->left.expr, T_AND);
+ fprintf(out, " && ");
+ fprint_expr(out, e->right.expr, T_AND);
+ if (token_gt(prevtoken, T_AND))
+ fprintf(out, ")");
+ break;
+ case '|':
+ if (token_gt(prevtoken, '|'))
+ fprintf(out, "(");
+ fprint_expr(out, e->left.expr, '|');
+ fprintf(out, " || ");
+ fprint_expr(out, e->right.expr, '|');
+ if (token_gt(prevtoken, '|'))
+ fprintf(out, ")");
+ break;
+ case '&':
+ if (token_gt(prevtoken, '&'))
+ fprintf(out, "(");
+ fprint_expr(out, e->left.expr, '&');
+ if (print_type)
+ fprintf(out, " & ");
+ else
+ fprintf(out, " && ");
+ fprint_expr(out, e->right.expr, '&');
+ if (token_gt(prevtoken, '&'))
+ fprintf(out, ")");
+ break;
+ case '^':
+ if (e->left.expr) {
+ fprint_expr(out, e->left.expr, '^');
+ fprintf(out, " ^ ");
+ }
+ fprintf(out, "%s", e->right.sym->name);
+ break;
+ case T_IF:
+ if (token_gt(prevtoken, T_IF))
+ fprintf(out, "[");
+ if (e->right.expr) {
+ fprint_expr(out, e->right.expr, T_IF);
+ fprintf(out, " && ");
+ }
+ fprint_expr(out, e->left.expr, T_IF);
+ if (token_gt(prevtoken, T_IF))
+ fprintf(out, "]");
+ break;
+ case T_ELSE:
+ if (token_gt(prevtoken, T_ELSE))
+ fprintf(out, "[");
+ //fprintf(out, "[");
+ if (e->right.expr) {
+ fprint_expr(out, e->right.expr, T_ELSE);
+ fprintf(out, " && ");
+ }
+ fprintf(out, "!");
+ fprint_expr(out, e->left.expr, '!');
+ if (token_gt(prevtoken, T_ELSE))
+ fprintf(out, "]");
+ break;
+ default:
+ fprintf(out, "<unknown token %d>", e->token);
+ break;
+ }
+}
+
+void print_expr(int mask, struct expr *e, int prevtoken)
+{
+ if (!(cdebug & mask))
+ return;
+ fprint_expr(stdout, e, prevtoken);
+}
+
+struct file *lookup_file(const char *name)
+{
+ struct file *file;
+
+ for (file = file_list; file; file = file->next) {
+ if (!strcmp(name, file->name))
+ return file;
+ }
+
+ file = malloc(sizeof(*file));
+ memset(file, 0, sizeof(*file));
+ file->name = strdup(name);
+ file->next = file_list;
+ file_list = file;
+ return file;
+}
diff --git a/scripts/kconfig/extconf.rb b/scripts/kconfig/extconf.rb
new file mode 100644
index 0000000..051446d
--- a/dev/null
+++ b/scripts/kconfig/extconf.rb
@@ -0,0 +1,5 @@
+require 'mkmf'
+$CFLAGS = '-I..'
+$LDFLAGS = '-ldl'
+$objs = ["kconfig_wrap.o"]
+create_makefile 'kconfig'
diff --git a/scripts/kconfig/fixup-all.diff b/scripts/kconfig/fixup-all.diff
new file mode 100644
index 0000000..0844c98
--- a/dev/null
+++ b/scripts/kconfig/fixup-all.diff
@@ -0,0 +1,925 @@
+--- ./arch/alpha/Kconfig.org 2002-10-16 17:09:12.000000000 +0200
++++ ./arch/alpha/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -791,10 +791,10 @@
+
+ endmenu
+
+-#if [ "$CONFIG_PCI" = "y" ]; then
++if PCI
+ source "drivers/message/fusion/Kconfig"
++endif
+
+-#fi
+ source "net/Kconfig"
+
+
+@@ -1046,5 +1046,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/arm/Kconfig.org 2002-10-16 17:09:13.000000000 +0200
++++ ./arch/arm/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -876,10 +876,10 @@
+
+ source "drivers/parport/Kconfig"
+
+-#if [ "$CONFIG_ALIGNMENT_TRAP" = "y" ]; then
++if ALIGNMENT_TRAP
+ source "drivers/mtd/Kconfig"
++endif
+
+-#else
+ source "drivers/pnp/Kconfig"
+
+ source "drivers/block/Kconfig"
+@@ -1233,5 +1233,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/cris/Kconfig.org 2002-10-16 17:09:14.000000000 +0200
++++ ./arch/cris/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -749,5 +749,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/i386/Kconfig.org 2002-10-16 17:09:15.000000000 +0200
++++ ./arch/i386/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -1430,7 +1430,8 @@
+ Read the file <file:Documentation/svga.txt> for more information
+ about the Video mode selection support. If unsure, say N.
+
+-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++if EXPERIMENTAL
++
+ config MDA_CONSOLE
+ tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
+ ---help---
+@@ -1449,7 +1450,8 @@
+
+ source "drivers/video/Kconfig"
+
+-#fi
++endif
++
+ endmenu
+
+
+@@ -1625,5 +1627,3 @@
+ bool
+ default y
+
+-source "Kconfig"
+-
+--- ./arch/ia64/Kconfig.org 2002-10-16 17:09:16.000000000 +0200
++++ ./arch/ia64/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -120,43 +120,10 @@
+
+ choice
+ prompt "Kernel page size"
+- depends on ITANIUM
+- default IA64_PAGE_SIZE_16KB_1
+-
+-config IA64_PAGE_SIZE_4KB_1
+- bool "4KB"
+-
+-config IA64_PAGE_SIZE_8KB_1
+- bool "8KB"
+-
+-config IA64_PAGE_SIZE_16KB_1
+- bool "16KB"
+-
+-endchoice
+-
+-choice
+- prompt "Kernel page size"
+- depends on !ITANIUM
+- default IA64_PAGE_SIZE_16KB_2
+-
+-config IA64_PAGE_SIZE_4KB_2
+- bool "4KB"
+-
+-config IA64_PAGE_SIZE_8KB_2
+- bool "8KB"
+-
+-config IA64_PAGE_SIZE_16KB_2
+- bool "16KB"
+-
+-config IA64_PAGE_SIZE_64KB
+- bool "64KB"
+-
+-endchoice
++ default IA64_PAGE_SIZE_16KB
+
+ config IA64_PAGE_SIZE_4KB
+- bool
+- depends on IA64_PAGE_SIZE_4KB_1 || IA64_PAGE_SIZE_4KB_2
+- default y
++ bool "4KB"
+ ---help---
+ This lets you select the page size of the kernel. For best IA-64
+ performance, a page size of 8KB or 16KB is recommended. For best
+@@ -173,14 +140,16 @@
+ If you don't know what to do, choose 8KB.
+
+ config IA64_PAGE_SIZE_8KB
+- bool
+- depends on IA64_PAGE_SIZE_8KB_1 || IA64_PAGE_SIZE_8KB_2
+- default y
++ bool "8KB"
+
+ config IA64_PAGE_SIZE_16KB
+- bool
+- depends on IA64_PAGE_SIZE_16KB_1 || IA64_PAGE_SIZE_16KB_2
+- default y
++ bool "16KB"
++
++config IA64_PAGE_SIZE_64KB
++ depends on !ITANIUM
++ bool "64KB"
++
++endchoice
+
+ config ACPI
+ bool
+@@ -403,87 +372,33 @@
+
+ choice
+ prompt "IA-64 Huge TLB Page Size"
+- depends on HUGETLB_PAGE && MCKINLEY
+- default HUGETLB_PAGE_SIZE_16MB_1
++ depends on HUGETLB_PAGE
++ default HUGETLB_PAGE_SIZE_16MB
+
+ config HUGETLB_PAGE_SIZE_4GB
++ depends on MCKINLEY
+ bool "4GB"
+
+-config HUGETLB_PAGE_SIZE_256MB_1
+- bool "256MB"
+-
+-config HUGETLB_PAGE_SIZE_64MB_1
+- bool "64MB"
+-
+-config HUGETLB_PAGE_SIZE_16MB_1
+- bool "16MB"
+-
+-config HUGETLB_PAGE_SIZE_4MB_1
+- bool "4MB"
+-
+-config HUGETLB_PAGE_SIZE_1MB_1
+- bool "1MB"
+-
+-config HUGETLB_PAGE_SIZE_256KB_1
+- bool "256KB"
+-
+-endchoice
+-
+-choice
+- prompt "IA-64 Huge TLB Page Size"
+- depends on HUGETLB_PAGE && !MCKINLEY
+- default HUGETLB_PAGE_SIZE_16MB_2
+-
+-config HUGETLB_PAGE_SIZE_256MB_2
++config HUGETLB_PAGE_SIZE_256MB
+ bool "256MB"
+
+-config HUGETLB_PAGE_SIZE_64MB_2
++config HUGETLB_PAGE_SIZE_64MB
+ bool "64MB"
+
+-config HUGETLB_PAGE_SIZE_16MB_2
++config HUGETLB_PAGE_SIZE_16MB
+ bool "16MB"
+
+-config HUGETLB_PAGE_SIZE_4MB_2
++config HUGETLB_PAGE_SIZE_4MB
+ bool "4MB"
+
+-config HUGETLB_PAGE_SIZE_1MB_2
++config HUGETLB_PAGE_SIZE_1MB
+ bool "1MB"
+
+-config HUGETLB_PAGE_SIZE_256KB_2
++config HUGETLB_PAGE_SIZE_256KB
+ bool "256KB"
+
+ endchoice
+
+-config HUGETLB_PAGE_SIZE_256MB
+- bool
+- depends on HUGETLB_PAGE_SIZE_256MB_1 || HUGETLB_PAGE_SIZE_256MB_2
+- default y
+-
+-config HUGETLB_PAGE_SIZE_64MB
+- bool
+- depends on HUGETLB_PAGE_SIZE_64MB_1 || HUGETLB_PAGE_SIZE_64MB_2
+- default y
+-
+-config HUGETLB_PAGE_SIZE_16MB
+- bool
+- depends on HUGETLB_PAGE_SIZE_16MB_1 || HUGETLB_PAGE_SIZE_16MB_2
+- default y
+-
+-config HUGETLB_PAGE_SIZE_4MB
+- bool
+- depends on HUGETLB_PAGE_SIZE_4MB_1 || HUGETLB_PAGE_SIZE_4MB_2
+- default y
+-
+-config HUGETLB_PAGE_SIZE_1MB
+- bool
+- depends on HUGETLB_PAGE_SIZE_1MB_1 || HUGETLB_PAGE_SIZE_1MB_2
+- default y
+-
+-config HUGETLB_PAGE_SIZE_256KB
+- bool
+- depends on HUGETLB_PAGE_SIZE_256KB_1 || HUGETLB_PAGE_SIZE_256KB_2
+- default y
+-
+ config SMP
+ bool "SMP support"
+ ---help---
+@@ -608,7 +523,8 @@
+ you have use for it; the module is called binfmt_misc.o. If you
+ don't know what to answer at this point, say Y.
+
+-#if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
++if !IA64_HP_SIM
++
+ source "drivers/acpi/Kconfig"
+
+ config PCI
+@@ -650,10 +566,12 @@
+
+ source "drivers/parport/Kconfig"
+
+-#fi # !HP_SIM
++endif
++
+ endmenu
+
+-#if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
++if !IA64_HP_SIM
++
+ source "drivers/mtd/Kconfig"
+
+ source "drivers/pnp/Kconfig"
+@@ -721,7 +639,8 @@
+
+ endmenu
+
+-#fi
++endif
++
+
+ menu "SCSI support"
+
+@@ -751,7 +670,8 @@
+
+ source "net/Kconfig"
+
+-#if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
++
++if !IA64_HP_SIM
+
+ menu "Network device support"
+ depends on NET
+@@ -841,7 +761,8 @@
+ #source drivers/misc/Config.in
+ source "drivers/media/Kconfig"
+
+-#else # HP_SIM
++endif
++
+
+ menu "Block devices"
+ depends on IA64_HP_SIM
+@@ -863,10 +784,10 @@
+
+ endmenu
+
+-# HP_SIM
+ source "fs/Kconfig"
+
+-#if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
++if !IA64_HP_SIM
++
+
+ menu "Console drivers"
+ depends on VT
+@@ -936,7 +857,8 @@
+
+ source "net/bluetooth/Kconfig"
+
+-#fi # !HP_SIM
++endif
++
+ source "arch/ia64/hp/sim/Kconfig"
+
+
+@@ -1058,5 +980,3 @@
+
+ source "security/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/m68k/Kconfig.org 2002-10-16 17:09:18.000000000 +0200
++++ ./arch/m68k/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -634,10 +634,10 @@
+
+ source "drivers/zorro/Kconfig"
+
+-#if [ "$CONFIG_Q40" = "y" ]; then
++if Q40
+ source "drivers/pnp/Kconfig"
++endif
+
+-#fi
+ endmenu
+
+ source "drivers/mtd/Kconfig"
+@@ -646,10 +646,10 @@
+
+ source "drivers/md/Kconfig"
+
+-#if [ "$CONFIG_MAC" = "y" ]; then
++if MAC
+ source "drivers/input/Kconfig"
++endif
+
+-#fi
+
+ menu "ATA/ATAPI/MFM/RLL device support"
+
+@@ -2382,5 +2382,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/mips/Kconfig.org 2002-10-16 17:09:20.000000000 +0200
++++ ./arch/mips/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -810,10 +810,11 @@
+ # fi
+ endmenu
+
+-#if [ "$CONFIG_ISA" = "y" ]; then
++
++if ISA
+ source "drivers/pnp/Kconfig"
++endif
+
+-#fi
+ source "drivers/mtd/Kconfig"
+
+ source "drivers/parport/Kconfig"
+@@ -903,11 +904,11 @@
+
+ endmenu
+
+-#if [ "$CONFIG_DECSTATION" != "y" -a \
+-# "$CONFIG_SGI_IP22" != "y" ]; then
++
++if !DECSTATION" && !SGI_IP22
+ source "drivers/message/i2o/Kconfig"
++endif
+
+-#fi
+ source "net/Kconfig"
+
+
+@@ -1200,7 +1201,8 @@
+
+ Say Y.
+
+-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++if EXPERIMENTAL
++
+ config MDA_CONSOLE
+ tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
+ ---help---
+@@ -1219,7 +1221,8 @@
+
+ source "drivers/video/Kconfig"
+
+-#fi
++endif
++
+ endmenu
+
+
+@@ -1333,5 +1336,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/mips64/Kconfig.org 2002-10-16 17:09:22.000000000 +0200
++++ ./arch/mips64/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -735,5 +735,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/parisc/Kconfig.org 2002-10-16 17:09:22.000000000 +0200
++++ ./arch/parisc/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -759,5 +759,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/ppc/Kconfig.org 2002-10-16 17:09:23.000000000 +0200
++++ ./arch/ppc/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -1826,5 +1826,3 @@
+
+ source "security/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/ppc64/Kconfig.org 2002-10-16 17:09:24.000000000 +0200
++++ ./arch/ppc64/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -525,5 +525,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/s390/Kconfig.org 2002-10-16 17:09:25.000000000 +0200
++++ ./arch/s390/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -318,5 +318,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/s390x/Kconfig.org 2002-10-16 17:09:25.000000000 +0200
++++ ./arch/s390x/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -326,5 +326,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/sh/Kconfig.org 2002-10-16 17:09:25.000000000 +0200
++++ ./arch/sh/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -1214,7 +1214,8 @@
+ Read the file <file:Documentation/svga.txt> for more information
+ about the Video mode selection support. If unsure, say N.
+
+-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++if EXPERIMENTAL
++
+ config MDA_CONSOLE
+ tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
+ ---help---
+@@ -1233,7 +1234,8 @@
+
+ source "drivers/video/Kconfig"
+
+-#fi
++endif
++
+ endmenu
+
+
+@@ -1319,5 +1321,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/sparc/Kconfig.org 2002-10-16 17:09:28.000000000 +0200
++++ ./arch/sparc/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -238,7 +238,8 @@
+ a kernel compiled with this option will run only on Sun4.
+ (And the current version will probably work only on sun4/330.)
+
+-#if [ "$CONFIG_SUN4" != "y" ]; then
++if !SUN4
++
+ config PCI
+ bool "Support for PCI and PS/2 keyboard/mouse"
+ help
+@@ -254,7 +255,8 @@
+
+ source "drivers/pci/Kconfig"
+
+-#else
++endif
++
+ config SUN_OPENPROMFS
+ tristate "Openprom tree appears in /proc/openprom"
+ help
+@@ -429,10 +431,10 @@
+
+ source "drivers/serial/Kconfig"
+
+-#if [ "$CONFIG_SUN4" != "y" ]; then
++if !SUN4
+ source "drivers/sbus/char/Kconfig"
++endif
+
+-#fi
+
+ menu "Block devices"
+
+@@ -575,7 +577,7 @@
+ endmenu
+
+ # Don't frighten a common SBus user
+-#if [ "$CONFIG_PCI" = "y" ]; then
++if PCI
+
+ menu "ATA/ATAPI/MFM/RLL support"
+
+@@ -629,7 +631,8 @@
+
+ endmenu
+
+-#else
++endif
++
+ source "drivers/isdn/Kconfig"
+
+
+@@ -1419,5 +1422,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/sparc64/Kconfig.org 2002-10-16 17:09:28.000000000 +0200
++++ ./arch/sparc64/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -978,12 +978,58 @@
+ whenever you want). If you want to compile it as a module, say M
+ here and read <file:Documentation/modules.txt>.
+
+-#if [ "$CONFIG_PCI" != "n" ]; then
++
++choice
++ prompt "Adaptec AIC7xxx support"
++ optional
++ depends on SCSI && PCI
++
+ source "drivers/scsi/aic7xxx/Kconfig"
+
++config SCSI_AIC7XXX_OLD
++ tristate "Old driver"
++ ---help---
++ WARNING This driver is an older aic7xxx driver and is no longer
++ under active development. Adaptec, Inc. is writing a new driver to
++ take the place of this one, and it is recommended that whenever
++ possible, people should use the new Adaptec written driver instead
++ of this one. This driver will eventually be phased out entirely.
++
++ This is support for the various aic7xxx based Adaptec SCSI
++ controllers. These include the 274x EISA cards; 284x VLB cards;
++ 2902, 2910, 293x, 294x, 394x, 3985 and several other PCI and
++ motherboard based SCSI controllers from Adaptec. It does not support
++ the AAA-13x RAID controllers from Adaptec, nor will it likely ever
++ support them. It does not support the 2920 cards from Adaptec that
++ use the Future Domain SCSI controller chip. For those cards, you
++ need the "Future Domain 16xx SCSI support" driver.
++
++ In general, if the controller is based on an Adaptec SCSI controller
++ chip from the aic777x series or the aic78xx series, this driver
++ should work. The only exception is the 7810 which is specifically
++ not supported (that's the RAID controller chip on the AAA-13x
++ cards).
++
++ Note that the AHA2920 SCSI host adapter is *not* supported by this
++ driver; choose "Future Domain 16xx SCSI support" instead if you have
++ one of those.
++
++ Information on the configuration options for this controller can be
++ found by checking the help file for each of the available
++ configuration options. You should read
++ <file:drivers/scsi/aic7xxx_old/README.aic7xxx> at a minimum before
++ contacting the maintainer with any questions. The SCSI-HOWTO,
++ available from <http://www.linuxdoc.org/docs.html#howto>, can also
++ be of great help.
++
++ If you want to compile this driver as a module ( = code which can be
++ inserted in and removed from the running kernel whenever you want),
++ say M here and read <file:Documentation/modules.txt>. The module
++ will be called aic7xxx_old.o.
++
+ config AIC7XXX_OLD_TCQ_ON_BY_DEFAULT
+ bool "Enable Tagged Command Queueing (TCQ) by default"
+- depends on SCSI_AIC7XXX!=y && SCSI_AIC7XXX_OLD
++ depends on SCSI_AIC7XXX_OLD
+ ---help---
+ This option causes the aic7xxx driver to attempt to use Tagged
+ Command Queueing (TCQ) on all devices that claim to support it.
+@@ -1019,7 +1065,7 @@
+
+ config AIC7XXX_OLD_CMDS_PER_DEVICE
+ int "Maximum number of TCQ commands per device"
+- depends on SCSI_AIC7XXX!=y && SCSI_AIC7XXX_OLD
++ depends on SCSI_AIC7XXX_OLD
+ default "8"
+ ---help---
+ Specify the number of commands you would like to allocate per SCSI
+@@ -1043,7 +1089,7 @@
+
+ config AIC7XXX_OLD_PROC_STATS
+ bool "Collect statistics to report in /proc"
+- depends on SCSI_AIC7XXX!=y && SCSI_AIC7XXX_OLD
++ depends on SCSI_AIC7XXX_OLD
+ ---help---
+ This option tells the driver to keep track of how many commands have
+ been sent to each particular device and report that information to
+@@ -1056,6 +1102,8 @@
+
+ If unsure, say N.
+
++endchoice
++
+ config SCSI_SYM53C8XX_2
+ tristate "SYM53C8XX Version 2 SCSI support"
+ depends on PCI && SCSI
+@@ -1346,10 +1394,10 @@
+
+ source "drivers/fc4/Kconfig"
+
+-#if [ "$CONFIG_PCI" = "y" ]; then
++if PCI
+ source "drivers/message/fusion/Kconfig"
++endif
+
+-#fi
+ source "drivers/ieee1394/Kconfig"
+
+ source "net/Kconfig"
+@@ -1651,5 +1699,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/x86_64/Kconfig.org 2002-10-16 17:09:29.000000000 +0200
++++ ./arch/x86_64/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -592,7 +592,8 @@
+ Read the file <file:Documentation/svga.txt> for more information
+ about the Video mode selection support. If unsure, say N.
+
+-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++if EXPERIMENTAL
++
+ config MDA_CONSOLE
+ tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
+ ---help---
+@@ -611,7 +612,8 @@
+
+ source "drivers/video/Kconfig"
+
+-#fi
++endif
++
+ endmenu
+
+
+@@ -713,5 +715,3 @@
+
+ source "lib/Kconfig"
+
+-source "Kconfig"
+-
+--- ./arch/um/Kconfig.org 2002-10-16 17:09:29.000000000 +0200
++++ ./arch/um/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -163,5 +163,3 @@
+
+ endmenu
+
+-source "Kconfig"
+-
+--- ./drivers/isdn/eicon/Kconfig.org 2002-10-16 17:09:15.000000000 +0200
++++ ./drivers/isdn/eicon/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -11,12 +11,12 @@
+ <file:Documentation/isdn/README.eicon> for more information.
+
+ choice
+- prompt "change me!"
++ prompt "Eicon active card support"
+ optional
+ depends on ISDN_DRV_EICON && ISDN
+
+ config ISDN_DRV_EICON_DIVAS
+- tristate "Build Eicon driver type standalone"
++ tristate "Eicon driver"
+ depends on PCI
+ help
+ Enable this option if you want the eicon driver as standalone
+@@ -26,16 +26,14 @@
+ here.
+
+ config ISDN_DRV_EICON_OLD
+- tristate "Legacy Eicon driver"
++ tristate "Legacy driver"
+ help
+ Say Y here to use your Eicon active ISDN card with ISDN4Linux
+ isdn module.
+
+-endchoice
+-
+ config ISDN_DRV_EICON_PCI
+ bool "Eicon PCI DIVA Server BRI/PRI/4BRI support"
+- depends on ISDN_DRV_EICON_DIVAS!=y && ISDN_DRV_EICON_OLD && PCI
++ depends on ISDN_DRV_EICON_OLD && PCI
+ help
+ Say Y here if you have an Eicon Diva Server (BRI/PRI/4BRI) ISDN
+ card. Please read <file:Documentation/isdn/README.eicon> for more
+@@ -43,7 +41,7 @@
+
+ config ISDN_DRV_EICON_ISA
+ bool "Eicon S,SX,SCOM,Quadro,S2M support"
+- depends on ISDN_DRV_EICON_DIVAS!=y && ISDN_DRV_EICON_OLD
++ depends on ISDN_DRV_EICON_OLD
+ help
+ Say Y here if you have an old-type Eicon active ISDN card. In order
+ to use this card, additional firmware is necessary, which has to be
+@@ -51,3 +49,5 @@
+ the latest isdn4k-utils package. Please read the file
+ <file:Documentation/isdn/README.eicon> for more information.
+
++endchoice
++
+--- ./drivers/scsi/aic7xxx/Kconfig.org 2002-10-16 17:09:15.000000000 +0200
++++ ./drivers/scsi/aic7xxx/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -1,51 +1,5 @@
+-choice
+- prompt "change me!"
+- optional
+- depends on SCSI
+-
+-config SCSI_AIC7XXX_OLD
+- tristate "Old Adaptec AIC7xxx support"
+- ---help---
+- WARNING This driver is an older aic7xxx driver and is no longer
+- under active development. Adaptec, Inc. is writing a new driver to
+- take the place of this one, and it is recommended that whenever
+- possible, people should use the new Adaptec written driver instead
+- of this one. This driver will eventually be phased out entirely.
+-
+- This is support for the various aic7xxx based Adaptec SCSI
+- controllers. These include the 274x EISA cards; 284x VLB cards;
+- 2902, 2910, 293x, 294x, 394x, 3985 and several other PCI and
+- motherboard based SCSI controllers from Adaptec. It does not support
+- the AAA-13x RAID controllers from Adaptec, nor will it likely ever
+- support them. It does not support the 2920 cards from Adaptec that
+- use the Future Domain SCSI controller chip. For those cards, you
+- need the "Future Domain 16xx SCSI support" driver.
+-
+- In general, if the controller is based on an Adaptec SCSI controller
+- chip from the aic777x series or the aic78xx series, this driver
+- should work. The only exception is the 7810 which is specifically
+- not supported (that's the RAID controller chip on the AAA-13x
+- cards).
+-
+- Note that the AHA2920 SCSI host adapter is *not* supported by this
+- driver; choose "Future Domain 16xx SCSI support" instead if you have
+- one of those.
+-
+- Information on the configuration options for this controller can be
+- found by checking the help file for each of the available
+- configuration options. You should read
+- <file:drivers/scsi/aic7xxx_old/README.aic7xxx> at a minimum before
+- contacting the maintainer with any questions. The SCSI-HOWTO,
+- available from <http://www.linuxdoc.org/docs.html#howto>, can also
+- be of great help.
+-
+- If you want to compile this driver as a module ( = code which can be
+- inserted in and removed from the running kernel whenever you want),
+- say M here and read <file:Documentation/modules.txt>. The module
+- will be called aic7xxx_old.o.
+-
+ config SCSI_AIC7XXX
+- tristate "Adaptec AIC7xxx support"
++ tristate "New driver"
+ help
+ This driver supports all of Adaptec's PCI based SCSI controllers
+ (not the hardware RAID controllers though) as well as the aic7770
+@@ -54,11 +8,10 @@
+ intended to replace the previous aic7xxx driver maintained by Doug
+ Ledford since Doug is no longer maintaining that driver.
+
+-endchoice
+
+ config AIC7XXX_CMDS_PER_DEVICE
+ int "Maximum number of TCQ commands per device"
+- depends on SCSI_AIC7XXX_OLD!=y && SCSI_AIC7XXX
++ depends on SCSI_AIC7XXX
+ default "253"
+ ---help---
+ Specify the number of commands you would like to allocate per SCSI
+@@ -77,7 +30,7 @@
+
+ config AIC7XXX_RESET_DELAY_MS
+ int "Initial bus reset delay in milli-seconds"
+- depends on SCSI_AIC7XXX_OLD!=y && SCSI_AIC7XXX
++ depends on SCSI_AIC7XXX
+ default "15000"
+ help
+ The number of milliseconds to delay after an initial bus reset.
+@@ -88,7 +41,7 @@
+
+ config AIC7XXX_BUILD_FIRMWARE
+ bool "Build Adapter Firmware with Kernel Build"
+- depends on SCSI_AIC7XXX_OLD!=y && SCSI_AIC7XXX
++ depends on SCSI_AIC7XXX
+ help
+ This option should only be enabled if you are modifying the firmware
+ source to the aic7xxx driver and wish to have the generated firmware
+--- ./drivers/scsi/Kconfig.org 2002-10-16 17:09:15.000000000 +0200
++++ ./drivers/scsi/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -311,8 +311,57 @@
+ tristate "Adaptec AACRAID support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && SCSI && PCI
+
++choice
++ prompt "Adaptec AIC7xxx support"
++ optional
++ depends on SCSI
++
+ source "drivers/scsi/aic7xxx/Kconfig"
+
++config SCSI_AIC7XXX_OLD
++ tristate "Old driver"
++ help
++ WARNING This driver is an older aic7xxx driver and is no longer
++ under active development. Adaptec, Inc. is writing a new driver to
++ take the place of this one, and it is recommended that whenever
++ possible, people should use the new Adaptec written driver instead
++ of this one. This driver will eventually be phased out entirely.
++
++ This is support for the various aic7xxx based Adaptec SCSI
++ controllers. These include the 274x EISA cards; 284x VLB cards;
++ 2902, 2910, 293x, 294x, 394x, 3985 and several other PCI and
++ motherboard based SCSI controllers from Adaptec. It does not support
++ the AAA-13x RAID controllers from Adaptec, nor will it likely ever
++ support them. It does not support the 2920 cards from Adaptec that
++ use the Future Domain SCSI controller chip. For those cards, you
++ need the "Future Domain 16xx SCSI support" driver.
++
++ In general, if the controller is based on an Adaptec SCSI controller
++ chip from the aic777x series or the aic78xx series, this driver
++ should work. The only exception is the 7810 which is specifically
++ not supported (that's the RAID controller chip on the AAA-13x
++ cards).
++
++ Note that the AHA2920 SCSI host adapter is *not* supported by this
++ driver; choose "Future Domain 16xx SCSI support" instead if you have
++ one of those.
++
++ Information on the configuration options for this controller can be
++ found by checking the help file for each of the available
++ configuration options. You should read
++ <file:drivers/scsi/aic7xxx_old/README.aic7xxx> at a minimum before
++ contacting the maintainer with any questions. The SCSI-HOWTO,
++ available from <http://www.linuxdoc.org/docs.html#howto>, can also
++ be of great help.
++
++ If you want to compile this driver as a module ( = code which can be
++ inserted in and removed from the running kernel whenever you want),
++ say M here and read <file:Documentation/modules.txt>. The module
++ will be called aic7xxx_old.o.
++
++endchoice
++
++
+ # All the I2O code and drivers do not seem to be 64bit safe.
+ config SCSI_DPT_I2O
+ tristate "Adaptec I2O RAID support "
+--- ./sound/oss/Kconfig.org 2002-10-16 17:09:15.000000000 +0200
++++ ./sound/oss/Kconfig 2002-10-16 17:12:17.000000000 +0200
+@@ -1023,12 +1023,12 @@
+ DSP 16 card.
+
+ choice
+- prompt "change me!"
++ prompt "Audio Excel DSP 16"
+ optional
+ depends on SOUND_AEDSP16
+
+ config AEDSP16_MSS
+- bool "Audio Excel DSP 16 (MSS emulation)"
++ bool "MSS emulation"
+ depends on SOUND_MSS
+ help
+ Answer Y if you want your audio card to emulate Microsoft Sound
+@@ -1036,7 +1036,7 @@
+ and say N to "Audio Excel DSP 16 (SBPro emulation)".
+
+ config AEDSP16_SBPRO
+- bool "Audio Excel DSP 16 (SBPro emulation)"
++ bool "SBPro emulation"
+ depends on SOUND_SB
+ help
+ Answer Y if you want your audio card to emulate Sound Blaster Pro.
diff --git a/scripts/kconfig/help.l b/scripts/kconfig/help.l
new file mode 100644
index 0000000..5ac4c2f
--- a/dev/null
+++ b/scripts/kconfig/help.l
@@ -0,0 +1,78 @@
+%option nounput nostdinit noyywrap 8bit
+%x ENTRY
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include "cml1.h"
+
+#define YY_DECL void helplex(char *help)
+#undef YY_NULL
+#define YY_NULL
+%}
+
+%%
+ struct symbol *sym = NULL;
+ helpin = fopen(help, "r");
+ if (!helpin)
+ return;
+ //help_flex_debug = 1;
+ yyrestart(helpin);
+ BEGIN(INITIAL);
+
+^#.*\n /* skip */
+
+^CONFIG_[[:alnum:]_]+ {
+ char name[256];
+ int ch;
+ while ((ch = input()) != '\n' && ch != EOF)
+ ;
+ memcpy(name, yytext, yyleng);
+ name[yyleng] = 0;
+ sym = lookup_symbol(name, SYMBOL_UNKNOWN);
+ new_string();
+ BEGIN(ENTRY);
+}
+
+<ENTRY>{
+ [ \t].*\n+/[^ \t\n] |
+ <<EOF>> {
+ append_string(yytext, yyleng);
+ if (sym) {
+ if (sym->help) {
+ //printf("symbol %s has duplicated help?\n", sym->name);
+ free(text);
+ } else
+ sym->help = text;
+ sym = NULL;
+ } else
+ printf("no symbol?\n");
+ BEGIN(INITIAL);
+ }
+ \n/[^ \t\n] {
+ append_string(yytext, yyleng);
+ if (sym) {
+ if (sym->help) {
+ //printf("symbol %s has duplicated help?\n", sym->name);
+ free(text);
+ } else
+ sym->help = text;
+ sym = NULL;
+ } else
+ printf("no symbol?\n");
+ BEGIN(INITIAL);
+ }
+ [ \t].*\n |
+ . |
+ \n {
+ append_string(yytext, yyleng);
+ }
+}
+
+.
+\n
+%%
diff --git a/scripts/kconfig/images.c b/scripts/kconfig/images.c
new file mode 100644
index 0000000..65a5d67
--- a/dev/null
+++ b/scripts/kconfig/images.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+static const char *xpm_load[] = {
+"22 22 5 1",
+". c None",
+"# c #000000",
+"c c #838100",
+"a c #ffff00",
+"b c #ffffff",
+"......................",
+"......................",
+"......................",
+"............####....#.",
+"...........#....##.##.",
+"..................###.",
+".................####.",
+".####...........#####.",
+"#abab##########.......",
+"#babababababab#.......",
+"#ababababababa#.......",
+"#babababababab#.......",
+"#ababab###############",
+"#babab##cccccccccccc##",
+"#abab##cccccccccccc##.",
+"#bab##cccccccccccc##..",
+"#ab##cccccccccccc##...",
+"#b##cccccccccccc##....",
+"###cccccccccccc##.....",
+"##cccccccccccc##......",
+"###############.......",
+"......................"};
+
+static const char *xpm_save[] = {
+"22 22 5 1",
+". c None",
+"# c #000000",
+"a c #838100",
+"b c #c5c2c5",
+"c c #cdb6d5",
+"......................",
+".####################.",
+".#aa#bbbbbbbbbbbb#bb#.",
+".#aa#bbbbbbbbbbbb#bb#.",
+".#aa#bbbbbbbbbcbb####.",
+".#aa#bbbccbbbbbbb#aa#.",
+".#aa#bbbccbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aa#bbbbbbbbbbbb#aa#.",
+".#aaa############aaa#.",
+".#aaaaaaaaaaaaaaaaaa#.",
+".#aaaaaaaaaaaaaaaaaa#.",
+".#aaa#############aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+".#aaa#########bbb#aa#.",
+"..##################..",
+"......................"};
+
+static const char *xpm_back[] = {
+"22 22 3 1",
+". c None",
+"# c #000083",
+"a c #838183",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................",
+"...........######a....",
+"..#......##########...",
+"..##...####......##a..",
+"..###.###.........##..",
+"..######..........##..",
+"..#####...........##..",
+"..######..........##..",
+"..#######.........##..",
+"..########.......##a..",
+"...............a###...",
+"...............###....",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................",
+"......................"};
+
+static const char *xpm_tree_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......#...............",
+"......########........",
+"......................",
+"......................"};
+
+static const char *xpm_single_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"..........#...........",
+"......................",
+"......................"};
+
+static const char *xpm_split_view[] = {
+"22 22 2 1",
+". c None",
+"# c #000000",
+"......................",
+"......................",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......#......#........",
+"......................",
+"......................"};
+
+static const char *xpm_symbol_no[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_symbol_mod[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_symbol_yes[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . . ",
+" . . . ",
+" . .. . ",
+" . . .. . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_choice_no[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .... ",
+" .. .. ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .. .. ",
+" .... ",
+" "};
+
+static const char *xpm_choice_yes[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .... ",
+" .. .. ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .. .. ",
+" .... ",
+" "};
+
+static const char *xpm_menu[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" . . ",
+" . .. . ",
+" . .... . ",
+" . ...... . ",
+" . ...... . ",
+" . .... . ",
+" . .. . ",
+" . . ",
+" .......... ",
+" "};
+
+static const char *xpm_menu_inv[] = {
+"12 12 2 1",
+" c white",
+". c black",
+" ",
+" .......... ",
+" .......... ",
+" .. ...... ",
+" .. .... ",
+" .. .. ",
+" .. .. ",
+" .. .... ",
+" .. ...... ",
+" .......... ",
+" .......... ",
+" "};
diff --git a/scripts/kconfig/kconfig.i b/scripts/kconfig/kconfig.i
new file mode 100644
index 0000000..699cb13
--- a/dev/null
+++ b/scripts/kconfig/kconfig.i
@@ -0,0 +1,133 @@
+%module kconfig
+%{
+#include "kconfig_load.c"
+%}
+
+%init %{
+ kconfig_load();
+%}
+
+%nodefault;
+
+#ifdef SWIGRUBY
+%typemap (out) char * {
+ if ($1 == NULL)
+ $result = Qnil;
+ else
+ $result = rb_str_new2($1);
+}
+%typemap (in) char * {
+ if ($input == Qnil)
+ $1 = NULL;
+ else
+ $1 = STR2CSTR($input);
+}
+
+%{
+static void expr_to_s_help(void *data, const char *str)
+{
+ rb_str_cat((VALUE)data, str, strlen(str));
+}
+%}
+#endif
+
+%immutable;
+%include "expr.h"
+#define P(name,type,arg) extern type name arg
+%include "lkc_proto.h"
+%mutable;
+
+#ifdef SWIGRUBY
+%predicate menu::isVisible;
+%predicate symbol::isChangable;
+%predicate symbol::isChoice;
+%predicate symbol::isChoiceValue;
+#endif
+
+%extend menu {
+ bool isVisible(void) {
+ return menu_is_visible(self);
+ }
+#ifdef SWIGRUBY
+ void each(void) {
+ struct menu *child;
+ for (child = self->list; child; child = child->next)
+ rb_yield(SWIG_NewPointerObj(child, SWIGTYPE_p_menu, 0));
+ }
+ static void each_menu(void) {
+ struct menu *child;
+ for (child = rootmenu.list; child; child = child->next)
+ rb_yield(SWIG_NewPointerObj(child, SWIGTYPE_p_menu, 0));
+ }
+#endif
+}
+
+%extend symbol {
+ void calc_value(void) {
+ sym_calc_value(self);
+ }
+ tristate set_tristate(tristate val) {
+ return sym_set_tristate_value(self, val);
+ }
+ bool set_string(char *val) {
+ return sym_set_string_value(self, val);
+ }
+ const char *get_string(void) {
+ return sym_get_string_value(self);
+ }
+ bool isChangable(void) {
+ return sym_is_changable(self);
+ }
+ bool isChoice(void) {
+ return sym_is_choice(self);
+ }
+ bool isChoiceValue(void) {
+ return sym_is_choice_value(self);
+ }
+ static struct symbol *lookup(const char *name) {
+ return sym_lookup(name, 0);
+ }
+ static struct symbol *find(const char *name) {
+ return sym_find(name);
+ }
+ static const char *type_name(enum symbol_type type) {
+ return sym_type_name(type);
+ }
+#ifdef SWIGRUBY
+ void each(void) {
+ struct property *prop;
+ for (prop = self->prop; prop; prop = prop->next)
+ rb_yield(SWIG_NewPointerObj(prop, SWIGTYPE_p_property, 0));
+ }
+ static void each_sym(void) {
+ struct symbol *sym;
+ int i;
+ for (i = 0; i < SYMBOL_HASHSIZE; i++) {
+ for (sym = symbol_hash[i]; sym; sym = sym->next) {
+ if (sym->flags & SYMBOL_CONST)
+ continue;
+ rb_yield(SWIG_NewPointerObj(sym, SWIGTYPE_p_symbol, 0));
+ }
+ }
+ }
+#endif
+}
+
+%extend property {
+ static const char *type_name(enum prop_type type) {
+ return prop_get_type_name(type);
+ }
+}
+
+%extend expr {
+ static int comp_type(enum expr_type t1, enum expr_type t2) {
+ return expr_compare_type(t1, t2);
+ }
+#ifdef SWIGRUBY
+ VALUE __str__(void) {
+ VALUE str = rb_str_new2("");
+ expr_print(self, expr_to_s_help, (void*)str, E_NONE);
+ return str;
+ }
+#endif
+}
diff --git a/scripts/kconfig/kconfig_load.c b/scripts/kconfig/kconfig_load.c
new file mode 100644
index 0000000..dbdcaad
--- a/dev/null
+++ b/scripts/kconfig/kconfig_load.c
@@ -0,0 +1,35 @@
+#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/lkc.h b/scripts/kconfig/lkc.h
new file mode 100644
index 0000000..688945b
--- a/dev/null
+++ b/scripts/kconfig/lkc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#ifndef LKC_H
+#define LKC_H
+
+#include "expr.h"
+
+#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
+
+void symbol_end(char *help);
+int zconfparse(void);
+void zconfdump(FILE *out);
+
+extern int zconfdebug;
+void zconf_starthelp(void);
+void zconf_initscan(const char *name);
+void zconf_nextfile(const char *name);
+int zconf_lineno(void);
+char *zconf_curname(void);
+
+/* confdata.c */
+extern const char conf_def_filename[];
+extern char conf_filename[];
+
+char *conf_get_default_confname(void);
+
+/* kconfig_load.c */
+void kconfig_load(void);
+
+/* menu.c */
+void menu_init(void);
+void menu_add_menu(void);
+void menu_end_menu(void);
+void menu_add_entry(struct symbol *sym);
+void menu_end_entry(void);
+struct property *create_prop(enum prop_type type);
+void menu_add_dep(struct expr *dep);
+struct property *menu_add_prop(int token, char *prompt, struct symbol *def, struct expr *dep);
+void menu_finalize(struct menu *parent);
+void menu_set_type(int type);
+struct file *file_lookup(const char *name);
+int file_write_dep(const char *name);
+
+extern struct menu *current_entry;
+extern struct menu *current_menu;
+
+/* symbol.c */
+void sym_init(void);
+void sym_clear_all_valid(void);
+
+static inline tristate sym_get_tristate_value(struct symbol *sym)
+{
+ return S_TRI(sym->curr);
+}
+
+
+static inline struct symbol *sym_get_choice_value(struct symbol *sym)
+{
+ return (struct symbol *)S_VAL(sym->curr);
+}
+
+static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval)
+{
+ return sym_set_tristate_value(chval, yes);
+}
+
+static inline bool sym_is_choice(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_CHOICE ? true : false;
+}
+
+static inline bool sym_is_choice_value(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_CHOICEVAL ? true : false;
+}
+
+static inline bool sym_is_optional(struct symbol *sym)
+{
+ return sym->flags & SYMBOL_OPTIONAL ? true : false;
+}
+
+static inline bool sym_has_value(struct symbol *sym)
+{
+ //return S_VAL(sym->def) != NULL;
+ return sym->flags & SYMBOL_NEW ? false : true;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LKC_H */
diff --git a/scripts/kconfig/lkc_overview b/scripts/kconfig/lkc_overview
new file mode 100644
index 0000000..e9db60e
--- a/dev/null
+++ b/scripts/kconfig/lkc_overview
@@ -0,0 +1,111 @@
+Introduction
+------------
+
+The configuration database is collection of configuration options
+organized in a tree structure:
+
+ +- Code maturity level options
+ | +- Prompt for development and/or incomplete code/drivers
+ +- General setup
+ | +- Networking support
+ | +- System V IPC
+ | +- BSD Process Accounting
+ | +- Sysctl support
+ +- Loadable module support
+ | +- Enable loadable module support
+ | +- Set version information on all module symbols
+ | +- Kernel module loader
+ +- ...
+
+Every entry has its own dependencies. These dependencies are used
+to determine the visible of an entry. Any child entry is only
+visible if its parent entry is also visible.
+
+Menu entries
+------------
+
+A single configuration option is defined like this:
+
+config MODVERSIONS
+ bool "Set version information on all module symbols"
+ depends MODULES
+ help
+ Usually, modules have to be recompiled whenever you switch to a new
+ kernel. ...
+
+Every line starts with a key word and can be followed by multiple arguments.
+"config" starts a new config entry. The following lines define attributes
+for this config option. Attributes can be the type of the config option,
+input prompt, dependencies, help text and default values. A config option
+can be defined multiple times, but every definition can have only a single
+input prompt and the type must not conflict.
+
+Menu dependencies
+-----------------
+
+Dependencies define the visibility of a menu entry. When a dependency
+exprecession evaluates not to 'n', the entry is visible. Additionally
+the dependency limits the input range of tristate choice symbols.
+
+Menu structure
+--------------
+
+The position of a menu entry in the tree is determined in two ways. First
+it can be specified explicitely:
+
+menu "Network device support"
+ depends NET
+
+config NETDEVICES
+ ...
+
+endmenu
+
+All entries within the "menu" ... "endmenu" block become a submenu of
+"Processor type and features". All subentries have the same dependencies
+than the menu entry, e.g. this means the dependency "NET" is added to the
+dependencies of the option NETDEVICES.
+The other way to generate the menu structure is done by analyzing the
+dependencies. If a menu entry somehow depends on the previous entry, it
+can be made a submenu of it.
+
+config MODULES
+ bool "Enable loadable module support"
+
+config MODVERSIONS
+ bool "Set version information on all module symbols"
+ depends MODULES
+
+comment "module support disabled"
+ depends !MODULES
+
+MODVERSIONS directly depends on MODULES, this means it's only visible if
+MODULES is different from 'n'. The comment on the other hand is always
+visible when MODULES it's visible (the dependency of MODULES are part
+of the comment dependencies).
+
+Menu attributes
+---------------
+
+A menu attribute can have a number of attributes. Not all of them are
+applicable everywhere (see spec).
+Input prompt: Every menu entry can have at most one menu entry, which
+is used to display to the user. An input prompt is either defined with
+"prompt" or it can be defined with the type.
+Type definition: Every config option must have a type, known types are
+currently: bool, tristate, string, hex, integer.
+Default value: It's possible to assign a config option a default value.
+This default is always used, when the option wasn't explicitly set by
+the user. This means it's either used as default value for input prompts
+or the value is saved to the kernel configuration. Multiple default
+values can be specified and every one has it's own dependencies. If
+multiple default values are visible, the first defined one is active.
+A default is not limited to a single menu entry, this means the default
+doesn't has to be defined with a input prompt, but it can also be
+overridden by prepend it with another definition.
+Dependencies: Dependencies can be either defined with "depends", then
+there are applied to all attributes of a menu entry, or attribute
+specific dependencies can be defined with "if", which immediately
+follows the attribute.
+
+
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
new file mode 100644
index 0000000..116d759
--- a/dev/null
+++ b/scripts/kconfig/lkc_proto.h
@@ -0,0 +1,38 @@
+
+/* confdata.c */
+P(conf_parse,void,(const char *name));
+P(conf_read,int,(const char *name));
+P(conf_write,int,(const char *name));
+
+/* menu.c */
+P(rootmenu,struct menu,);
+
+P(menu_is_visible,bool,(struct menu *menu));
+P(menu_get_prompt,const char *,(struct menu *menu));
+P(menu_get_root_menu,struct menu *,(struct menu *menu));
+P(menu_get_parent_menu,struct menu *,(struct menu *menu));
+
+/* symbol.c */
+P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
+P(sym_change_count,int,);
+
+P(sym_lookup,struct symbol *,(const char *name, int isconst));
+P(sym_find,struct symbol *,(const char *name));
+P(sym_type_name,const char *,(int type));
+P(sym_calc_value,void,(struct symbol *sym));
+P(sym_get_type,int,(struct symbol *sym));
+P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri));
+P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri));
+P(sym_toggle_tristate_value,tristate,(struct symbol *sym));
+P(sym_string_valid,bool,(struct symbol *sym, const char *newval));
+P(sym_set_string_value,bool,(struct symbol *sym, const char *newval));
+P(sym_is_changable,bool,(struct symbol *sym));
+P(sym_get_choice_prop,struct property *,(struct symbol *sym));
+P(sym_get_default_prop,struct property *,(struct symbol *sym));
+P(sym_get_string_value,const char *,(struct symbol *sym));
+
+P(prop_get_type_name,const char *,(enum prop_type type));
+
+/* expr.c */
+P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
+P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken));
diff --git a/scripts/kconfig/lkc_spec b/scripts/kconfig/lkc_spec
new file mode 100644
index 0000000..45c36eb
--- a/dev/null
+++ b/scripts/kconfig/lkc_spec
@@ -0,0 +1,250 @@
+1. General Structure
+
+The configuration file describes a series of menu entries. These menu
+entries are organized in a tree structure. The following statements
+start a new menu entry definition (and end a previous menu entry):
+- config
+- choice
+- comment
+- menu
+The following statements are control entries and also end the definition
+of a previous menu entry:
+- source
+- if
+
+2. Dependencies
+
+Every menu entry has dependencies, which define it's visibility in the
+menu structure. What makes these dependencies more difficult is that
+they use three states instead of two, that most programmers are familiar
+with. The additional 'mod' state is needed to describe drivers which
+are not compiled into the kernel, but are compiled as modules, which
+can be loaded at runtime. Nevertheless they should be straigthforward
+to use.
+Dependencies describe in first place the relation between configuration
+symbols and consequently between different parts of the kernel. To
+simplify the verification of the rule base, dependencies must be
+hierarchical, that means no recursive dependencies are allowed. The only
+possible non-hierarchical dependency are exclusions (aka choices), to
+cover typical uses during kernel configuration the semantic of choice
+statements has been extended (see the choice statement below).
+
+This allows to describe the following basic relationships:
+- initialization order of kernel subsystems. That means which other
+ subsystems are required (initialized and working), before a specific
+ subsystem can be initialized itself. This allows above requirement of
+ hierarchical dependencies.
+- mutual exclusions of kernel subsystems. This allows that only a single
+ of multiple possible subsystems is configured into the kernel.
+These are the same relationships, which are reasonably representable
+with cml1, but with this new config syntax it should be possible to
+easily add further relationships and other properties.
+
+The important usage of the dependency information is for generation of
+the menu structure. First it defines whether a symbol or statement is
+visible at all. If the dependency expression evaluates to 'n', the symbol
+is not visible (and is currently also not saved, this BTW corresponds to
+the behavior of xconfig, which is noted as a bug in Documentation/
+kbuild/config-language.txt, that didn't seem to be a problem so far, but
+that has to be considered).
+If a symbol is visible, it defines the possible input range for tristate
+symbols, if the dependency expression evaluates to 'm', a tristate symbol
+can only be set to 'n' or 'm', otherwise also 'y' is possible.
+Finally dependency information is also used to group symbols together.
+If a symbol entry is followed by other symbol entries which depends on
+the first one, the latter entries are associated with the first entry.
+The text config front end uses this information to automatically indent
+the entries, the qt interface creates further submenus. This can reduce
+the amount of explicit menu information required.
+
+syntax:
+
+This is the syntax of dependency expressions:
+
+<expr> ::= <symbol> (1)
+ <symbol> '=' <symbol> (2)
+ <symbol> '!=' <symbol> (3)
+ '(' <expr> ')' (4)
+ '!' <expr> (5)
+ <expr> '||' <expr> (6)
+ <expr> '&&' <expr> (7)
+
+Expressions are listed in decreasing order of precedence. An
+expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2 respectively
+for calculations below).
+There are two type of symbols: constant and nonconstant symbols.
+Nonconstant symbols are the most common ones and are defined with the
+'config' statement. Nonconstant symbols consist entirely of alphanumeric
+characters or underscores.
+Constant symbols are only part of expressions. Constant symbols are
+always surrounded by single or double quotes. Within the quote any
+other character is allowed and the quotes can be escaped using '\'.
+Nonconstant symbols which are nowhere defined with 'config' are a
+special case, they behave like constant symbols, so that one can do
+"FOO=123", it usage should restricted to number values (this might
+be enforced later).
+
+expression syntax:
+
+(1) Convert the symbol into an expression. Boolean and tristate symbols
+ are simply converted into the respective expression values. All other
+ symbol types result in 'n'.
+(2) If the values of both symbols are equal, it returns 'y', otherwise 'n'.
+(3) If the values of both symbols are equal, it returns 'n', otherwise 'y'.
+(4) Returns the value of the expression. Used to override precedence.
+(5) Returns the result of (2-/expr/).
+(6) Returns the result of min(/expr/, /expr/).
+(7) Returns the result of max(/expr/, /expr/).
+
+3. "config"
+
+syntax:
+
+ "config" <symbol>
+ <config options>
+
+Defines a new config symbol. A symbol can be defined multiple times as
+long as the symbol type is always the same.
+
+config options:
+
+ "depends" <expr>
+
+defines the visibility and the input range of the config symbol.
+
+ "tristate" <prompt> "if" <expr>
+ "bool" <prompt> "if" <expr>
+ "int" <prompt> "if" <expr>
+ "hex" <prompt> "if" <expr>
+ "string" <prompt> "if" <expr>
+
+defines the type of the symbol and the prompt which is used to request a
+value from the user. Additional constraints for the visibility and the
+input range of the prompt can be defined after an "if" statement. The
+prompt and the "if" statement are optional, but an "if" statement
+without a prompt is not possible.
+
+ "prompt" <prompt> "if" <expr>
+
+same as above, but without defining the type of the symbol. This was
+generated by earlier versions of the converter and will likely
+disappear unless needed otherwise.
+
+ "default" <symbol> "if" <expr>
+
+defines a default value for the config symbol. Unless the config symbol
+was previously set by the user, it will set to this value. This means
+it will be used as default value for above input prompts or if no user
+prompt is visible the config symbol will be saved with this value. If
+multiple default statements are visible only the first is used.
+
+ "help"
+
+defines a help text for this statement. The end of the help text
+is determined by the level indentation, this means it ends at the first
+line which has a smaller indentation than the first line of the help text.
+
+4. "choice"
+
+syntax:
+
+ "choice"
+ <choice options>
+ <choice block>
+ "endchoice"
+
+defines a group of related config statements. There are two types of
+choice statements - bool and tristate.
+
+bool choice: allows only single config statement to be selected and
+set to "y".
+tristate choice: extends the bool choice by also allowing multiple
+config statement to be selected, but in this mode these will only be set
+"m". This can be used if multiple drivers for a single hardware exists
+and only a single driver can be compiled/loaded into the kernel, but all
+drivers can be compiled as modules.
+
+choice options:
+
+ "depends" <expr>
+
+defines the visibility and the input range of the choice.
+
+ "prompt" <prompt>
+
+defines the prompt which is presented to the user.
+
+ <optional>
+
+by default exactly one of the config statements of a bool choice has
+to be selected, this option allows that also no config statement has to
+be selected.
+
+ "default" <symbol>
+
+defines the default choice presented to the user. The prompt must be a
+one of symbols defined within this choice.
+
+ "help"
+
+defines a help text for this choice statement. The end of the help text
+is determined by the level indentation, this means it ends at the first
+line which has a smaller indentation than the first line of the help text.
+
+choice block:
+
+right now only config statements allowed. (It's possible to also allow
+other statements later.)
+
+5. "comment"
+
+syntax:
+
+ "comment" <prompt>
+ <comment options>
+
+defines the prompt which is displayed to the user during the
+configuration process and is also echoes it to the output files during
+output.
+
+comment options:
+
+ "depends" <expr>
+
+defines the visibility of the comment.
+
+6. "menu"
+
+syntax:
+
+ "menu" <prompt>
+ <menu options>
+ <menu block>
+ "endmenu"
+
+menu options:
+
+ "depends" <expr>
+
+defines the visibility of the menu.
+
+menu block:
+
+Any of the basic statements is allowed within a menu block.
+
+7. "if"
+
+syntax:
+
+ "if" <expr>
+ <if block>
+ "endif"
+
+8. "source"
+
+syntax:
+
+ "source" <prompt>
+
+reads the specified configuration file. this is done unconditionally,
+
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
new file mode 100644
index 0000000..84699be
--- a/dev/null
+++ b/scripts/kconfig/mconf.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+static char menu_backtitle[128];
+static const char menu_instructions[] =
+ "Arrow keys navigate the menu. "
+ "<Enter> selects submenus --->. "
+ "Highlighted letters are hotkeys. "
+ "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
+ "Press <Esc><Esc> to exit, <?> for Help. "
+ "Legend: [*] built-in [ ] excluded <M> module < > module capable",
+radiolist_instructions[] =
+ "Use the arrow keys to navigate this window or "
+ "press the hotkey of the item you wish to select "
+ "followed by the <SPACE BAR>. "
+ "Press <?> for additional information about this option.",
+inputbox_instructions_int[] =
+ "Please enter a decimal value. "
+ "Fractions will not be accepted. "
+ "Use the <TAB> key to move from the input field to the buttons below it.",
+inputbox_instructions_hex[] =
+ "Please enter a hexadecimal value. "
+ "Use the <TAB> key to move from the input field to the buttons below it.",
+inputbox_instructions_string[] =
+ "Please enter a string value. "
+ "Use the <TAB> key to move from the input field to the buttons below it.",
+setmod_text[] =
+ "This feature depends on another which has been configured as a module.\n"
+ "As a result, this feature will be built as a module.",
+nohelp_text[] =
+ "There is no help available for this kernel option.\n",
+load_config_text[] =
+ "Enter the name of the configuration file you wish to load. "
+ "Accept the name shown to restore the configuration you "
+ "last retrieved. Leave blank to abort.",
+load_config_help[] =
+ "\n"
+ "For various reasons, one may wish to keep several different kernel\n"
+ "configurations available on a single machine.\n"
+ "\n"
+ "If you have saved a previous configuration in a file other than the\n"
+ "kernel's default, entering the name of the file here will allow you\n"
+ "to modify 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",
+save_config_text[] =
+ "Enter a filename to which this configuration should be saved "
+ "as an alternate. Leave blank to abort.",
+save_config_help[] =
+ "\n"
+ "For various reasons, one may wish to keep different kernel\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"
+;
+
+static char buf[4096], *bufptr = buf;
+static char input_buf[4096];
+static char *args[1024], **argptr = args;
+static int indent = 0;
+static int rows, cols;
+static struct menu *current_menu;
+static int child_count;
+static int do_resize;
+
+static void conf(struct menu *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 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);
+static void show_readme(void);
+
+static void cprint_init(void);
+static int cprint1(const char *fmt, ...);
+static void cprint_done(void);
+static int cprint(const char *fmt, ...);
+
+static void init_wsize(void)
+{
+ struct winsize ws;
+
+ if (ioctl(1, TIOCGWINSZ, &ws) == -1) {
+ rows = 24;
+ cols = 80;
+ } else {
+ rows = ws.ws_row;
+ cols = ws.ws_col;
+ }
+
+ if (rows < 19 || cols < 80) {
+ fprintf(stderr, "Your display is too small to run Menuconfig!\n");
+ fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
+ exit(1);
+ }
+
+ rows -= 4;
+ cols -= 5;
+}
+
+static void cprint_init(void)
+{
+ bufptr = buf;
+ argptr = args;
+ memset(args, 0, sizeof(args));
+ indent = 0;
+ child_count = 0;
+ cprint("./scripts/lxdialog/lxdialog");
+ cprint("--backtitle");
+ cprint(menu_backtitle);
+}
+
+static int cprint1(const char *fmt, ...)
+{
+ va_list ap;
+ int res;
+
+ if (!*argptr)
+ *argptr = bufptr;
+ va_start(ap, fmt);
+ res = vsprintf(bufptr, fmt, ap);
+ va_end(ap);
+ bufptr += res;
+
+ return res;
+}
+
+static void cprint_done(void)
+{
+ *bufptr++ = 0;
+ argptr++;
+}
+
+static int cprint(const char *fmt, ...)
+{
+ va_list ap;
+ int res;
+
+ *argptr++ = bufptr;
+ va_start(ap, fmt);
+ res = vsprintf(bufptr, fmt, ap);
+ va_end(ap);
+ bufptr += res;
+ *bufptr++ = 0;
+
+ return res;
+}
+
+pid_t pid;
+
+static void winch_handler(int sig)
+{
+ if (!do_resize) {
+ kill(pid, SIGINT);
+ do_resize = 1;
+ }
+}
+
+static int exec_conf(void)
+{
+ int pipefd[2], stat, size;
+ struct sigaction sa;
+ sigset_t sset, osset;
+
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGINT);
+ sigprocmask(SIG_BLOCK, &sset, &osset);
+
+ signal(SIGINT, SIG_DFL);
+
+ sa.sa_handler = winch_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sigaction(SIGWINCH, &sa, NULL);
+
+ *argptr++ = NULL;
+
+ pipe(pipefd);
+ pid = fork();
+ if (pid == 0) {
+ sigprocmask(SIG_SETMASK, &osset, NULL);
+ dup2(pipefd[1], 2);
+ close(pipefd[0]);
+ close(pipefd[1]);
+ execv(args[0], args);
+ _exit(EXIT_FAILURE);
+ }
+
+ close(pipefd[1]);
+ bufptr = input_buf;
+ while (1) {
+ size = input_buf + sizeof(input_buf) - bufptr;
+ size = read(pipefd[0], bufptr, size);
+ if (size <= 0) {
+ if (size < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ perror("read");
+ }
+ break;
+ }
+ bufptr += size;
+ }
+ *bufptr++ = 0;
+ close(pipefd[0]);
+ waitpid(pid, &stat, 0);
+
+ if (do_resize) {
+ init_wsize();
+ do_resize = 0;
+ sigprocmask(SIG_SETMASK, &osset, NULL);
+ return -1;
+ }
+ if (WIFSIGNALED(stat)) {
+ printf("\finterrupted(%d)\n", WTERMSIG(stat));
+ exit(1);
+ }
+#if 0
+ printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf);
+ sleep(1);
+#endif
+ sigpending(&sset);
+ if (sigismember(&sset, SIGINT)) {
+ printf("\finterrupted\n");
+ exit(1);
+ }
+ sigprocmask(SIG_SETMASK, &osset, NULL);
+
+ return WEXITSTATUS(stat);
+}
+
+static void build_conf(struct menu *menu)
+{
+ struct symbol *sym;
+ struct property *prop;
+ struct menu *child;
+ int type, tmp, doint = 2;
+ tristate val;
+ char ch;
+
+ if (!menu_is_visible(menu))
+ return;
+
+ sym = menu->sym;
+ prop = menu->prompt;
+ if (!sym) {
+ if (prop && menu != current_menu) {
+ const char *prompt = menu_get_prompt(menu);
+ switch (prop->type) {
+ case P_MENU:
+ child_count++;
+ cprint("m%p", menu);
+ if (menu->parent != &rootmenu)
+ cprint1(" %*c", indent + 1, ' ');
+ cprint1("%s --->", prompt);
+ cprint_done();
+ return;
+ default:
+ if (prompt) {
+ child_count++;
+ cprint(":%p", menu);
+ cprint("---%*c%s", indent + 1, ' ', prompt);
+ }
+ }
+ } else
+ doint = 0;
+ goto conf_childs;
+ }
+
+ type = sym_get_type(sym);
+ if (sym_is_choice(sym)) {
+ struct symbol *def_sym = sym_get_choice_value(sym);
+ struct menu *def_menu = NULL;
+
+ child_count++;
+ for (child = menu->list; child; child = child->next) {
+ if (menu_is_visible(child) && child->sym == def_sym)
+ def_menu = child;
+ }
+
+ val = sym_get_tristate_value(sym);
+ if (sym_is_changable(sym)) {
+ cprint("t%p", menu);
+ switch (type) {
+ case S_BOOLEAN:
+ cprint1("[%c]", val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ switch (val) {
+ case yes: ch = '*'; break;
+ case mod: ch = 'M'; break;
+ default: ch = ' '; break;
+ }
+ cprint1("<%c>", ch);
+ break;
+ }
+ } else {
+ cprint("%c%p", def_menu ? 't' : ':', menu);
+ cprint1(" ");
+ }
+
+ cprint1("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
+ if (val == yes) {
+ if (def_menu) {
+ cprint1(" (%s)", menu_get_prompt(def_menu));
+ cprint1(" --->");
+ cprint_done();
+ if (def_menu->list) {
+ indent += 2;
+ build_conf(def_menu);
+ indent -= 2;
+ }
+ } else
+ cprint_done();
+ return;
+ }
+ cprint_done();
+ } else {
+ child_count++;
+ val = sym_get_tristate_value(sym);
+ if (sym_is_choice_value(sym) && val == yes) {
+ cprint(":%p", menu);
+ cprint1(" ");
+ } else {
+ switch (type) {
+ case S_BOOLEAN:
+ cprint("t%p", menu);
+ cprint1("[%c]", val == no ? ' ' : '*');
+ break;
+ case S_TRISTATE:
+ cprint("t%p", menu);
+ switch (val) {
+ case yes: ch = '*'; break;
+ case mod: ch = 'M'; break;
+ default: ch = ' '; break;
+ }
+ cprint1("<%c>", ch);
+ break;
+ default:
+ cprint("s%p", menu);
+ tmp = cprint1("(%s)", sym_get_string_value(sym));
+ tmp = indent - tmp + 4;
+ if (tmp < 0)
+ tmp = 0;
+ cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
+ sym_has_value(sym) ? "" : " (NEW)");
+ cprint_done();
+ goto conf_childs;
+ }
+ }
+ cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
+ sym_has_value(sym) ? "" : " (NEW)");
+ cprint_done();
+ }
+
+conf_childs:
+ indent += doint;
+ for (child = menu->list; child; child = child->next)
+ build_conf(child);
+ indent -= doint;
+}
+
+static void conf(struct menu *menu)
+{
+ struct menu *submenu;
+ const char *prompt = menu_get_prompt(menu);
+ struct symbol *sym;
+ char active_entry[40];
+ int stat, type, i;
+
+ active_entry[0] = 0;
+ while (1) {
+ cprint_init();
+ cprint("--title");
+ cprint("%s", prompt ? prompt : "Main Menu");
+ cprint("--menu");
+ cprint(menu_instructions);
+ cprint("%d", rows);
+ cprint("%d", cols);
+ cprint("%d", rows - 10);
+ cprint("%s", active_entry);
+ current_menu = menu;
+ build_conf(menu);
+ if (!child_count)
+ break;
+ if (menu == &rootmenu) {
+ cprint(":");
+ cprint("--- ");
+ cprint("L");
+ cprint("Load an Alternate Configuration File");
+ cprint("S");
+ cprint("Save Configuration to an Alternate File");
+ }
+ stat = exec_conf();
+ if (stat < 0)
+ continue;
+
+ if (stat == 1 || stat == 255)
+ break;
+
+ type = input_buf[0];
+ if (!type)
+ continue;
+
+ for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++)
+ ;
+ if (i >= sizeof(active_entry))
+ i = sizeof(active_entry) - 1;
+ input_buf[i] = 0;
+ strcpy(active_entry, input_buf);
+
+ sym = NULL;
+ submenu = NULL;
+ if (sscanf(input_buf + 1, "%p", &submenu) == 1)
+ sym = submenu->sym;
+
+ switch (stat) {
+ case 0:
+ switch (type) {
+ case 'm':
+ conf(submenu);
+ break;
+ case 't':
+ if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
+ conf_choice(submenu);
+ 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
+ show_readme();
+ break;
+ case 3:
+ if (type == 't') {
+ if (sym_set_tristate_value(sym, yes))
+ break;
+ if (sym_set_tristate_value(sym, mod))
+ show_textbox(NULL, setmod_text, 6, 74);
+ }
+ break;
+ case 4:
+ if (type == 't')
+ sym_set_tristate_value(sym, no);
+ break;
+ case 5:
+ if (type == 't')
+ sym_set_tristate_value(sym, mod);
+ break;
+ case 6:
+ if (type == 't')
+ sym_toggle_tristate_value(sym);
+ break;
+ }
+ }
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+ int fd;
+
+ fd = creat(".help.tmp", 0777);
+ write(fd, text, strlen(text));
+ close(fd);
+ do {
+ cprint_init();
+ if (title) {
+ cprint("--title");
+ cprint("%s", title);
+ }
+ cprint("--textbox");
+ cprint(".help.tmp");
+ cprint("%d", r);
+ cprint("%d", c);
+ } while (exec_conf() < 0);
+ unlink(".help.tmp");
+}
+
+static void show_helptext(const char *title, const char *text)
+{
+ show_textbox(title, text, rows, cols);
+}
+
+static void show_help(struct menu *menu)
+{
+ const char *help;
+
+ help = menu->sym->help;
+ if (!help)
+ help = nohelp_text;
+ show_helptext(menu_get_prompt(menu), help);
+}
+
+static void show_readme(void)
+{
+ do {
+ cprint_init();
+ cprint("--textbox");
+ cprint("scripts/README.Menuconfig");
+ cprint("%d", rows);
+ cprint("%d", cols);
+ } while (exec_conf() == -1);
+}
+
+static void conf_choice(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+ struct menu *child;
+ struct symbol *active;
+ int stat;
+
+ while (1) {
+ cprint_init();
+ cprint("--title");
+ cprint("%s", prompt ? prompt : "Main Menu");
+ cprint("--radiolist");
+ cprint(radiolist_instructions);
+ cprint("15");
+ cprint("70");
+ cprint("6");
+
+ current_menu = menu;
+ active = sym_get_choice_value(menu->sym);
+ for (child = menu->list; child; child = child->next) {
+ if (!menu_is_visible(child))
+ continue;
+ cprint("%p", child);
+ cprint("%s", menu_get_prompt(child));
+ cprint(child->sym == active ? "ON" : "OFF");
+ }
+
+ stat = exec_conf();
+ switch (stat) {
+ case 0:
+ if (sscanf(input_buf, "%p", &menu) != 1)
+ break;
+ sym_set_tristate_value(menu->sym, yes);
+ return;
+ case 1:
+ show_help(menu);
+ break;
+ case 255:
+ return;
+ }
+ }
+}
+
+static void conf_string(struct menu *menu)
+{
+ const char *prompt = menu_get_prompt(menu);
+ int stat;
+
+ while (1) {
+ cprint_init();
+ cprint("--title");
+ cprint("%s", prompt ? prompt : "Main Menu");
+ cprint("--inputbox");
+ switch (sym_get_type(menu->sym)) {
+ case S_INT:
+ cprint(inputbox_instructions_int);
+ break;
+ case S_HEX:
+ cprint(inputbox_instructions_hex);
+ break;
+ case S_STRING:
+ cprint(inputbox_instructions_string);
+ break;
+ default:
+ /* panic? */;
+ }
+ cprint("10");
+ cprint("75");
+ cprint("%s", sym_get_string_value(menu->sym));
+ stat = exec_conf();
+ switch (stat) {
+ case 0:
+ if (sym_set_string_value(menu->sym, input_buf))
+ return;
+ show_textbox(NULL, "You have made an invalid entry.", 5, 43);
+ break;
+ case 1:
+ show_help(menu);
+ break;
+ case 255:
+ return;
+ }
+ }
+}
+
+static void conf_load(void)
+{
+ int stat;
+
+ while (1) {
+ cprint_init();
+ cprint("--inputbox");
+ cprint(load_config_text);
+ cprint("11");
+ cprint("55");
+ cprint("%s", conf_filename);
+ stat = exec_conf();
+ switch(stat) {
+ case 0:
+ if (!input_buf[0])
+ return;
+ if (!conf_read(input_buf))
+ return;
+ show_textbox(NULL, "File does not exist!", 5, 38);
+ break;
+ case 1:
+ show_helptext("Load Alternate Configuration", load_config_help);
+ break;
+ case 255:
+ return;
+ }
+ }
+}
+
+static void conf_save(void)
+{
+ int stat;
+
+ while (1) {
+ cprint_init();
+ cprint("--inputbox");
+ cprint(save_config_text);
+ cprint("11");
+ cprint("55");
+ cprint("%s", conf_filename);
+ stat = exec_conf();
+ switch(stat) {
+ case 0:
+ if (!input_buf[0])
+ return;
+ if (!conf_write(input_buf))
+ return;
+ show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60);
+ break;
+ case 1:
+ show_helptext("Save Alternate Configuration", save_config_help);
+ break;
+ case 255:
+ return;
+ }
+ }
+}
+
+int main(int ac, char **av)
+{
+ int stat;
+ conf_parse(av[1]);
+ conf_read(NULL);
+
+ sprintf(menu_backtitle, "Configuration");
+
+ init_wsize();
+ conf(&rootmenu);
+
+ do {
+ cprint_init();
+ cprint("--yesno");
+ cprint("Do you wish to save your new configuration?");
+ cprint("5");
+ cprint("60");
+ stat = exec_conf();
+ } while (stat < 0);
+
+ if (stat == 0) {
+ conf_write(NULL);
+ printf("\n\n"
+ "*** End of configuration.\n"
+ "*** Check the top-level Makefile for additional configuration.\n");
+ } else
+ printf("\n\nYour configuration changes were NOT saved.\n\n");
+
+ return 0;
+}
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
new file mode 100644
index 0000000..4595110
--- a/dev/null
+++ b/scripts/kconfig/menu.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+struct menu rootmenu;
+struct menu *current_menu, *current_entry;
+static struct menu **last_entry_ptr;
+
+struct file *file_list;
+struct file *current_file;
+
+void menu_init(void)
+{
+ current_entry = current_menu = &rootmenu;
+ last_entry_ptr = &rootmenu.list;
+}
+
+void menu_add_entry(struct symbol *sym)
+{
+ struct menu *menu;
+
+ menu = malloc(sizeof(*menu));
+ memset(menu, 0, sizeof(*menu));
+ menu->sym = sym;
+ menu->parent = current_menu;
+ menu->file = current_file;
+ menu->lineno = zconf_lineno();
+
+ *last_entry_ptr = menu;
+ last_entry_ptr = &menu->next;
+ current_entry = menu;
+}
+
+void menu_end_entry(void)
+{
+}
+
+void menu_add_menu(void)
+{
+ current_menu = current_entry;
+ last_entry_ptr = &current_entry->list;
+}
+
+void menu_end_menu(void)
+{
+ last_entry_ptr = &current_menu->next;
+ current_menu = current_menu->parent;
+}
+
+void menu_add_dep(struct expr *dep)
+{
+ current_entry->dep = expr_alloc_and(current_entry->dep, dep);
+}
+
+void menu_set_type(int type)
+{
+ struct symbol *sym = current_entry->sym;
+
+ if (sym->type == type)
+ return;
+ if (sym->type == S_UNKNOWN) {
+ sym->type = type;
+ return;
+ }
+ fprintf(stderr, "%s:%d: type of '%s' redefined from '%s' to '%s'\n",
+ current_entry->file->name, current_entry->lineno,
+ sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type));
+}
+
+struct property *create_prop(enum prop_type type)
+{
+ struct property *prop;
+
+ prop = malloc(sizeof(*prop));
+ memset(prop, 0, sizeof(*prop));
+ prop->type = type;
+ prop->file = current_file;
+ prop->lineno = zconf_lineno();
+
+ return prop;
+}
+
+struct property *menu_add_prop(int token, char *prompt, struct symbol *def, struct expr *dep)
+{
+ struct property *prop = create_prop(token);
+ struct property **propp;
+
+ prop->sym = current_entry->sym;
+ prop->menu = current_entry;
+ prop->text = prompt;
+ prop->def = def;
+ E_EXPR(prop->visible) = dep;
+
+ if (prompt)
+ current_entry->prompt = prop;
+
+ /* append property to the prop list of symbol */
+ if (prop->sym) {
+ for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next)
+ ;
+ *propp = prop;
+ }
+
+ return prop;
+}
+
+void menu_add_prompt(int token, char *prompt, struct expr *dep)
+{
+ current_entry->prompt = menu_add_prop(token, prompt, NULL, dep);
+}
+
+void menu_add_default(int token, struct symbol *def, struct expr *dep)
+{
+ current_entry->prompt = menu_add_prop(token, NULL, def, dep);
+}
+
+void menu_finalize(struct menu *parent)
+{
+ struct menu *menu, *last_menu;
+ struct symbol *sym;
+ struct property *prop;
+ struct expr *parentdep, *basedep, *dep, *dep2;
+
+ sym = parent->sym;
+ if (parent->list) {
+ if (sym && sym_is_choice(sym)) {
+ /* find the first choice value and find out choice type */
+ for (menu = parent->list; menu; menu = menu->next) {
+ if (menu->sym) {
+ current_entry = parent;
+ menu_set_type(menu->sym->type);
+ current_entry = menu;
+ menu_set_type(sym->type);
+ break;
+ }
+ }
+ parentdep = expr_alloc_symbol(sym);
+ } else if (parent->prompt)
+ parentdep = E_EXPR(parent->prompt->visible);
+ else
+ parentdep = parent->dep;
+
+ for (menu = parent->list; menu; menu = menu->next) {
+ basedep = expr_transform(menu->dep);
+ basedep = expr_alloc_and(expr_copy(parentdep), basedep);
+ basedep = expr_eliminate_dups(basedep);
+ menu->dep = basedep;
+ if (menu->sym)
+ prop = menu->sym->prop;
+ else
+ prop = menu->prompt;
+ for (; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ dep = expr_transform(E_EXPR(prop->visible));
+ dep = expr_alloc_and(expr_copy(basedep), dep);
+ dep = expr_eliminate_dups(dep);
+ if (menu->sym && menu->sym->type != S_TRISTATE)
+ dep = expr_trans_bool(dep);
+ E_EXPR(prop->visible) = dep;
+ }
+ }
+ for (menu = parent->list; menu; menu = menu->next)
+ menu_finalize(menu);
+ } else if (sym && parent->prompt) {
+ basedep = E_EXPR(parent->prompt->visible);
+ basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
+ basedep = expr_eliminate_dups(expr_transform(basedep));
+ last_menu = NULL;
+ for (menu = parent->next; menu; menu = menu->next) {
+ dep = menu->prompt ? E_EXPR(menu->prompt->visible) : menu->dep;
+ if (!expr_contains_symbol(dep, sym))
+ break;
+ if (expr_depends_symbol(dep, sym))
+ goto next;
+ dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
+ dep = expr_eliminate_dups(expr_transform(dep));
+ dep2 = expr_copy(basedep);
+ expr_eliminate_eq(&dep, &dep2);
+ expr_free(dep);
+ if (!expr_is_yes(dep2)) {
+ expr_free(dep2);
+ break;
+ }
+ expr_free(dep2);
+ next:
+ menu_finalize(menu);
+ menu->parent = parent;
+ last_menu = menu;
+ }
+ if (last_menu) {
+ parent->list = parent->next;
+ parent->next = last_menu->next;
+ last_menu->next = NULL;
+ }
+ }
+ for (menu = parent->list; menu; menu = menu->next) {
+ if (sym && sym_is_choice(sym) && menu->sym) {
+ menu->sym->flags |= SYMBOL_CHOICEVAL;
+ current_entry = menu;
+ menu_set_type(sym->type);
+ menu_add_prop(P_CHOICE, NULL, parent->sym, NULL);
+ prop = sym_get_choice_prop(parent->sym);
+ //dep = expr_alloc_one(E_CHOICE, dep);
+ //dep->right.sym = menu->sym;
+ prop->dep = expr_alloc_one(E_CHOICE, prop->dep);
+ prop->dep->right.sym = menu->sym;
+ }
+ if (menu->list && (!menu->prompt || !menu->prompt->text)) {
+ for (last_menu = menu->list; ; last_menu = last_menu->next) {
+ last_menu->parent = parent;
+ if (!last_menu->next)
+ break;
+ }
+ last_menu->next = menu->next;
+ menu->next = menu->list;
+ menu->list = NULL;
+ }
+ }
+}
+
+bool menu_is_visible(struct menu *menu)
+{
+ tristate visible;
+
+ if (!menu->prompt)
+ return false;
+ if (menu->sym) {
+ sym_calc_value(menu->sym);
+ visible = E_TRI(menu->prompt->visible);
+ } else
+ visible = E_CALC(menu->prompt->visible);
+ return visible != no;
+}
+
+const char *menu_get_prompt(struct menu *menu)
+{
+ if (menu->prompt)
+ return menu->prompt->text;
+ else if (menu->sym)
+ return menu->sym->name;
+ return NULL;
+}
+
+struct menu *menu_get_root_menu(struct menu *menu)
+{
+ return &rootmenu;
+}
+
+struct menu *menu_get_parent_menu(struct menu *menu)
+{
+ enum prop_type type;
+
+ while (menu != &rootmenu) {
+ menu = menu->parent;
+ type = menu->prompt ? menu->prompt->type : 0;
+ if (type == P_MENU || type == P_ROOTMENU)
+ break;
+ }
+ return menu;
+}
+
+struct file *file_lookup(const char *name)
+{
+ struct file *file;
+
+ for (file = file_list; file; file = file->next) {
+ if (!strcmp(name, file->name))
+ return file;
+ }
+
+ file = malloc(sizeof(*file));
+ memset(file, 0, sizeof(*file));
+ file->name = strdup(name);
+ file->next = file_list;
+ file_list = file;
+ return file;
+}
+
+int file_write_dep(const char *name)
+{
+ struct file *file;
+ FILE *out;
+
+ if (!name)
+ name = "..config.cmd";
+ out = fopen("..config.tmp", "w");
+ if (!out)
+ return 1;
+ fprintf(out, "deps_config := \\\n");
+ for (file = file_list; file; file = file->next) {
+ if (file->next)
+ fprintf(out, "\t%s \\\n", file->name);
+ else
+ fprintf(out, "\t%s\n", file->name);
+ }
+ fprintf(out, "\n.config include/linux/autoconf.h: $(deps_config)\n\n$(deps_config):\n");
+ fclose(out);
+ rename("..config.tmp", name);
+ return 0;
+}
+
diff --git a/scripts/kconfig/prepare-all.diff b/scripts/kconfig/prepare-all.diff
new file mode 100644
index 0000000..305aabc
--- a/dev/null
+++ b/scripts/kconfig/prepare-all.diff
@@ -0,0 +1,1883 @@
+Index: Makefile
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/Makefile,v
+retrieving revision 1.1.1.44
+diff -u -p -r1.1.1.44 Makefile
+--- Makefile 16 Oct 2002 19:38:52 -0000 1.1.1.44
++++ Makefile 16 Oct 2002 23:00:47 -0000
+@@ -44,7 +44,9 @@
+ TOPDIR := $(CURDIR)
+
+ HOSTCC = gcc
++HOSTCXX = g++
+ HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
++HOSTCXXFLAGS = -O2
+
+ CROSS_COMPILE =
+
+@@ -161,7 +163,8 @@
+
+ export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
+ CONFIG_SHELL TOPDIR HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
+- CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES GENKSYMS PERL
++ CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES GENKSYMS PERL \
++ HOSTCXX HOSTCXXFLAGS
+
+ export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS
+ export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
+@@ -237,21 +240,7 @@
+
+ # In this section, we need .config
+
+-# If .config doesn't exist - tough luck
+-
+-.config: arch/$(ARCH)/config.in # FIXME $(shell find . -name Config.in)
+- @echo '***'
+- @if [ -f $@ ]; then \
+- echo '*** The tree was updated, so your .config may be'; \
+- echo '*** out of date!'; \
+- else \
+- echo '*** You have not yet configured your kernel!'; \
+- fi
+- @echo '***'
+- @echo '*** Please run some configurator (e.g. "make oldconfig" or'
+- @echo '*** "make menuconfig" or "make xconfig").'
+- @echo '***'
+- @exit 1
++-include ..config.cmd
+
+ ifdef CONFIG_MODULES
+ export EXPORT_FLAGS := -DEXPORT_SYMTAB
+@@ -419,11 +408,8 @@
+ # with it and forgot to run make oldconfig
+
+ include/linux/autoconf.h: .config
+- @echo '***'
+- @echo '*** You changed .config w/o running make *config?'
+- @echo '*** Please run "make oldconfig"'
+- @echo '***'
+- @exit 1
++ +@$(call descend,scripts/kconfig,scripts/kconfig/conf)
++ ./scripts/kconfig/conf -s arch/$(ARCH)/Kconfig
+
+ # Generate some files
+ # ---------------------------------------------------------------------------
+@@ -637,34 +623,36 @@
+ .PHONY: oldconfig xconfig menuconfig config \
+ make_with_config
+
+-xconfig:
+- +@$(call descend,scripts,scripts/kconfig.tk)
+- wish -f scripts/kconfig.tk
++scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf: scripts/fixdep FORCE
++ +@$(call descend,scripts/kconfig,$@)
++
++xconfig: scripts/kconfig/qconf
++ ./scripts/kconfig/qconf arch/$(ARCH)/Kconfig
+
+-menuconfig:
+- +@$(call descend,scripts,lxdialog)
+- $(CONFIG_SHELL) $(src)/scripts/Menuconfig arch/$(ARCH)/config.in
++menuconfig: scripts/kconfig/mconf
++ +@$(call descend,scripts/lxdialog,)
++ ./scripts/kconfig/mconf arch/$(ARCH)/Kconfig
+
+-config:
+- $(CONFIG_SHELL) $(src)/scripts/Configure arch/$(ARCH)/config.in
++config: scripts/kconfig/conf
++ ./scripts/kconfig/conf arch/$(ARCH)/Kconfig
+
+-oldconfig:
+- $(CONFIG_SHELL) $(src)/scripts/Configure -d arch/$(ARCH)/config.in
++oldconfig: scripts/kconfig/conf
++ ./scripts/kconfig/conf -o arch/$(ARCH)/Kconfig
+
+-randconfig:
+- $(CONFIG_SHELL) $(src)/scripts/Configure -r arch/$(ARCH)/config.in
++randconfig: scripts/kconfig/conf
++ ./scripts/kconfig/conf -r arch/$(ARCH)/Kconfig
+
+-allyesconfig:
+- $(CONFIG_SHELL) $(src)/scripts/Configure -y arch/$(ARCH)/config.in
++allyesconfig: scripts/kconfig/conf
++ ./scripts/kconfig/conf -y arch/$(ARCH)/Kconfig
+
+-allnoconfig:
+- $(CONFIG_SHELL) $(src)/scripts/Configure -n arch/$(ARCH)/config.in
++allnoconfig: scripts/kconfig/conf
++ ./scripts/kconfig/conf -n arch/$(ARCH)/Kconfig
+
+-allmodconfig:
+- $(CONFIG_SHELL) $(src)/scripts/Configure -m arch/$(ARCH)/config.in
++allmodconfig: scripts/kconfig/conf
++ ./scripts/kconfig/conf -m arch/$(ARCH)/Kconfig
+
+-defconfig:
+- yes '' | $(CONFIG_SHELL) $(src)/scripts/Configure -d arch/$(ARCH)/config.in
++defconfig: scripts/kconfig/conf
++ ./scripts/kconfig/conf -d arch/$(ARCH)/Kconfig
+
+ ###
+ # Cleaning is done on three levels.
+Index: Rules.make
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/Rules.make,v
+retrieving revision 1.1.1.22
+diff -u -p -r1.1.1.22 Rules.make
+--- Rules.make 12 Oct 2002 11:42:02 -0000 1.1.1.22
++++ Rules.make 16 Oct 2002 23:00:49 -0000
+@@ -114,9 +114,33 @@
+ # Only build module versions for files which are selected to be built
+ export-objs := $(filter $(export-objs),$(real-objs-y) $(real-objs-m))
+
+-host-progs-single := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
+-host-progs-multi := $(foreach m,$(host-progs),$(if $($(m)-objs),$(m)))
+-host-progs-multi-objs := $(foreach m,$(host-progs-multi),$($(m)-objs))
++# C code
++# Executables compiled from a single .c file
++host-csingle := $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
++
++# C executables linked based on several .o files
++host-cmulti := $(foreach m,$(host-progs),\
++ $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
++
++# Object (.o) files compiled from .c files
++host-cobjs := $(sort $(foreach m,$(host-progs),$($(m)-objs)))
++
++# C++ code
++# C++ executables compiled from at least on .cc file
++# and zero or more .c files
++host-cxxmulti := $(foreach m,$(host-progs),$(if $($(m)-cxxobjs),$(m)))
++
++# C++ Object (.o) files compiled from .cc files
++host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
++
++# Shared libaries (only .c supported)
++# Shared libraries (.so) - all .so files referenced in "xxx-objs"
++host-cshlib := $(sort $(filter %.so, $(host-cobjs)))
++# Remove .so files from "xxx-objs"
++host-cobjs := $(filter-out %.so,$(host-cobjs))
++
++#Object (.o) files used by the shared libaries
++host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
+
+ # Add subdir path
+
+@@ -134,10 +158,14 @@
+ subdir-ym := $(addprefix $(obj)/,$(subdir-ym))
+ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
+ clean-files := $(addprefix $(obj)/,$(clean-files))
+-host-progs := $(addprefix $(obj)/,$(host-progs))
+-host-progs-single := $(addprefix $(obj)/,$(host-progs-single))
+-host-progs-multi := $(addprefix $(obj)/,$(host-progs-multi))
+-host-progs-multi-objs := $(addprefix $(obj)/,$(host-progs-multi-objs))
++host-progs := $(addprefix $(obj)/,$(host-progs))
++host-csingle := $(addprefix $(obj)/,$(host-csingle))
++host-cmulti := $(addprefix $(obj)/,$(host-cmulti))
++host-cobjs := $(addprefix $(obj)/,$(host-cobjs))
++host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti))
++host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs))
++host-cshlib := $(addprefix $(obj)/,$(host-cshlib))
++host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs))
+
+ # The temporary file to save gcc -MD generated dependencies must not
+ # contain a comma
+@@ -423,30 +451,96 @@
+
+ # Compile programs on the host
+ # ===========================================================================
++# host-progs := bin2hex
++# Will compile bin2hex.c and create an executable named bin2hex
++#
++# host-progs := lxdialog
++# lxdialog-objs := checklist.o lxdialog.o
++# Will compile lxdialog.c and checklist.c, and then link the executable
++# lxdialog, based on checklist.o and lxdialog.o
++#
++# host-progs := qconf
++# qconf-cxxobjs := qconf.o
++# qconf-objs := menu.o
++# Will compile qconf as a C++ program, and menu as a C program.
++# They are linked as C++ code to the executable qconf
++
++# host-progs := conf
++# conf-objs := conf.o libkconfig.so
++# libkconfig-objs := expr.o type.o
++# Will create a shared library named libkconfig.so that consist of
++# expr.o and type.o (they are both compiled as C code and the object file
++# are made as position independent code).
++# conf.c is compiled as a c program, and conf.o is linked together with
++# libkconfig.so as the executable conf.
++# Note: Shared libraries consisting of C++ files are not supported
++#
++
++# Create executable from a single .c file
++# host-csingle -> Executable
++quiet_cmd_host-csingle = HOSTCC $(echo_target)
++ cmd_host-csingle = $(HOSTCC) -Wp,-MD,$(depfile) \
++ $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
++ $(HOST_LOADLIBES) -o $@ $<
++$(host-csingle): %: %.c FORCE
++ $(call if_changed_dep,host-csingle)
++
++# Link an executable based on list of .o files, all plain c
++# host-cmulti -> executable
++quiet_cmd_host-cmulti = HOSTLD $(echo_target)
++ cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
++ $(addprefix $(obj)/,$($(@F)-objs)) \
++ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
++$(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE
++ $(call if_changed,host-cmulti)
++
++# Create .o file from a single .c file
++# host-cobjs -> .o
++quiet_cmd_host-cobjs = HOSTCC $(echo_target)
++ cmd_host-cobjs = $(HOSTCC) -Wp,-MD,$(depfile) \
++ $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
++ $(HOSTCFLAGS_$(@F)) -c -o $@ $<
++$(host-cobjs): %.o: %.c FORCE
++ $(call if_changed_dep,host-cobjs)
++
++# Link an executable based on list of .o files, a mixture of .c and .cc
++# host-cxxmulti -> executable
++quiet_cmd_host-cxxmulti = HOSTLD $(echo_target)
++ cmd_host-cxxmulti = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
++ $(foreach o,objs cxxobjs,\
++ $(addprefix $(obj)/,$($(@F)-$(o)))) \
++ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
++$(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
++ $(call if_changed,host-cxxmulti)
++
++# Create .o file from a single .cc (C++) file
++quiet_cmd_host-cxxobjs = HOSTCXX $(echo_target)
++ cmd_host-cxxobjs = $(HOSTCXX) -Wp,-MD,$(depfile) \
++ $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
++ $(HOSTCXXFLAGS_$(@F)) -c -o $@ $<
++$(host-cxxobjs): %.o: %.cc FORCE
++ $(call if_changed_dep,host-cxxobjs)
++
++# Compile .c file, create position independent .o file
++# host-cshobjs -> .o
++quiet_cmd_host-cshobjs = HOSTCC -fPIC $(echo_target)
++ cmd_host-cshobjs = $(HOSTCC) -Wp,-MD,$(depfile) -fPIC\
++ $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
++ $(HOSTCFLAGS_$(@F)) -c -o $@ $<
++$(host-cshobjs): %.o: %.c FORCE
++ $(call if_changed_dep,host-cshobjs)
++
++# Link a shared library, based on position independent .o files
++# *.o -> .so shared library (host-cshlib)
++quiet_cmd_host-cshlib = HOSTLLD -shared $(echo_target)
++ cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
++ $(addprefix $(obj)/,$($(@F:.so=-objs))) \
++ $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
++$(host-cshlib): %: $(host-cshobjs) FORCE
++ $(call if_changed,host-cshlib)
+
+-quiet_cmd_host_cc__c = HOSTCC $(echo_target)
+-cmd_host_cc__c = $(HOSTCC) -Wp,-MD,$(depfile) \
+- $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \
+- $(HOST_LOADLIBES) -o $@ $<
+-
+-$(host-progs-single): %: %.c FORCE
+- $(call if_changed_dep,host_cc__c)
+-
+-quiet_cmd_host_cc_o_c = HOSTCC $(echo_target)
+-cmd_host_cc_o_c = $(HOSTCC) -Wp,-MD,$(depfile) \
+- $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) -c -o $@ $<
+-
+-$(host-progs-multi-objs): %.o: %.c FORCE
+- $(call if_changed_dep,host_cc_o_c)
+-
+-quiet_cmd_host_cc__o = HOSTLD $(echo_target)
+-cmd_host_cc__o = $(HOSTCC) $(HOSTLDFLAGS) -o $@ $(addprefix $(obj)/,$($(subst $(obj)/,,$@)-objs)) \
+- $(HOST_LOADLIBES)
+-
+-$(host-progs-multi): %: $(host-progs-multi-objs) FORCE
+- $(call if_changed,host_cc__o)
+-
+-targets += $(host-progs-single) $(host-progs-multi-objs) $(host-progs-multi)
++targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\
++ $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs)
+
+ endif # ! subdirclean
+ endif # ! modules_install
+Index: arch/alpha/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/alpha/config.in,v
+retrieving revision 1.1.1.16
+diff -u -p -r1.1.1.16 config.in
+--- arch/alpha/config.in 12 Oct 2002 11:50:40 -0000 1.1.1.16
++++ arch/alpha/config.in 16 Oct 2002 23:00:53 -0000
+@@ -19,11 +19,11 @@ choice 'Alpha system type' \
+ Alcor/Alpha-XLT CONFIG_ALPHA_ALCOR \
+ Alpha-XL CONFIG_ALPHA_XL \
+ AlphaBook1 CONFIG_ALPHA_BOOK1 \
+- Avanti CONFIG_ALPHA_AVANTI \
++ Avanti CONFIG_ALPHA_AVANTI_CH \
+ Cabriolet CONFIG_ALPHA_CABRIOLET \
+ DP264 CONFIG_ALPHA_DP264 \
+ EB164 CONFIG_ALPHA_EB164 \
+- EB64+ CONFIG_ALPHA_EB64P \
++ EB64+ CONFIG_ALPHA_EB64P_CH \
+ EB66 CONFIG_ALPHA_EB66 \
+ EB66+ CONFIG_ALPHA_EB66P \
+ Eiger CONFIG_ALPHA_EIGER \
+@@ -32,7 +32,7 @@ choice 'Alpha system type' \
+ Miata CONFIG_ALPHA_MIATA \
+ Mikasa CONFIG_ALPHA_MIKASA \
+ Nautilus CONFIG_ALPHA_NAUTILUS \
+- Noname CONFIG_ALPHA_NONAME \
++ Noname CONFIG_ALPHA_NONAME_CH \
+ Noritake CONFIG_ALPHA_NORITAKE \
+ PC164 CONFIG_ALPHA_PC164 \
+ Platform2000 CONFIG_ALPHA_P2K \
+@@ -69,7 +69,7 @@ else
+ define_bool CONFIG_PCI y
+ fi
+
+-if [ "$CONFIG_ALPHA_BOOK1" = "y" ]
++if [ "$CONFIG_ALPHA_BOOK1" = "y" -o "$CONFIG_ALPHA_NONAME_CH" = "y" ]
+ then
+ define_bool CONFIG_ALPHA_NONAME y
+ fi
+@@ -79,13 +79,13 @@ then
+ define_bool CONFIG_ALPHA_EV4 y
+ define_bool CONFIG_ALPHA_LCA y
+ fi
+-if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
+- -o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_XL" = "y" ]
++if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI_CH" = "y" \
++ -o "$CONFIG_ALPHA_EB64P_CH" = "y" -o "$CONFIG_ALPHA_XL" = "y" ]
+ then
+ define_bool CONFIG_ALPHA_EV4 y
+ define_bool CONFIG_ALPHA_APECS y
+ fi
+-if [ "$CONFIG_ALPHA_CABRIOLET" = "y" ]
++if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_EB64P_CH" = "y" ]
+ then
+ define_bool CONFIG_ALPHA_EB64P y
+ fi
+@@ -198,7 +198,7 @@ if [ "$CONFIG_ALPHA_JENSEN" = "y" -o "$C
+ then
+ define_bool CONFIG_ALPHA_SRM y
+ fi
+-if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
++if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI_CH" = "y" \
+ -o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_PC164" = "y" \
+ -o "$CONFIG_ALPHA_TAKARA" = "y" -o "$CONFIG_ALPHA_EB164" = "y" \
+ -o "$CONFIG_ALPHA_ALCOR" = "y" -o "$CONFIG_ALPHA_MIATA" = "y" \
+@@ -214,7 +214,7 @@ if [ "$CONFIG_ALPHA_ALCOR" = "y" -o "$CO
+ then
+ define_bool CONFIG_ALPHA_EISA y
+ fi
+-if [ "$CONFIG_ALPHA_XL" = "y" ]
++if [ "$CONFIG_ALPHA_XL" = "y" -o "$CONFIG_ALPHA_AVANTI_CH" = "y" ]
+ then
+ define_bool CONFIG_ALPHA_AVANTI y
+ fi
+@@ -253,7 +253,7 @@ bool 'Support for hot-pluggable devices'
+ if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+ source drivers/pcmcia/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
++ define_tristate CONFIG_PCMCIA n
+ fi
+
+ if [ "$CONFIG_PROC_FS" = "y" ]; then
+@@ -306,9 +306,9 @@ if [ "$CONFIG_SCSI" != "n" ]; then
+ fi
+ endmenu
+
+-if [ "$CONFIG_PCI" = "y" ]; then
++#if [ "$CONFIG_PCI" = "y" ]; then
+ source drivers/message/fusion/Config.in
+-fi
++#fi
+
+ if [ "$CONFIG_NET" = "y" ]; then
+ source net/Config.in
+@@ -399,3 +399,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/arm/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/arm/config.in,v
+retrieving revision 1.1.1.17
+diff -u -p -r1.1.1.17 config.in
+--- arch/arm/config.in 16 Oct 2002 19:45:13 -0000 1.1.1.17
++++ arch/arm/config.in 16 Oct 2002 23:00:54 -0000
+@@ -356,7 +356,7 @@ bool 'Support for hot-pluggable devices'
+ if [ "$CONFIG_HOTPLUG" = "y" ]; then
+ source drivers/pcmcia/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
++ define_tristate CONFIG_PCMCIA n
+ fi
+ comment 'At least one math emulation must be selected'
+ tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE
+@@ -416,10 +416,11 @@ endmenu
+
+ source drivers/parport/Config.in
+
+-if [ "$CONFIG_ALIGNMENT_TRAP" = "y" ]; then
++#if [ "$CONFIG_ALIGNMENT_TRAP" = "y" ]; then
+ source drivers/mtd/Config.in
+-else
+- define_bool CONFIG_MTD n
++#else
++if [ "$CONFIG_ALIGNMENT_TRAP" != "y" ]; then
++ define_tristate CONFIG_MTD n
+ fi
+
+ source drivers/pnp/Config.in
+@@ -442,10 +443,11 @@ if [ "$CONFIG_NET" = "y" ]; then
+ fi
+ endmenu
+
+- source net/ax25/Config.in
++# source net/ax25/Config.in
+
+ source net/irda/Config.in
+ fi
++ source net/ax25/Config.in
+
+ mainmenu_option next_comment
+ comment 'ATA/ATAPI/MFM/RLL support'
+@@ -469,9 +471,9 @@ if [ "$CONFIG_SCSI" != "n" ]; then
+ fi
+ endmenu
+
+-if [ "$CONFIG_ARCH_CLPS711X" = "y" ]; then
+- source drivers/ssi/Config.in
+-fi
++#if [ "$CONFIG_ARCH_CLPS711X" = "y" ]; then
++# source drivers/ssi/Config.in
++#fi
+
+ source drivers/ieee1394/Config.in
+
+@@ -554,3 +556,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/cris/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/cris/config.in,v
+retrieving revision 1.1.1.8
+diff -u -p -r1.1.1.8 config.in
+--- arch/cris/config.in 27 Aug 2002 23:44:08 -0000 1.1.1.8
++++ arch/cris/config.in 16 Oct 2002 23:00:57 -0000
+@@ -230,3 +230,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/cris/drivers/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/cris/drivers/Config.in,v
+retrieving revision 1.1.1.3
+diff -u -p -r1.1.1.3 Config.in
+--- arch/cris/drivers/Config.in 25 May 2002 16:26:27 -0000 1.1.1.3
++++ arch/cris/drivers/Config.in 16 Oct 2002 23:00:57 -0000
+@@ -111,11 +111,11 @@ if [ "$CONFIG_ETRAX_IDE" = "y" ]; then
+ # general ide drivers so the common case does not need to go
+ # into that config submenu. enable disk and CD support. others
+ # need to go fiddle in the submenu..
+- define_bool CONFIG_IDE y
++ define_tristate CONFIG_IDE y
+
+- define_bool CONFIG_BLK_DEV_IDE y
+- define_bool CONFIG_BLK_DEV_IDEDISK y
+- define_bool CONFIG_BLK_DEV_IDECD y
++ define_tristate CONFIG_BLK_DEV_IDE y
++ define_tristate CONFIG_BLK_DEV_IDEDISK y
++ define_tristate CONFIG_BLK_DEV_IDECD y
+
+ define_bool CONFIG_BLK_DEV_IDEDMA y
+
+@@ -127,7 +127,7 @@ if [ "$CONFIG_ETRAX_IDE" = "y" ]; then
+ Port_CSE1_Bit_16 CONFIG_ETRAX_IDE_CSE1_16_RESET\
+ Port_CSP0_Bit_08 CONFIG_ETRAX_IDE_CSP0_8_RESET" Port_PB_Bit_7
+ else
+- define_bool CONFIG_IDE n
++ define_tristate CONFIG_IDE n
+ fi
+
+ bool 'Axis flash-map support' CONFIG_ETRAX_AXISFLASHMAP
+@@ -136,17 +136,17 @@ if [ "$CONFIG_ETRAX_AXISFLASHMAP" = "y"
+ int ' Byte-offset of partition table sector' CONFIG_ETRAX_PTABLE_SECTOR 65536
+ # here we define the CONFIG_'s necessary to enable MTD support
+ # for the flash
+- define_bool CONFIG_MTD y
++ define_tristate CONFIG_MTD y
+
+- define_bool CONFIG_MTD_CFI y
+- define_bool CONFIG_MTD_CFI_INTELEXT n
+- define_bool CONFIG_MTD_CFI_AMDSTD y
++ define_tristate CONFIG_MTD_CFI y
++ define_tristate CONFIG_MTD_CFI_INTELEXT n
++ define_tristate CONFIG_MTD_CFI_AMDSTD y
+
+- define_bool CONFIG_MTD_AMDSTD y
++ define_tristate CONFIG_MTD_AMDSTD y
+
+- define_bool CONFIG_MTD_CHAR y
+- define_bool CONFIG_MTD_BLOCK y
+- define_bool CONFIG_MTD_PARTITIONS y
++ define_tristate CONFIG_MTD_CHAR y
++ define_tristate CONFIG_MTD_BLOCK y
++ define_tristate CONFIG_MTD_PARTITIONS y
+ fi
+
+ bool 'I2C support' CONFIG_ETRAX_I2C
+@@ -182,11 +182,11 @@ fi
+
+ bool 'USB host' CONFIG_ETRAX_USB_HOST
+ if [ "$CONFIG_ETRAX_USB_HOST" = "y" ]; then
+- define_bool CONFIG_USB y
++ define_tristate CONFIG_USB y
+ bool ' USB port 1 enabled' CONFIG_ETRAX_USB_HOST_PORT1
+ bool ' USB port 2 enabled' CONFIG_ETRAX_USB_HOST_PORT2
+ else
+- define_bool CONFIG_USB n
++ define_tristate CONFIG_USB n
+ fi
+
+ bool 'DS1302 Real Time Clock support' CONFIG_ETRAX_DS1302
+Index: arch/i386/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/i386/config.in,v
+retrieving revision 1.1.1.28
+diff -u -p -r1.1.1.28 config.in
+--- arch/i386/config.in 16 Oct 2002 19:44:19 -0000 1.1.1.28
++++ arch/i386/config.in 16 Oct 2002 23:00:59 -0000
+@@ -185,6 +185,7 @@ else
+ fi
+ fi
+ fi
++ define_bool CONFIG_X86_UP_APIC y
+ fi
+
+ bool 'Machine Check Exception' CONFIG_X86_MCE
+@@ -313,8 +314,8 @@ if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+ source drivers/pcmcia/Config.in
+ source drivers/hotplug/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
+- define_bool CONFIG_HOTPLUG_PCI n
++ define_tristate CONFIG_PCMCIA n
++ define_tristate CONFIG_HOTPLUG_PCI n
+ fi
+
+ endmenu
+@@ -423,10 +424,10 @@ if [ "$CONFIG_VT" = "y" ]; then
+ comment 'Console drivers'
+ bool 'VGA text console' CONFIG_VGA_CONSOLE
+ bool 'Video mode selection support' CONFIG_VIDEO_SELECT
+- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++ #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
+ source drivers/video/Config.in
+- fi
++ #fi
+ endmenu
+ fi
+
+@@ -480,3 +481,4 @@ if [ "$CONFIG_SMP" = "y" ]; then
+ fi
+
+ define_bool CONFIG_X86_BIOS_REBOOT y
++source config.undef
+Index: arch/ia64/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/ia64/config.in,v
+retrieving revision 1.1.1.16
+diff -u -p -r1.1.1.16 config.in
+--- arch/ia64/config.in 12 Oct 2002 11:52:18 -0000 1.1.1.16
++++ arch/ia64/config.in 16 Oct 2002 23:01:01 -0000
+@@ -28,17 +28,27 @@ choice 'IA-64 system type' \
+
+ if [ "$CONFIG_ITANIUM" = "y" ]; then
+ choice 'Kernel page size' \
+- "4KB CONFIG_IA64_PAGE_SIZE_4KB \
+- 8KB CONFIG_IA64_PAGE_SIZE_8KB \
+- 16KB CONFIG_IA64_PAGE_SIZE_16KB" 16KB
++ "4KB CONFIG_IA64_PAGE_SIZE_4KB_1 \
++ 8KB CONFIG_IA64_PAGE_SIZE_8KB_1 \
++ 16KB CONFIG_IA64_PAGE_SIZE_16KB_1" 16KB
+ else
+ choice 'Kernel page size' \
+- "4KB CONFIG_IA64_PAGE_SIZE_4KB \
+- 8KB CONFIG_IA64_PAGE_SIZE_8KB \
+- 16KB CONFIG_IA64_PAGE_SIZE_16KB \
++ "4KB CONFIG_IA64_PAGE_SIZE_4KB_2 \
++ 8KB CONFIG_IA64_PAGE_SIZE_8KB_2 \
++ 16KB CONFIG_IA64_PAGE_SIZE_16KB_2 \
+ 64KB CONFIG_IA64_PAGE_SIZE_64KB" 16KB
+ fi
+
++if [ "$CONFIG_IA64_PAGE_SIZE_4KB_1" = "y" -o "$CONFIG_IA64_PAGE_SIZE_4KB_2" = "y" ]; then
++ define_bool CONFIG_IA64_PAGE_SIZE_4KB y
++fi
++if [ "$CONFIG_IA64_PAGE_SIZE_8KB_1" = "y" -o "$CONFIG_IA64_PAGE_SIZE_8KB_2" = "y" ]; then
++ define_bool CONFIG_IA64_PAGE_SIZE_8KB y
++fi
++if [ "$CONFIG_IA64_PAGE_SIZE_16KB_1" = "y" -o "$CONFIG_IA64_PAGE_SIZE_16KB_2" = "y" ]; then
++ define_bool CONFIG_IA64_PAGE_SIZE_16KB y
++fi
++
+ if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ define_bool CONFIG_ACPI y
+ define_bool CONFIG_ACPI_EFI y
+@@ -64,7 +74,7 @@ if [ "$CONFIG_MCKINLEY" = "y" ]; then
+ fi
+ fi
+
+-if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ];
++if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ]
+ then
+ bool ' Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
+ define_bool CONFIG_PM y
+@@ -95,23 +105,42 @@ if [ "$CONFIG_HUGETLB_PAGE" = "y" ]; the
+ if [ "$CONFIG_MCKINLEY" = "y" ]; then
+ choice ' IA-64 Huge TLB Page Size' \
+ "4GB CONFIG_HUGETLB_PAGE_SIZE_4GB \
+- 256MB CONFIG_HUGETLB_PAGE_SIZE_256MB \
+- 64MB CONFIG_HUGETLB_PAGE_SIZE_64MB \
+- 16MB CONFIG_HUGETLB_PAGE_SIZE_16MB \
+- 4MB CONFIG_HUGETLB_PAGE_SIZE_4MB \
+- 1MB CONFIG_HUGETLB_PAGE_SIZE_1MB \
+- 256KB CONFIG_HUGETLB_PAGE_SIZE_256KB" 16MB
++ 256MB CONFIG_HUGETLB_PAGE_SIZE_256MB_1 \
++ 64MB CONFIG_HUGETLB_PAGE_SIZE_64MB_1 \
++ 16MB CONFIG_HUGETLB_PAGE_SIZE_16MB_1 \
++ 4MB CONFIG_HUGETLB_PAGE_SIZE_4MB_1 \
++ 1MB CONFIG_HUGETLB_PAGE_SIZE_1MB_1 \
++ 256KB CONFIG_HUGETLB_PAGE_SIZE_256KB_1" 16MB
+ else
+ choice ' IA-64 Huge TLB Page Size' \
+- "256MB CONFIG_HUGETLB_PAGE_SIZE_256MB \
+- 64MB CONFIG_HUGETLB_PAGE_SIZE_64MB \
+- 16MB CONFIG_HUGETLB_PAGE_SIZE_16MB \
+- 4MB CONFIG_HUGETLB_PAGE_SIZE_4MB \
+- 1MB CONFIG_HUGETLB_PAGE_SIZE_1MB \
+- 256KB CONFIG_HUGETLB_PAGE_SIZE_256KB" 16MB
++ "256MB CONFIG_HUGETLB_PAGE_SIZE_256MB_2 \
++ 64MB CONFIG_HUGETLB_PAGE_SIZE_64MB_2 \
++ 16MB CONFIG_HUGETLB_PAGE_SIZE_16MB_2 \
++ 4MB CONFIG_HUGETLB_PAGE_SIZE_4MB_2 \
++ 1MB CONFIG_HUGETLB_PAGE_SIZE_1MB_2 \
++ 256KB CONFIG_HUGETLB_PAGE_SIZE_256KB_2" 16MB
+ fi
+ fi
+
++if [ "$CONFIG_HUGETLB_PAGE_SIZE_256MB_1" = "y" -o "$CONFIG_HUGETLB_PAGE_SIZE_256MB_2" = "y" ]; then
++ define_bool CONFIG_HUGETLB_PAGE_SIZE_256MB y
++fi
++if [ "$CONFIG_HUGETLB_PAGE_SIZE_64MB_1" = "y" -o "$CONFIG_HUGETLB_PAGE_SIZE_64MB_2" = "y" ]; then
++ define_bool CONFIG_HUGETLB_PAGE_SIZE_64MB y
++fi
++if [ "$CONFIG_HUGETLB_PAGE_SIZE_16MB_1" = "y" -o "$CONFIG_HUGETLB_PAGE_SIZE_16MB_2" = "y" ]; then
++ define_bool CONFIG_HUGETLB_PAGE_SIZE_16MB y
++fi
++if [ "$CONFIG_HUGETLB_PAGE_SIZE_4MB_1" = "y" -o "$CONFIG_HUGETLB_PAGE_SIZE_4MB_2" = "y" ]; then
++ define_bool CONFIG_HUGETLB_PAGE_SIZE_4MB y
++fi
++if [ "$CONFIG_HUGETLB_PAGE_SIZE_1MB_1" = "y" -o "$CONFIG_HUGETLB_PAGE_SIZE_1MB_2" = "y" ]; then
++ define_bool CONFIG_HUGETLB_PAGE_SIZE_1MB y
++fi
++if [ "$CONFIG_HUGETLB_PAGE_SIZE_256KB_1" = "y" -o "$CONFIG_HUGETLB_PAGE_SIZE_256KB_2" = "y" ]; then
++ define_bool CONFIG_HUGETLB_PAGE_SIZE_256KB y
++fi
++
+ bool 'SMP support' CONFIG_SMP
+ bool 'Support running of Linux/x86 binaries' CONFIG_IA32_SUPPORT
+ bool 'Performance monitor support' CONFIG_PERFMON
+@@ -125,7 +154,7 @@ fi
+ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+-if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
++#if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ source drivers/acpi/Config.in
+
+ bool 'PCI support' CONFIG_PCI
+@@ -136,15 +165,15 @@ if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ source drivers/hotplug/Config.in
+ source drivers/pcmcia/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
++ define_tristate CONFIG_PCMCIA n
+ fi
+
+ source drivers/parport/Config.in
+-fi # !HP_SIM
++#fi # !HP_SIM
+
+ endmenu
+
+-if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
++#if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ source drivers/mtd/Config.in
+ source drivers/pnp/Config.in
+ source drivers/block/Config.in
+@@ -164,7 +193,7 @@ if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ define_bool CONFIG_BLK_DEV_HD n
+ fi
+ endmenu
+-fi
++#fi
+
+ mainmenu_option next_comment
+ comment 'SCSI support'
+@@ -180,7 +209,7 @@ if [ "$CONFIG_NET" = "y" ]; then
+ source net/Config.in
+ fi
+
+-if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
++#if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ if [ "$CONFIG_NET" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Network device support'
+@@ -212,7 +241,8 @@ if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ #source drivers/misc/Config.in
+
+ source drivers/media/Config.in
+-else # HP_SIM
++#else # HP_SIM
++if [ "$CONFIG_IA64_HP_SIM" != "n" ]; then
+
+ mainmenu_option next_comment
+ comment 'Block devices'
+@@ -228,7 +258,7 @@ fi # HP_SIM
+
+ source fs/Config.in
+
+-if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
++#if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ if [ "$CONFIG_VT" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Console drivers'
+@@ -252,7 +282,7 @@ if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+ source drivers/usb/Config.in
+ source lib/Config.in
+ source net/bluetooth/Config.in
+-fi # !HP_SIM
++#fi # !HP_SIM
+
+ if [ "$CONFIG_IA64_HP_SIM" != "n" -o "$CONFIG_IA64_GENERIC" != "n" ]; then
+ source arch/ia64/hp/sim/Config.in
+@@ -288,3 +318,4 @@ fi
+ endmenu
+
+ source security/Config.in
++source config.undef
+Index: arch/m68k/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/m68k/config.in,v
+retrieving revision 1.1.1.13
+diff -u -p -r1.1.1.13 config.in
+--- arch/m68k/config.in 12 Oct 2002 11:51:33 -0000 1.1.1.13
++++ arch/m68k/config.in 16 Oct 2002 23:01:03 -0000
+@@ -18,7 +18,7 @@ comment 'Platform dependent setup'
+
+ define_bool CONFIG_EISA n
+ define_bool CONFIG_MCA n
+-define_bool CONFIG_PCMCIA n
++define_tristate CONFIG_PCMCIA n
+
+ bool 'Amiga support' CONFIG_AMIGA
+ bool 'Atari support' CONFIG_ATARI
+@@ -141,9 +141,9 @@ fi
+ source drivers/pci/Config.in
+ source drivers/zorro/Config.in
+
+-if [ "$CONFIG_Q40" = "y" ]; then
++#if [ "$CONFIG_Q40" = "y" ]; then
+ source drivers/pnp/Config.in
+-fi
++#fi
+
+ endmenu
+
+@@ -153,9 +153,9 @@ source drivers/block/Config.in
+
+ source drivers/md/Config.in
+
+-if [ "$CONFIG_MAC" = "y" ]; then
++#if [ "$CONFIG_MAC" = "y" ]; then
+ source drivers/input/Config.in
+-fi
++#fi
+
+ mainmenu_option next_comment
+ comment 'ATA/ATAPI/MFM/RLL device support'
+@@ -504,7 +504,7 @@ if [ "$CONFIG_ATARI" = "y" ]; then
+ bool 'Enhanced Real Time Clock Support' CONFIG_RTC
+ else
+ if [ "$CONFIG_SUN3" = "y" ]; then
+- define_bool CONFIG_GEN_RTC y
++ define_tristate CONFIG_GEN_RTC y
+ else
+ tristate 'Generic /dev/rtc emulation' CONFIG_GEN_RTC
+ fi
+@@ -548,3 +548,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/mips/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/mips/config.in,v
+retrieving revision 1.1.1.13
+diff -u -p -r1.1.1.13 config.in
+--- arch/mips/config.in 12 Oct 2002 11:50:54 -0000 1.1.1.13
++++ arch/mips/config.in 16 Oct 2002 23:01:07 -0000
+@@ -25,7 +25,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; the
+ choice 'Galileo Chip Clock' \
+ "75 CONFIG_SYSCLK_75\
+ 83.3 CONFIG_SYSCLK_83\
+- 100 CONFIG_SYSCLK_100" CONFIG_SYSCLK_83
++ 100 CONFIG_SYSCLK_100_1" CONFIG_SYSCLK_83
+ fi
+ bool 'Support for MIPS Atlas board (EXPERIMENTAL)' CONFIG_MIPS_ATLAS
+ bool 'Support for MIPS Malta board (EXPERIMENTAL)' CONFIG_MIPS_MALTA
+@@ -84,8 +84,12 @@ unset CONFIG_SWAP_IO_SPACE
+ unset CONFIG_VIDEO_G364
+ unset CONFIG_PC_KEYB
+
++define_bool CONFIG_ISA n
++define_bool CONFIG_EISA n
++define_bool CONFIG_PCI n
+ define_bool CONFIG_MCA n
+ define_bool CONFIG_SBUS n
++define_bool CONFIG_I8259 n
+
+ if [ "$CONFIG_MIPS_EV96100" = "y" ]; then
+ define_bool CONFIG_PCI y
+@@ -138,7 +142,7 @@ if [ "$CONFIG_MIPS_MALTA" = "y" ]; then
+ fi
+ if [ "$CONFIG_MOMENCO_OCELOT" = "y" ]; then
+ define_bool CONFIG_PCI y
+- define_bool CONFIG_SYSCLK_100 y
++ define_bool CONFIG_SYSCLK_100_2 y
+ define_bool CONFIG_SWAP_IO_SPACE y
+ define_bool CONFIG_NEW_IRQ y
+ define_bool CONFIG_OLD_TIME_C y
+@@ -201,19 +205,11 @@ if [ "$CONFIG_NINO" = "y" ]; then
+ define_bool CONFIG_PC_KEYB y
+ fi
+
+-if [ "$CONFIG_ISA" != "y" ]; then
+- define_bool CONFIG_ISA n
+- define_bool CONFIG_EISA n
+-else
++if [ "$CONFIG_ISA" = "y" ]; then
+ define_bool CONFIG_EISA y
+ fi
+-
+-if [ "$CONFIG_PCI" != "y" ]; then
+- define_bool CONFIG_PCI n
+-fi
+-
+-if [ "$CONFIG_I8259" != "y" ]; then
+- define_bool CONFIG_I8259 n
++if [ "$CONFIG_SYSCLK_100_1" = "y" -o "$CONFIG_SYSCLK_100_2" = "y" ]; then
++ define_bool CONFIG_SYSCLK_100 y
+ fi
+ endmenu
+
+@@ -302,7 +298,7 @@ bool 'Support for hot-pluggable devices'
+ if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+ source drivers/pcmcia/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
++ define_tristate CONFIG_PCMCIA n
+ fi
+
+ if [ "$CONFIG_DECSTATION" = "y" ]; then
+@@ -313,9 +309,9 @@ if [ "$CONFIG_DECSTATION" = "y" ]; then
+ fi
+ endmenu
+
+-if [ "$CONFIG_ISA" = "y" ]; then
++#if [ "$CONFIG_ISA" = "y" ]; then
+ source drivers/pnp/Config.in
+-fi
++#fi
+
+ source drivers/mtd/Config.in
+
+@@ -351,10 +347,10 @@ if [ "$CONFIG_SCSI" != "n" ]; then
+ fi
+ endmenu
+
+-if [ "$CONFIG_DECSTATION" != "y" -a \
+- "$CONFIG_SGI_IP22" != "y" ]; then
++#if [ "$CONFIG_DECSTATION" != "y" -a \
++# "$CONFIG_SGI_IP22" != "y" ]; then
+ source drivers/message/i2o/Config.in
+-fi
++#fi
+
+ if [ "$CONFIG_NET" = "y" ]; then
+ source net/Config.in
+@@ -418,7 +414,7 @@ if [ "$CONFIG_DECSTATION" = "y" ]; then
+ # if [ "$CONFIG_ACCESSBUS" = "y" ]; then
+ # bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE
+ # fi
+- bool 'Enhanced Real Time Clock Support' CONFIG_RTC
++ tristate 'Enhanced Real Time Clock Support' CONFIG_RTC
+
+ endmenu
+ fi
+@@ -453,10 +449,10 @@ if [ "$CONFIG_VT" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Console drivers'
+ bool 'VGA text console' CONFIG_VGA_CONSOLE
+- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++ #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
+ source drivers/video/Config.in
+- fi
++ #fi
+ endmenu
+ fi
+
+@@ -498,3 +494,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/mips64/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/mips64/config.in,v
+retrieving revision 1.1.1.12
+diff -u -p -r1.1.1.12 config.in
+--- arch/mips64/config.in 12 Oct 2002 11:52:33 -0000 1.1.1.12
++++ arch/mips64/config.in 16 Oct 2002 23:01:09 -0000
+@@ -24,10 +24,6 @@ if [ "$CONFIG_SGI_IP27" = "y" ]; then
+ fi
+ endmenu
+
+-define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+-define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+-define_bool CONFIG_GENERIC_ISA_DMA y
+-
+ #
+ # Select some configuration options automatically based on user selections
+ #
+@@ -42,6 +38,13 @@ unset CONFIG_ISA
+ unset CONFIG_MAPPED_PCI_IO
+ unset CONFIG_PCI
+
++define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
++define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
++define_bool CONFIG_GENERIC_ISA_DMA y
++define_bool CONFIG_PCI n
++define_bool CONFIG_ISA n
++define_bool CONFIG_EISA n
++
+ if [ "$CONFIG_SGI_IP22" = "y" ]; then
+ define_bool CONFIG_BOOT_ELF32 y
+ define_bool CONFIG_ARC32 y
+@@ -61,17 +64,10 @@ if [ "$CONFIG_SGI_IP27" = "y" ]; then
+ define_int CONFIG_L1_CACHE_SHIFT 7
+ fi
+
+-if [ "$CONFIG_ISA" != "y" ]; then
+- define_bool CONFIG_ISA n
+- define_bool CONFIG_EISA n
+-else
++if [ "$CONFIG_ISA" = "y" ]; then
+ define_bool CONFIG_EISA y
+ fi
+
+-if [ "$CONFIG_PCI" != "y" ]; then
+- define_bool CONFIG_PCI n
+-fi
+-
+ define_bool CONFIG_MCA n
+ define_bool CONFIG_SBUS n
+
+@@ -99,14 +95,12 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; the
+ bool 'Kernel floating-point emulation' CONFIG_MIPS_FPU_EMULATOR
+ fi
+
+-source drivers/pci/Config.in
+-
+ bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+
+ if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+ source drivers/pcmcia/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
++ define_tristate CONFIG_PCMCIA n
+ fi
+
+ if [ "$CONFIG_ARC32" = "y" ]; then
+@@ -252,3 +246,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/parisc/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/parisc/config.in,v
+retrieving revision 1.1.1.10
+diff -u -p -r1.1.1.10 config.in
+--- arch/parisc/config.in 12 Oct 2002 11:52:43 -0000 1.1.1.10
++++ arch/parisc/config.in 16 Oct 2002 23:01:10 -0000
+@@ -196,3 +196,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/ppc/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/ppc/config.in,v
+retrieving revision 1.1.1.21
+diff -u -p -r1.1.1.21 config.in
+--- arch/ppc/config.in 12 Oct 2002 11:51:09 -0000 1.1.1.21
++++ arch/ppc/config.in 16 Oct 2002 23:01:12 -0000
+@@ -55,7 +55,7 @@ if [ "$CONFIG_8260" = "y" ]; then
+ SBS8260 CONFIG_SBS8260 \
+ RPXSUPER CONFIG_RPX6 \
+ TQM8260 CONFIG_TQM8260 \
+- Willow CONFIG_WILLOW" Willow
++ Willow CONFIG_WILLOW_1" Willow
+ fi
+
+ if [ "$CONFIG_40x" = "y" ]; then
+@@ -114,9 +114,9 @@ fi
+
+ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then
+ choice 'Machine Type' \
+- "CHRP/PowerMac/PReP CONFIG_ALL_PPC \
++ "CHRP/PowerMac/PReP CONFIG_ALL_PPC_CH \
+ Amiga-APUS CONFIG_APUS \
+- Cogent-Willow CONFIG_WILLOW \
++ Cogent-Willow CONFIG_WILLOW_2 \
+ Force-PowerCore CONFIG_PCORE \
+ Force-PowerPMC250 CONFIG_POWERPMC250 \
+ Galileo-EV-64260-BP CONFIG_EV64260 \
+@@ -145,6 +145,14 @@ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_826
+ fi
+ fi
+
++if [ "$CONFIG_POWER3" = "y" -o "$CONFIG_ALL_PPC_CH" = "y" ]; then
++ define_bool CONFIG_ALL_PPC y
++fi
++
++if [ "$CONFIG_WILLOW_1" = "y" -o "$CONFIG_WILLOW_2" = "y" ]; then
++ define_bool CONFIG_WILLOW y
++fi
++
+ if [ "$CONFIG_FORCE" = "y" -o "$CONFIG_MENF1" = "y" \
+ -o "$CONFIG_SANDPOINT" = "y" -o "$CONFIG_ZX4500" = "y" ]; then
+ bool 'Enable MPC10x store gathering' CONFIG_MPC10X_STORE_GATHERING
+@@ -314,7 +322,7 @@ bool 'Support for hot-pluggable devices'
+ if [ "$CONFIG_HOTPLUG" = "y" ]; then
+ source drivers/pcmcia/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
++ define_tristate CONFIG_PCMCIA n
+ fi
+
+ source drivers/parport/Config.in
+@@ -488,7 +496,7 @@ if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
+ fi
+ if [ "$CONFIG_VIOCD" = "y" ]; then
+ define_bool CONFIG_CD_NO_IDESCSI y
+- define_bool CONFIG_BLK_DEV_IDECD y
++ define_tristate CONFIG_BLK_DEV_IDECD y
+ fi
+ endmenu
+ else
+@@ -617,3 +625,4 @@ endmenu
+
+ source security/Config.in
+
++source config.undef
+Index: arch/ppc64/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/ppc64/config.in,v
+retrieving revision 1.1.1.12
+diff -u -p -r1.1.1.12 config.in
+--- arch/ppc64/config.in 12 Oct 2002 11:52:54 -0000 1.1.1.12
++++ arch/ppc64/config.in 16 Oct 2002 23:01:13 -0000
+@@ -68,8 +68,8 @@ if [ "$CONFIG_HOTPLUG" = "y" ]; then
+ source drivers/pcmcia/Config.in
+ source drivers/hotplug/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
+- define_bool CONFIG_HOTPLUG_PCI n
++ define_tristate CONFIG_PCMCIA n
++ define_tristate CONFIG_HOTPLUG_PCI n
+ fi
+
+ if [ "$CONFIG_PPC_ISERIES" != "y" ]; then
+@@ -207,3 +207,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/s390/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/s390/config.in,v
+retrieving revision 1.1.1.7
+diff -u -p -r1.1.1.7 config.in
+--- arch/s390/config.in 12 Oct 2002 11:52:41 -0000 1.1.1.7
++++ arch/s390/config.in 16 Oct 2002 23:01:15 -0000
+@@ -77,3 +77,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/s390x/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/s390x/config.in,v
+retrieving revision 1.1.1.7
+diff -u -p -r1.1.1.7 config.in
+--- arch/s390x/config.in 12 Oct 2002 11:52:52 -0000 1.1.1.7
++++ arch/s390x/config.in 16 Oct 2002 23:01:15 -0000
+@@ -81,3 +81,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/sh/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/sh/config.in,v
+retrieving revision 1.1.1.10
+diff -u -p -r1.1.1.10 config.in
+--- arch/sh/config.in 27 Aug 2002 23:43:48 -0000 1.1.1.10
++++ arch/sh/config.in 16 Oct 2002 23:01:15 -0000
+@@ -186,7 +186,7 @@ bool 'Support for hot-pluggable devices'
+ if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+ source drivers/pcmcia/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
++ define_tristate CONFIG_PCMCIA n
+ fi
+
+ if [ "$CONFIG_PROC_FS" = "y" ]; then
+@@ -261,9 +261,9 @@ endmenu
+ #
+ source drivers/input/Config.in
+
+-if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
+- source drivers/maple/Config.in
+-fi
++#if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
++# source drivers/maple/Config.in
++#fi
+
+ mainmenu_option next_comment
+ comment 'Character devices'
+@@ -306,7 +306,7 @@ if [ "$CONFIG_SH_DREAMCAST" = "y" -a "$C
+ endmenu
+ fi
+
+-source drivers/char/joystick/Config.in
++#source drivers/char/joystick/Config.in
+
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+@@ -341,10 +341,10 @@ if [ "$CONFIG_VT" = "y" ]; then
+ comment 'Console drivers'
+ bool 'VGA text console' CONFIG_VGA_CONSOLE
+ bool 'Video mode selection support' CONFIG_VIDEO_SELECT
+- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++ #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
+ source drivers/video/Config.in
+- fi
++ #fi
+ endmenu
+ fi
+
+@@ -370,3 +370,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/sparc/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/sparc/config.in,v
+retrieving revision 1.1.1.15
+diff -u -p -r1.1.1.15 config.in
+--- arch/sparc/config.in 12 Oct 2002 11:50:47 -0000 1.1.1.15
++++ arch/sparc/config.in 16 Oct 2002 23:01:16 -0000
+@@ -30,7 +30,7 @@ define_bool CONFIG_SPARC32 y
+ define_bool CONFIG_ISA n
+ define_bool CONFIG_EISA n
+ define_bool CONFIG_MCA n
+-define_bool CONFIG_PCMCIA n
++define_tristate CONFIG_PCMCIA n
+ define_bool CONFIG_SBUS y
+ define_bool CONFIG_SBUSCHAR y
+ define_bool CONFIG_SERIAL_CONSOLE y
+@@ -41,10 +41,11 @@ define_bool CONFIG_RWSEM_XCHGADD_ALGORIT
+ define_bool CONFIG_SUN_PM y
+
+ bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
+-if [ "$CONFIG_SUN4" != "y" ]; then
++#if [ "$CONFIG_SUN4" != "y" ]; then
+ bool 'Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
+ source drivers/pci/Config.in
+-else
++#else
++if [ "$CONFIG_SUN4" = "y" ]; then
+ define_bool CONFIG_PCI n
+ fi
+
+@@ -72,9 +73,9 @@ endmenu
+ source drivers/mtd/Config.in
+
+ source drivers/serial/Config.in
+-if [ "$CONFIG_SUN4" != "y" ]; then
++#if [ "$CONFIG_SUN4" != "y" ]; then
+ source drivers/sbus/char/Config.in
+-fi
++#fi
+
+ mainmenu_option next_comment
+ comment 'Block devices'
+@@ -95,7 +96,7 @@ dep_bool ' Initial RAM disk (initrd) su
+ endmenu
+
+ # Don't frighten a common SBus user
+-if [ "$CONFIG_PCI" = "y" ]; then
++#if [ "$CONFIG_PCI" = "y" ]; then
+
+ mainmenu_option next_comment
+ comment 'ATA/ATAPI/MFM/RLL support'
+@@ -108,8 +109,9 @@ if [ "$CONFIG_PCI" = "y" ]; then
+ define_bool CONFIG_BLK_DEV_HD n
+ fi
+ endmenu
+-else
+- define_bool CONFIG_IDE n
++#else
++if [ "$CONFIG_PCI" != "y" ]; then
++ define_tristate CONFIG_IDE n
+ define_bool CONFIG_BLK_DEV_HD n
+ fi
+
+@@ -226,6 +228,9 @@ source drivers/input/Config.in
+
+ source fs/Config.in
+
++mainmenu_option next_comment
++comment 'Sound'
++
+ tristate 'Sound card support' CONFIG_SOUND
+ if [ "$CONFIG_SOUND" != "n" ]; then
+ source sound/Config.in
+@@ -253,3 +258,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/sparc64/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/sparc64/config.in,v
+retrieving revision 1.1.1.15
+diff -u -p -r1.1.1.15 config.in
+--- arch/sparc64/config.in 12 Oct 2002 11:51:46 -0000 1.1.1.15
++++ arch/sparc64/config.in 16 Oct 2002 23:01:17 -0000
+@@ -35,17 +35,17 @@ define_bool CONFIG_RWSEM_GENERIC_SPINLOC
+ define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
+ define_bool CONFIG_GENERIC_ISA_DMA y
+ define_bool CONFIG_ISA n
+-define_bool CONFIG_ISAPNP n
++define_bool CONFIG_ISAPNP n
+ define_bool CONFIG_EISA n
+ define_bool CONFIG_MCA n
+-define_bool CONFIG_PCMCIA n
++define_tristate CONFIG_PCMCIA n
+ define_bool CONFIG_SBUS y
+ define_bool CONFIG_SBUSCHAR y
+ define_bool CONFIG_SUN_AUXIO y
+ define_bool CONFIG_SUN_IO y
+ bool 'PCI support' CONFIG_PCI
+ if [ "$CONFIG_PCI" = "y" ] ; then
+- define_bool CONFIG_RTC y
++ define_tristate CONFIG_RTC y
+ fi
+ source drivers/pci/Config.in
+
+@@ -153,8 +153,9 @@ if [ "$CONFIG_SCSI" != "n" ]; then
+ dep_tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+ dep_tristate 'PTI Qlogic, ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
+
+- if [ "$CONFIG_PCI" != "n" ]; then
++ #if [ "$CONFIG_PCI" != "n" ]; then
+ source drivers/scsi/aic7xxx/Config.in
++ if [ "$CONFIG_PCI" != "n" ]; then
+ if [ "$CONFIG_SCSI_AIC7XXX" != "y" ]; then
+ dep_tristate 'Old Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX_OLD $CONFIG_SCSI
+ if [ "$CONFIG_SCSI_AIC7XXX_OLD" != "n" ]; then
+@@ -202,9 +203,9 @@ endmenu
+
+ source drivers/fc4/Config.in
+
+-if [ "$CONFIG_PCI" = "y" ]; then
++#if [ "$CONFIG_PCI" = "y" ]; then
+ source drivers/message/fusion/Config.in
+-fi
++#fi
+
+ source drivers/ieee1394/Config.in
+
+@@ -296,3 +297,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: arch/um/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/um/config.in,v
+retrieving revision 1.1.1.3
+diff -u -p -r1.1.1.3 config.in
+--- arch/um/config.in 16 Oct 2002 19:46:03 -0000 1.1.1.3
++++ arch/um/config.in 16 Oct 2002 23:01:18 -0000
+@@ -91,3 +91,4 @@ fi
+ dep_bool 'Enable gprof support' CONFIG_GPROF $CONFIG_DEBUGSYM
+ dep_bool 'Enable gcov support' CONFIG_GCOV $CONFIG_DEBUGSYM
+ endmenu
++source config.undef
+Index: arch/x86_64/config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/arch/x86_64/config.in,v
+retrieving revision 1.1.1.11
+diff -u -p -r1.1.1.11 config.in
+--- arch/x86_64/config.in 12 Oct 2002 11:53:03 -0000 1.1.1.11
++++ arch/x86_64/config.in 16 Oct 2002 23:01:20 -0000
+@@ -90,7 +90,7 @@ if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+ source drivers/pcmcia/Config.in
+ source drivers/hotplug/Config.in
+ else
+- define_bool CONFIG_PCMCIA n
++ define_tristate CONFIG_PCMCIA n
+ fi
+
+ endmenu
+@@ -193,10 +193,10 @@ if [ "$CONFIG_VT" = "y" ]; then
+ comment 'Console drivers'
+ bool 'VGA text console' CONFIG_VGA_CONSOLE
+ bool 'Video mode selection support' CONFIG_VIDEO_SELECT
+- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++ #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
+ source drivers/video/Config.in
+- fi
++ #fi
+ endmenu
+ fi
+
+@@ -229,3 +229,4 @@ endmenu
+
+ source security/Config.in
+ source lib/Config.in
++source config.undef
+Index: drivers/acpi/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/acpi/Config.in,v
+retrieving revision 1.1.1.10
+diff -u -p -r1.1.1.10 Config.in
+--- drivers/acpi/Config.in 27 Sep 2002 22:31:52 -0000 1.1.1.10
++++ drivers/acpi/Config.in 16 Oct 2002 23:01:21 -0000
+@@ -51,10 +51,10 @@ if [ "$CONFIG_IA64" = "y" ]; then
+ define_bool CONFIG_ACPI_POWER n
+ define_bool CONFIG_ACPI_SYSTEM n
+ define_bool CONFIG_ACPI_SLEEP n
+- define_bool CONFIG_ACPI_BUTTON n
+- define_bool CONFIG_ACPI_FAN n
+- define_bool CONFIG_ACPI_PROCESSOR n
+- define_bool CONFIG_ACPI_THERMAL n
++ define_tristate CONFIG_ACPI_BUTTON n
++ define_tristate CONFIG_ACPI_FAN n
++ define_tristate CONFIG_ACPI_PROCESSOR n
++ define_tristate CONFIG_ACPI_THERMAL n
+ define_bool CONFIG_ACPI_NUMA y
+ fi
+
+Index: drivers/char/agp/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/char/agp/Config.in,v
+retrieving revision 1.1.1.2
+diff -u -p -r1.1.1.2 Config.in
+--- drivers/char/agp/Config.in 27 Sep 2002 22:30:24 -0000 1.1.1.2
++++ drivers/char/agp/Config.in 16 Oct 2002 23:01:24 -0000
+@@ -1,8 +1,9 @@
+
+-if [ "$CONFIG_GART_IOMMU" = "y" ]; then
+- dep_bool '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP
++if [ "$CONFIG_GART_IOMMU" != "y" ]; then
++ tristate '/dev/agpgart (AGP Support)' CONFIG_AGP
+ else
+- dep_tristate '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP
++ bool '/dev/agpgart (AGP Support)' CONFIG_AGP_GART
++ define_tristate CONFIG_AGP $CONFIG_AGP_GART
+ fi
+ if [ "$CONFIG_AGP" != "n" ]; then
+ bool ' Intel 440LX/BX/GX and I815/I820/I830M/I830MP/I840/I845/I850/I860 support' CONFIG_AGP_INTEL
+Index: drivers/message/fusion/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/message/fusion/Config.in,v
+retrieving revision 1.1.1.4
+diff -u -p -r1.1.1.4 Config.in
+--- drivers/message/fusion/Config.in 16 Oct 2002 19:44:14 -0000 1.1.1.4
++++ drivers/message/fusion/Config.in 16 Oct 2002 23:01:29 -0000
+@@ -18,10 +18,10 @@ if [ "$CONFIG_FUSION" = "y" -o "$CONFIG_
+ dep_tristate " Fusion MPT misc device (ioctl) driver" CONFIG_FUSION_CTL $CONFIG_FUSION m
+ fi
+
+- dep_tristate " Fusion MPT LAN driver" CONFIG_FUSION_LAN $CONFIG_FUSION $CONFIG_NET
+- if [ "$CONFIG_FUSION_LAN" != "n" ]; then
+- define_bool CONFIG_NET_FC y
+- fi
++ dep_tristate " Fusion MPT LAN driver" CONFIG_FUSION_LAN $CONFIG_FUSION $CONFIG_NET $CONFIG_NET_FC
++# if [ "$CONFIG_FUSION_LAN" != "n" ]; then
++# define_bool CONFIG_NET_FC y
++# fi
+
+ else
+
+@@ -29,9 +29,9 @@ else
+ # These <should> be define_tristate, but we leave them define_bool
+ # for backward compatibility with pre-linux-2.2.15 kernels.
+ # (Bugzilla:fibrebugs, #384)
+- define_bool CONFIG_FUSION_ISENSE n
+- define_bool CONFIG_FUSION_CTL n
+- define_bool CONFIG_FUSION_LAN n
++ define_tristate CONFIG_FUSION_ISENSE n
++ define_tristate CONFIG_FUSION_CTL n
++ define_tristate CONFIG_FUSION_LAN n
+
+ fi
+
+Index: drivers/mtd/chips/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/mtd/chips/Config.in,v
+retrieving revision 1.1.1.1
+diff -u -p -r1.1.1.1 Config.in
+--- drivers/mtd/chips/Config.in 26 Nov 2001 19:31:18 -0000 1.1.1.1
++++ drivers/mtd/chips/Config.in 16 Oct 2002 23:01:30 -0000
+@@ -11,12 +11,12 @@ dep_tristate ' Detect flash chips by Co
+ dep_tristate ' Detect non-CFI AMD/JEDEC-compatible flash chips' CONFIG_MTD_JEDECPROBE $CONFIG_MTD
+
+ if [ "$CONFIG_MTD_CFI" = "y" -o "$CONFIG_MTD_INTELPROBE" = "y" -o "$CONFIG_MTD_JEDECPROBE" = "y" ]; then
+- define_bool CONFIG_MTD_GEN_PROBE y
++ define_tristate CONFIG_MTD_GEN_PROBE y
+ else
+ if [ "$CONFIG_MTD_CFI" = "m" -o "$CONFIG_MTD_INTELPROBE" = "m" -o "$CONFIG_MTD_JEDECPROBE" = "m" ]; then
+- define_bool CONFIG_MTD_GEN_PROBE m
++ define_tristate CONFIG_MTD_GEN_PROBE m
+ else
+- define_bool CONFIG_MTD_GEN_PROBE n
++ define_tristate CONFIG_MTD_GEN_PROBE n
+ fi
+ fi
+ if [ "$CONFIG_MTD_GEN_PROBE" = "y" -o "$CONFIG_MTD_GEN_PROBE" = "m" ]; then
+Index: drivers/mtd/devices/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/mtd/devices/Config.in,v
+retrieving revision 1.1.1.1
+diff -u -p -r1.1.1.1 Config.in
+--- drivers/mtd/devices/Config.in 26 Nov 2001 19:31:18 -0000 1.1.1.1
++++ drivers/mtd/devices/Config.in 16 Oct 2002 23:01:30 -0000
+@@ -29,12 +29,12 @@ comment 'Disk-On-Chip Device Drivers'
+ dep_tristate ' M-Systems Disk-On-Chip 2000 and Millennium' CONFIG_MTD_DOC2000 $CONFIG_MTD
+ dep_tristate ' M-Systems Disk-On-Chip Millennium-only alternative driver (see help)' CONFIG_MTD_DOC2001 $CONFIG_MTD
+ if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then
+- define_bool CONFIG_MTD_DOCPROBE y
++ define_tristate CONFIG_MTD_DOCPROBE y
+ else
+ if [ "$CONFIG_MTD_DOC2001" = "m" -o "$CONFIG_MTD_DOC2000" = "m" ]; then
+- define_bool CONFIG_MTD_DOCPROBE m
++ define_tristate CONFIG_MTD_DOCPROBE m
+ else
+- define_bool CONFIG_MTD_DOCPROBE n
++ define_tristate CONFIG_MTD_DOCPROBE n
+ fi
+ fi
+
+Index: drivers/net/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/net/Config.in,v
+retrieving revision 1.1.1.13
+diff -u -p -r1.1.1.13 Config.in
+--- drivers/net/Config.in 7 Oct 2002 19:16:13 -0000 1.1.1.13
++++ drivers/net/Config.in 16 Oct 2002 23:01:30 -0000
+@@ -305,6 +305,8 @@ if [ "$CONFIG_NET_RADIO" = "y" ]; then
+
+ # New directory for Wireless LAN devices - cards above will move there
+ source drivers/net/wireless/Config.in
++else
++ define_tristate CONFIG_AIRONET4500 n
+ fi
+
+ endmenu
+Index: drivers/parport/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/parport/Config.in,v
+retrieving revision 1.1.1.2
+diff -u -p -r1.1.1.2 Config.in
+--- drivers/parport/Config.in 31 Jan 2002 22:18:24 -0000 1.1.1.2
++++ drivers/parport/Config.in 16 Oct 2002 23:01:33 -0000
+@@ -11,8 +11,8 @@ comment 'Parallel port support'
+ tristate 'Parallel port support' CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+- if [ "$CONFIG_PARPORT_PC" != "n" -a "$CONFIG_SERIAL" != "n" ]; then
+- if [ "$CONFIG_SERIAL" = "m" ]; then
++ if [ "$CONFIG_PARPORT_PC" != "n" -a "$CONFIG_SERIAL_8250" != "n" ]; then
++ if [ "$CONFIG_SERIAL_8250" = "m" ]; then
+ define_tristate CONFIG_PARPORT_PC_CML1 m
+ else
+ define_tristate CONFIG_PARPORT_PC_CML1 $CONFIG_PARPORT_PC
+Index: drivers/pnp/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/pnp/Config.in,v
+retrieving revision 1.1.1.3
+diff -u -p -r1.1.1.3 Config.in
+--- drivers/pnp/Config.in 19 Oct 2002 11:36:15 -0000 1.1.1.3
++++ drivers/pnp/Config.in 19 Oct 2002 13:00:10 -0000
+@@ -4,15 +4,17 @@
+ mainmenu_option next_comment
+ comment 'Plug and Play configuration'
+
+-dep_bool 'Plug and Play support' CONFIG_PNP
++bool 'Plug and Play support' CONFIG_PNP
+
+- dep_bool ' Plug and Play device name database' CONFIG_PNP_NAMES $CONFIG_PNP
+- dep_bool ' PnP Debug Messages' CONFIG_PNP_DEBUG $CONFIG_PNP
++if [ "$CONFIG_PNP" = "y" ]; then
++ bool ' Plug and Play device name database' CONFIG_PNP_NAMES
++ bool ' PnP Debug Messages' CONFIG_PNP_DEBUG
+
+-comment 'Protocols' $CONFIG_PNP
++ comment 'Protocols'
+
+-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+- dep_bool ' ISA Plug and Play support (EXPERIMENTAL)' CONFIG_ISAPNP $CONFIG_PNP
+- dep_bool ' Plug and Play BIOS support (EXPERIMENTAL)' CONFIG_PNPBIOS $CONFIG_PNP
++ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
++ bool ' ISA Plug and Play support (EXPERIMENTAL)' CONFIG_ISAPNP
++ bool ' Plug and Play BIOS support (EXPERIMENTAL)' CONFIG_PNPBIOS
++ fi
+ fi
+ endmenu
+Index: drivers/serial/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/serial/Config.in,v
+retrieving revision 1.1.1.4
+diff -u -p -r1.1.1.4 Config.in
+--- drivers/serial/Config.in 16 Oct 2002 19:42:48 -0000 1.1.1.4
++++ drivers/serial/Config.in 16 Oct 2002 23:01:36 -0000
+@@ -62,14 +62,14 @@ if [ "$CONFIG_SERIAL_AMBA" = "y" -o "$
+ "$CONFIG_SERIAL_ANAKIN" = "y" -o "$CONFIG_SERIAL_UART00" = "y" -o \
+ "$CONFIG_SERIAL_8250" = "y" -o "$CONFIG_SERIAL_ROCKETPORT" = "y" -o \
+ "$CONFIG_SERIAL_SUNCORE" = "y" ]; then
+- define_bool CONFIG_SERIAL_CORE y
++ define_tristate CONFIG_SERIAL_CORE y
+ else
+ if [ "$CONFIG_SERIAL_AMBA" = "m" -o "$CONFIG_SERIAL_CLPS711X" = "m" -o \
+ "$CONFIG_SERIAL_21285" = "m" -o "$CONFIG_SERIAL_SA1100" = "m" -o \
+ "$CONFIG_SERIAL_ANAKIN" = "m" -o "$CONFIG_SERIAL_UART00" = "m" -o \
+ "$CONFIG_SERIAL_8250" = "m" -o "$CONFIG_SERIAL_ROCKETPORT" = "m" -o \
+ "$CONFIG_SERIAL_SUNCORE" = "m" ]; then
+- define_bool CONFIG_SERIAL_CORE m
++ define_tristate CONFIG_SERIAL_CORE m
+ fi
+ fi
+ if [ "$CONFIG_SERIAL_AMBA_CONSOLE" = "y" -o \
+Index: drivers/usb/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/drivers/usb/Config.in,v
+retrieving revision 1.1.1.11
+diff -u -p -r1.1.1.11 Config.in
+--- drivers/usb/Config.in 27 Aug 2002 23:41:47 -0000 1.1.1.11
++++ drivers/usb/Config.in 16 Oct 2002 23:01:36 -0000
+@@ -8,7 +8,7 @@ comment 'USB support'
+ if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" ]; then
+ tristate 'Support for USB' CONFIG_USB
+ else
+- define_bool CONFIG_USB n
++ define_tristate CONFIG_USB n
+ fi
+
+ if [ "$CONFIG_USB" = "y" -o "$CONFIG_USB" = "m" ]; then
+Index: fs/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/fs/Config.in,v
+retrieving revision 1.1.1.18
+diff -u -p -r1.1.1.18 Config.in
+--- fs/Config.in 16 Oct 2002 19:38:54 -0000 1.1.1.18
++++ fs/Config.in 16 Oct 2002 23:01:39 -0000
+@@ -173,7 +173,7 @@ if [ "$CONFIG_NET" = "y" ]; then
+ else
+ # for fs/nls/Config.in
+ define_bool CONFIG_NCPFS_NLS n
+- define_bool CONFIG_SMB_FS n
++ define_tristate CONFIG_SMB_FS n
+ fi
+
+ if [ "$CONFIG_ZISOFS" = "y" ]; then
+Index: scripts/Makefile
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/scripts/Makefile,v
+retrieving revision 1.1.1.7
+diff -u -p -r1.1.1.7 Makefile
+--- scripts/Makefile 7 Oct 2002 19:20:55 -0000 1.1.1.7
++++ scripts/Makefile 16 Oct 2002 23:02:01 -0000
+@@ -11,7 +11,7 @@
+
+ EXTRA_TARGETS := fixdep split-include docproc conmakehash
+
+-subdir- := lxdialog
++subdir- := lxdialog kconfig
+
+ # Yikes. We need to build this stuff here even if the user only wants
+ # modules.
+Index: sound/oss/Config.in
+===================================================================
+RCS file: /usr/src/cvsroot/linux-2.5/sound/oss/Config.in,v
+retrieving revision 1.1.1.4
+diff -u -p -r1.1.1.4 Config.in
+--- sound/oss/Config.in 27 Aug 2002 23:44:49 -0000 1.1.1.4
++++ sound/oss/Config.in 16 Oct 2002 23:02:04 -0000
+@@ -201,12 +201,3 @@ fi
+
+ dep_tristate ' TV card (bt848) mixer support' CONFIG_SOUND_TVMIXER $CONFIG_SOUND $CONFIG_I2C
+
+-# A cross directory dependence. The sound modules will need gameport.o compiled in,
+-# but it resides in the drivers/char/joystick directory. This define_tristate takes
+-# care of that. --Vojtech
+-
+-if [ "$CONFIG_INPUT_GAMEPORT" != "n" ]; then
+- if [ "$CONFIG_SOUND_ESSSOLO1" = "y" -o "$CONFIG_SOUND_ES1370" = "y" -o "$CONFIG_SOUND_ES1371" = "y" -o "$CONFIG_SOUND_SONICVIBES" = "y" ]; then
+- define_tristate CONFIG_INPUT_GAMEPORT y
+- fi
+-fi
+diff -ur config.undef config.undef
+--- config.undef 1970-01-01 01:00:00.000000000 +0100
++++ config.undef 2002-08-22 20:17:58.000000000 +0200
+@@ -0,0 +1,210 @@
++mainmenu_option next_comment
++comment ''
++define_bool CONFIG_IBM_OCP n
++define_bool CONFIG_VISWS n
++define_bool CONFIG_HUB6 n
++define_bool CONFIG_ALL_PPC n
++define_bool CONFIG_ALPHA_BOOK1 n
++define_bool CONFIG_8xx n
++define_bool CONFIG_SUN3 n
++define_bool CONFIG_ARCH_EBSA110 n
++define_bool CONFIG_HP300 n
++define_bool CONFIG_ARCH_NETWINDER n
++define_bool CONFIG_ARCH_ANAKIN n
++define_bool CONFIG_SERIAL_CONSOLE n
++define_bool CONFIG_MIPS_GT96100 n
++define_bool CONFIG_MOMENCO_OCELOT n
++define_bool CONFIG_IA64_HP_SIM n
++define_bool CONFIG_IA64_SGI_SN n
++define_bool CONFIG_MIPS n
++define_bool CONFIG_ARCH_A5K n
++define_bool CONFIG_SGI_IP22 n
++define_bool CONFIG_SGI_IP27 n
++define_bool CONFIG_SERIAL_MANY_PORTS n
++define_bool CONFIG_MIPS_ITE8172 n
++define_bool CONFIG_ARCH_CDB89712 n
++define_bool CONFIG_ARCH_ARC n
++define_bool CONFIG_PPC_ISERIES n
++define_bool CONFIG_SA1100_CERF_CPLD n
++define_bool CONFIG_SA1111 n
++define_bool CONFIG_PPC_PSERIES n
++define_bool CONFIG_AMIGA n
++define_bool CONFIG_ARCH_FOOTBRIDGE n
++define_bool CONFIG_GSC_LASI n
++define_bool CONFIG_ALPHA n
++define_bool CONFIG_TQM8xxL n
++define_bool CONFIG_IA64_SGI_SN1 n
++define_bool CONFIG_ARCH_S390 n
++define_bool CONFIG_IT8712 n
++define_bool CONFIG_SERIAL_EXTENDED n
++define_bool CONFIG_ATARI n
++define_bool CONFIG_ARCH_CLPS7500 n
++define_bool CONFIG_SPARC n
++define_bool CONFIG_ARCH_INTEGRATOR n
++define_bool CONFIG_SUN3X n
++define_bool CONFIG_ARCH_CAMELOT n
++define_bool CONFIG_MIPS_IVR n
++define_bool CONFIG_SH_DREAMCAST n
++define_bool CONFIG_X86_64 n
++define_bool CONFIG_HD64461 n
++define_bool CONFIG_HD64465 n
++define_bool CONFIG_TC n
++define_bool CONFIG_ZORRO n
++define_bool CONFIG_ARCH_CLPS711X n
++define_bool CONFIG_DDB5477 n
++define_bool CONFIG_Q40 n
++define_bool CONFIG_ARCH_P720T n
++define_bool CONFIG_DEBUG_BUGVERBOSE n
++define_bool CONFIG_PARISC n
++define_bool CONFIG_APOLLO n
++define_bool CONFIG_FB_G364 n
++define_bool CONFIG_MAC n
++define_bool CONFIG_ARCH_SA1100 n
++define_bool CONFIG_SA1100_CERF n
++define_bool CONFIG_MIPS_JAZZ n
++define_bool CONFIG_SUPERH n
++define_bool CONFIG_SERIAL_SHARE_IRQ n
++define_bool CONFIG_ARCH_EP7211 n
++define_bool CONFIG_SPARC32 n
++define_bool CONFIG_ARM n
++define_bool CONFIG_SGI n
++define_bool CONFIG_PPC n
++define_bool CONFIG_SPARC64 n
++define_bool CONFIG_FOOTBRIDGE n
++define_bool CONFIG_SA1100_LART n
++define_bool CONFIG_DECSTATION n
++define_bool CONFIG_SERIAL_MULTIPORT n
++define_bool CONFIG_MIPS_AU1000 n
++define_bool CONFIG_ARCH_ACORN n
++define_bool CONFIG_IA64 n
++define_bool CONFIG_BAGET_MIPS n
++define_bool CONFIG_IA32_EMULATION n
++define_bool CONFIG_RPXCLASSIC n
++define_bool CONFIG_ARCH_IQ80310 n
++define_bool CONFIG_RPXLITE n
++define_bool CONFIG_NINO n
++define_bool CONFIG_PPC64 n
++define_bool CONFIG_APUS n
++define_bool CONFIG_ARCH_FTVPCI n
++define_bool CONFIG_ARCH_NEXUSPCI n
++define_bool CONFIG_ARCH_S390X n
++define_bool CONFIG_ARCH_TBOX n
++define_bool CONFIG_CARDBUS n
++define_bool CONFIG_CD_NO_IDESCSI n
++define_bool CONFIG_CPU_DISABLE_DCACHE n
++define_bool CONFIG_DEBUG_IOVIRT n
++define_bool CONFIG_EISA n
++define_bool CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST n
++define_bool CONFIG_FDDI n
++define_bool CONFIG_GG2 n
++define_bool CONFIG_GSC_PS2 n
++define_bool CONFIG_HOTPLUG n
++define_bool CONFIG_IODC_CONSOLE n
++define_bool CONFIG_ISA n
++define_bool CONFIG_IT8172_SCR0 n
++define_bool CONFIG_IT8172_SCR1 n
++define_bool CONFIG_JULIETTE n
++define_bool CONFIG_MCA n
++define_bool CONFIG_MOUSE n
++define_bool CONFIG_NETLINK n
++define_bool CONFIG_NO_PGT_CACHE n
++define_bool CONFIG_NUMA n
++define_bool CONFIG_PCI n
++define_bool CONFIG_PLD_HOTSWAP n
++define_bool CONFIG_REMOTE_DEBUG n
++define_bool CONFIG_SBUS n
++define_bool CONFIG_SIMNOW n
++define_bool CONFIG_SOFTWARE_SUSPEND n
++define_bool CONFIG_TQM860 n
++define_bool CONFIG_VGA_CONSOLE n
++define_bool CONFIG_X86 n
++define_bool CONFIG_X86_IO_APIC n
++define_bool CONFIG_X86_LOCAL_APIC n
++define_bool CONFIG_X86_UP_APIC n
++define_bool CONFIG_X86_UP_IOAPIC n
++define_bool CONFIG_XSCALE_PMU_TIMER n
++define_bool CONFIG_IT8172_TUNING n
++define_bool CONFIG_SA1100_CONSUS n
++define_bool CONFIG_M68K n
++define_bool CONFIG_PPC32 n
++define_bool CONFIG_ISAPNP n
++define_tristate CONFIG_PCMCIA n
++define_tristate CONFIG_SERIAL n
++define_tristate CONFIG_DASD_CKD n
++define_tristate CONFIG_I2C n
++define_tristate CONFIG_I2C_ALGOBIT n
++define_tristate CONFIG_PARPORT n
++define_tristate CONFIG_PPP_DEFLATE n
++define_tristate CONFIG_SCSI_DEBUG n
++define_tristate CONFIG_SERIAL_8250 n
++define_tristate CONFIG_SONYPI n
++define_tristate CONFIG_SOUND_GAMEPORT n
++define_tristate CONFIG_MTD n
++define_tristate CONFIG_USB n
++define_tristate CONFIG_BLK_DEV_IDETAPE n
++define_tristate CONFIG_AMIGAMOUSE n
++define_tristate CONFIG_SCx200 n
++define_tristate CONFIG_DRM_GAMMA n
++define_tristate CONFIG_VIDEO_DEV n
++define_tristate CONFIG_BT n
++define_tristate CONFIG_BT_L2CAP n
++define_tristate CONFIG_BT_SCO n
++#undef
++define_bool CONFIG_HIGHPTE n
++define_bool CONFIG_GMAC n
++define_bool CONFIG_IEEE1394_PCILYNX_LOCALRAM n
++define_bool CONFIG_DRM_AGP n
++define_bool CONFIG_SERIAL_DETECT_IRQ n
++define_bool CONFIG_DEBUG_OBSOLETE n
++define_bool CONFIG_FB_TBOX n
++define_bool CONFIG_LOGITECH_3D n
++define_bool CONFIG_SERIAL_ROCKETPORT n
++define_bool CONFIG_MTD_INTELPROBE n
++define_bool CONFIG_SERIAL_ACPI n
++define_bool CONFIG_SA1100_BITSY n
++define_bool CONFIG_I2C_PARPORT n
++define_bool CONFIG_GAMEPORT_CS461X n
++define_bool CONFIG_NET_PROFILE n
++define_bool CONFIG_OBSOLETE n
++define_bool CONFIG_IEEE1394_PCILYNX_PORTS n
++define_bool CONFIG_MAPLE n
++define_bool CONFIG_L3 n
++define_bool CONFIG_SIBYTE_SB1250 n
++define_bool CONFIG_SA n
++define_bool CONFIG_405 n
++define_bool CONFIG_AX25_DAMA_MASTER n
++define_bool CONFIG_SND_DEBUG_DETECTION n
++define_bool CONFIG_PCMCIA_SERIAL_CS n
++define_bool CONFIG_SOUND_SND n
++define_bool CONFIG_MTD_CFI_INTELSTD n
++define_bool CONFIG_IT8172_REVC n
++define_bool CONFIG_UM n
++define_bool CONFIG_SIBYTE_SWARM n
++define_bool CONFIG_S390 n
++define_bool CONFIG_BLK_DEV_TIVO n
++define_bool CONFIG_BRIDGE_EBT n
++define_bool CONFIG_PPC_RTC n
++define_bool CONFIG_GART_IOMMU n
++define_bool CONFIG_ARCH_AUTCPU12 n
++define_bool CONFIG_ARCH_CEIVA n
++#help only
++define_bool CONFIG_BLK_DEV_HD_IDE n
++define_bool CONFIG_INPUT_GAMEPORT n
++define_bool CONFIG_BLK_DEV_IDE_TCQ_DEFAULT n
++define_bool CONFIG_BLK_DEV_ATARAID n
++define_bool CONFIG_ATAPI n
++define_bool CONFIG_AEC6280_BURST n
++define_bool CONFIG_BLK_DEV_IDE_TCQ n
++define_bool CONFIG_USB_SPEEDTCH n
++define_bool CONFIG_BLK_DEV_ATARAID_PDC n
++define_bool CONFIG_BLK_DEV_HD_ONLY n
++define_bool CONFIG_BLK_DEV_ATARAID_HPT n
++define_bool CONFIG_NFS_DIRECTIO n
++define_bool CONFIG_AIC7XXX_OLD_PROC_STATS n
++define_bool CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT n
++define_bool CONFIG_ISDN_DIVAS_DIVA2I4L n
++define_bool CONFIG_CIFS_DEBUG n
++define_bool CONFIG_X86_CYCLONE n
++define_bool CONFIG_SA1100_FORTUNET n
++define_bool CONFIG_MTD_NAND_EDB7312 n
++endmenu
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
new file mode 100644
index 0000000..feefa1c
--- a/dev/null
+++ b/scripts/kconfig/qconf.cc
@@ -0,0 +1,1073 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <qapplication.h>
+#include <qmainwindow.h>
+#include <qtoolbar.h>
+#include <qvbox.h>
+#include <qsplitter.h>
+#include <qlistview.h>
+#include <qtextview.h>
+#include <qlineedit.h>
+#include <qmenubar.h>
+#include <qmessagebox.h>
+#include <qaction.h>
+#include <qheader.h>
+#include <qfiledialog.h>
+#include <qregexp.h>
+#include <stdlib.h>
+
+#include "lkc.h"
+#include "qconf.h"
+
+#include "qconf.moc"
+#include "images.c"
+
+static QApplication *configApp;
+
+/*
+ * update all the children of a menu entry
+ * removes/adds the entries from the parent widget as necessary
+ *
+ * parent: either the menu list widget or a menu entry widget
+ * menu: entry to be updated
+ */
+template <class P>
+static void updateMenuList(P* parent, struct menu* menu)
+{
+ struct menu* child;
+ ConfigList* list = parent->listView();
+ ConfigItem* item;
+ ConfigItem* last;
+ bool visible;
+ bool showAll = list->showAll;
+ enum listMode mode = list->mode;
+ enum prop_type type;
+
+ if (!menu) {
+ while ((item = parent->firstChild()))
+ delete item;
+ return;
+ }
+
+ last = 0;
+ for (child = menu->list; child; child = child->next) {
+ item = last ? last->nextSibling() : parent->firstChild();
+ type = child->prompt ? child->prompt->type : P_UNKNOWN;
+
+ switch (mode) {
+ case menuMode:
+ if (type != P_ROOTMENU)
+ goto hide;
+ break;
+ case symbolMode:
+ if (type == P_ROOTMENU)
+ goto hide;
+ break;
+ default:
+ break;
+ }
+
+ visible = menu_is_visible(child);
+ if (showAll || visible) {
+ if (!item || item->menu != child)
+ item = new ConfigItem(parent, last, child);
+ item->visible = visible;
+ item->updateMenu();
+
+ if (mode == fullMode || mode == menuMode ||
+ (type != P_MENU && type != P_ROOTMENU))
+ updateMenuList(item, child);
+ else
+ updateMenuList(item, 0);
+ last = item;
+ continue;
+ }
+ hide:
+ if (item && item->menu == child) {
+ last = parent->firstChild();
+ if (last == item)
+ last = 0;
+ else while (last->nextSibling() != item)
+ last = last->nextSibling();
+ delete item;
+ }
+ }
+}
+
+#if QT_VERSION >= 300
+/*
+ * set the new data
+ * TODO check the value
+ */
+void ConfigItem::okRename(int col)
+{
+ Parent::okRename(col);
+ sym_set_string_value(menu->sym, text(dataColIdx).latin1());
+}
+#endif
+
+/*
+ * update the displayed of a menu entry
+ */
+void ConfigItem::updateMenu(void)
+{
+ ConfigList* list;
+ struct symbol* sym;
+ QString prompt;
+ int type;
+ enum prop_type ptype;
+ tristate expr;
+ bool update;
+
+ list = listView();
+ update = doInit;
+ if (update)
+ doInit = false;
+ else
+ update = list->updateAll;
+
+ sym = menu->sym;
+ if (!sym) {
+ if (update) {
+ setText(promptColIdx, menu_get_prompt(menu));
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if ((ptype == P_ROOTMENU || ptype == P_MENU) &&
+ (list->mode == singleMode || list->mode == symbolMode))
+ setPixmap(promptColIdx, list->menuPix);
+ else
+ setPixmap(promptColIdx, 0);
+ }
+ return;
+ }
+
+ sym_calc_value(sym);
+ if (!(sym->flags & SYMBOL_CHANGED) && !update)
+ return;
+
+ sym->flags &= ~SYMBOL_CHANGED;
+
+ setText(nameColIdx, menu->sym->name);
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ char ch;
+
+ prompt = menu_get_prompt(menu);
+ if (!sym_is_changable(sym) && !list->showAll) {
+ setText(noColIdx, 0);
+ setText(modColIdx, 0);
+ setText(yesColIdx, 0);
+ break;
+ }
+ expr = sym_get_tristate_value(sym);
+ switch (expr) {
+ case yes:
+ if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ setPixmap(promptColIdx, list->choiceYesPix);
+ else
+ setPixmap(promptColIdx, list->symbolYesPix);
+ setText(yesColIdx, "Y");
+ ch = 'Y';
+ break;
+ case mod:
+ setPixmap(promptColIdx, list->symbolModPix);
+ setText(modColIdx, "M");
+ ch = 'M';
+ break;
+ default:
+ if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ setPixmap(promptColIdx, list->choiceNoPix);
+ else
+ setPixmap(promptColIdx, list->symbolNoPix);
+ setText(noColIdx, "N");
+ ch = 'N';
+ break;
+ }
+ if (expr != no)
+ setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0);
+ if (expr != mod)
+ setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0);
+ if (expr != yes)
+ setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0);
+
+ setText(dataColIdx, QChar(ch));
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ const char* data;
+
+ data = sym_get_string_value(sym);
+#if QT_VERSION >= 300
+ setRenameEnabled(list->mapIdx(dataColIdx), TRUE);
+#endif
+ setText(dataColIdx, data);
+ if (type == S_STRING)
+ prompt.sprintf("%s: %s", menu_get_prompt(menu), data);
+ else
+ prompt.sprintf("(%s) %s", data, menu_get_prompt(menu));
+ break;
+ }
+ if (!sym_has_value(sym) && visible)
+ prompt += " (NEW)";
+ setText(promptColIdx, prompt);
+}
+
+void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align)
+{
+ ConfigList* list = listView();
+
+ if (visible) {
+ if (isSelected() && !list->hasFocus() && list->mode == menuMode)
+ Parent::paintCell(p, list->inactivedColorGroup, column, width, align);
+ else
+ Parent::paintCell(p, cg, column, width, align);
+ } else
+ Parent::paintCell(p, list->disabledColorGroup, column, width, align);
+}
+
+/*
+ * construct a menu entry
+ */
+void ConfigItem::init(void)
+{
+ ConfigList* list = listView();
+#if QT_VERSION < 300
+ visible = TRUE;
+#endif
+ //menu->data = this;
+ if (list->mode != fullMode)
+ setOpen(TRUE);
+ doInit= true;
+}
+
+/*
+ * destruct a menu entry
+ */
+ConfigItem::~ConfigItem(void)
+{
+ //menu->data = 0;
+}
+
+void ConfigLineEdit::show(ConfigItem* i)
+{
+ item = i;
+ if (sym_get_string_value(item->menu->sym))
+ setText(sym_get_string_value(item->menu->sym));
+ else
+ setText(0);
+ Parent::show();
+ setFocus();
+}
+
+void ConfigLineEdit::keyPressEvent(QKeyEvent* e)
+{
+ switch (e->key()) {
+ case Key_Escape:
+ break;
+ case Key_Return:
+ case Key_Enter:
+ sym_set_string_value(item->menu->sym, text().latin1());
+ emit lineChanged(item);
+ break;
+ default:
+ Parent::keyPressEvent(e);
+ return;
+ }
+ e->accept();
+ hide();
+}
+
+ConfigList::ConfigList(QWidget* p, ConfigView* cv)
+ : Parent(p), cview(cv),
+ updateAll(false),
+ symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
+ choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), menuPix(xpm_menu), menuInvPix(xpm_menu_inv),
+ showAll(false), showName(false), showRange(false), showData(false),
+ rootEntry(0)
+{
+ int i;
+
+ setSorting(-1);
+ setRootIsDecorated(TRUE);
+ disabledColorGroup = palette().active();
+ disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text());
+ inactivedColorGroup = palette().active();
+ inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight());
+
+ connect(this, SIGNAL(selectionChanged(void)),
+ SLOT(updateSelection(void)));
+
+ for (i = 0; i < colNr; i++)
+ colMap[i] = colRevMap[i] = -1;
+ addColumn(promptColIdx, "Option");
+
+ reinit();
+}
+
+void ConfigList::reinit(void)
+{
+ removeColumn(dataColIdx);
+ removeColumn(yesColIdx);
+ removeColumn(modColIdx);
+ removeColumn(noColIdx);
+ removeColumn(nameColIdx);
+
+ if (showName)
+ addColumn(nameColIdx, "Name");
+ if (showRange) {
+ addColumn(noColIdx, "N");
+ addColumn(modColIdx, "M");
+ addColumn(yesColIdx, "Y");
+ }
+ if (showData)
+ addColumn(dataColIdx, "Value");
+
+ updateListAll();
+}
+
+void ConfigList::updateSelection(void)
+{
+ struct menu *menu;
+ enum prop_type type;
+
+ ConfigItem* item = (ConfigItem*)selectedItem();
+ if (!item)
+ return;
+
+ cview->setHelp(item);
+
+ menu = item->menu;
+ type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (mode == menuMode && (type == P_MENU || type == P_ROOTMENU))
+ emit menuSelected(menu);
+}
+
+void ConfigList::updateList(ConfigItem* item)
+{
+ (void)item; // unused so far
+ updateMenuList(this, rootEntry);
+}
+
+void ConfigList::setAllOpen(bool open)
+{
+ QListViewItemIterator it(this);
+
+ for (; it.current(); it++)
+ it.current()->setOpen(open);
+}
+
+void ConfigList::setValue(ConfigItem* item, tristate val)
+{
+ struct symbol* sym;
+ int type;
+ tristate oldval;
+
+ sym = item->menu->sym;
+ if (!sym)
+ return;
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ oldval = sym_get_tristate_value(sym);
+
+ if (!sym_set_tristate_value(sym, val))
+ return;
+ if (oldval == no && item->menu->list)
+ item->setOpen(TRUE);
+ emit symbolChanged(item);
+ break;
+ }
+}
+
+void ConfigList::changeValue(ConfigItem* item)
+{
+ struct symbol* sym;
+ struct menu* menu;
+ int type, oldexpr, newexpr;
+
+ menu = item->menu;
+ sym = menu->sym;
+ if (!sym) {
+ if (item->menu->list)
+ item->setOpen(!item->isOpen());
+ return;
+ }
+
+ type = sym_get_type(sym);
+ switch (type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ oldexpr = sym_get_tristate_value(sym);
+ newexpr = sym_toggle_tristate_value(sym);
+ if (item->menu->list) {
+ if (oldexpr == newexpr)
+ item->setOpen(!item->isOpen());
+ else if (oldexpr == no)
+ item->setOpen(TRUE);
+ }
+ if (oldexpr != newexpr)
+ emit symbolChanged(item);
+ break;
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+#if QT_VERSION >= 300
+ if (colMap[dataColIdx] >= 0)
+ item->startRename(colMap[dataColIdx]);
+ else
+#endif
+ lineEdit->show(item);
+ break;
+ }
+}
+
+void ConfigList::setRootMenu(struct menu *menu)
+{
+ enum prop_type type;
+
+ if (rootEntry == menu)
+ return;
+ type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if (type != P_MENU && type != P_ROOTMENU)
+ return;
+ updateMenuList(this, 0);
+ rootEntry = menu;
+ updateListAll();
+ setSelected(currentItem(), hasFocus());
+}
+
+void ConfigList::setParentMenu(void)
+{
+ ConfigItem* item;
+ struct menu *oldroot, *newroot;
+
+ oldroot = rootEntry;
+ newroot = menu_get_parent_menu(oldroot);
+ if (newroot == oldroot)
+ return;
+ setRootMenu(newroot);
+
+ QListViewItemIterator it(this);
+ for (; (item = (ConfigItem*)it.current()); it++) {
+ if (item->menu == oldroot) {
+ setCurrentItem(item);
+ ensureItemVisible(item);
+ break;
+ }
+ }
+}
+
+void ConfigList::keyPressEvent(QKeyEvent* ev)
+{
+ QListViewItem* i = currentItem();
+ ConfigItem* item;
+ struct menu *menu;
+ enum prop_type type;
+
+ if (ev->key() == Key_Escape && mode != fullMode) {
+ emit parentSelected();
+ ev->accept();
+ return;
+ }
+
+ if (!i) {
+ Parent::keyPressEvent(ev);
+ return;
+ }
+ item = (ConfigItem*)i;
+
+ switch (ev->key()) {
+ case Key_Return:
+ case Key_Enter:
+ menu = item->menu;
+ type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if ((type == P_MENU || type == P_ROOTMENU) && mode != fullMode) {
+ emit menuSelected(menu);
+ break;
+ }
+ case Key_Space:
+ changeValue(item);
+ break;
+ case Key_N:
+ setValue(item, no);
+ break;
+ case Key_M:
+ setValue(item, mod);
+ break;
+ case Key_Y:
+ setValue(item, yes);
+ break;
+ default:
+ Parent::keyPressEvent(ev);
+ return;
+ }
+ ev->accept();
+}
+
+void ConfigList::contentsMousePressEvent(QMouseEvent* e)
+{
+ //QPoint p(contentsToViewport(e->pos()));
+ //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
+ QListView::contentsMousePressEvent(e);
+}
+
+void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e)
+{
+ QPoint p(contentsToViewport(e->pos()));
+ ConfigItem* item = (ConfigItem*)itemAt(p);
+ struct menu *menu;
+ const QPixmap* pm;
+ int idx, x;
+
+ if (!item)
+ goto skip;
+
+ menu = item->menu;
+ x = header()->offset() + p.x();
+ idx = colRevMap[header()->sectionAt(x)];
+ switch (idx) {
+ case promptColIdx:
+ pm = item->pixmap(promptColIdx);
+ if (pm) {
+ int off = header()->sectionPos(0) + itemMargin() +
+ treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0));
+ if (x >= off && x < off + pm->width()) {
+ if (menu->sym)
+ changeValue(item);
+ else
+ emit menuSelected(menu);
+ }
+ }
+ break;
+ case noColIdx:
+ setValue(item, no);
+ break;
+ case modColIdx:
+ setValue(item, mod);
+ break;
+ case yesColIdx:
+ setValue(item, yes);
+ break;
+ case dataColIdx:
+ changeValue(item);
+ break;
+ }
+
+skip:
+ //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y());
+ QListView::contentsMouseReleaseEvent(e);
+}
+
+void ConfigList::contentsMouseMoveEvent(QMouseEvent* e)
+{
+ //QPoint p(contentsToViewport(e->pos()));
+ //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
+ QListView::contentsMouseMoveEvent(e);
+}
+
+void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e)
+{
+ QPoint p(contentsToViewport(e->pos()));
+ ConfigItem* item = (ConfigItem*)itemAt(p);
+ struct menu *menu;
+ enum prop_type ptype;
+
+ if (!item)
+ goto skip;
+ menu = item->menu;
+ ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
+ if ((ptype == P_ROOTMENU || ptype == P_MENU) &&
+ (mode == singleMode || mode == symbolMode))
+ emit menuSelected(menu);
+
+skip:
+ //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y());
+ QListView::contentsMouseDoubleClickEvent(e);
+}
+
+void ConfigList::focusInEvent(QFocusEvent *e)
+{
+ Parent::focusInEvent(e);
+
+ QListViewItem* item = currentItem();
+ if (!item)
+ return;
+
+ setSelected(item, TRUE);
+ emit gotFocus();
+}
+
+/*
+ * Construct the complete config widget
+ */
+ConfigView::ConfigView(void)
+{
+ QMenuBar* menu;
+ QSplitter* split1;
+ QSplitter* split2;
+
+ showDebug = false;
+
+ split1 = new QSplitter(this);
+ split1->setOrientation(QSplitter::Horizontal);
+ setCentralWidget(split1);
+
+ menuList = new ConfigList(split1, this);
+
+ split2 = new QSplitter(split1);
+ split2->setOrientation(QSplitter::Vertical);
+
+ // create config tree
+ QVBox* box = new QVBox(split2);
+ configList = new ConfigList(box, this);
+ configList->lineEdit = new ConfigLineEdit(box);
+ configList->lineEdit->hide();
+ configList->connect(configList, SIGNAL(symbolChanged(ConfigItem*)),
+ configList, SLOT(updateList(ConfigItem*)));
+ configList->connect(configList, SIGNAL(symbolChanged(ConfigItem*)),
+ menuList, SLOT(updateList(ConfigItem*)));
+ configList->connect(configList->lineEdit, SIGNAL(lineChanged(ConfigItem*)),
+ SLOT(updateList(ConfigItem*)));
+
+ helpText = new QTextView(split2);
+ helpText->setTextFormat(Qt::RichText);
+
+ setTabOrder(configList, helpText);
+ configList->setFocus();
+
+ menu = menuBar();
+ toolBar = new QToolBar("Tools", this);
+
+ backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
+ connect(backAction, SIGNAL(activated()), SLOT(goBack()));
+ backAction->setEnabled(FALSE);
+ QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
+ connect(quitAction, SIGNAL(activated()), SLOT(close()));
+ QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
+ connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
+ QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
+ connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
+ QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
+ connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
+ QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
+ connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
+ QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
+ connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
+ QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
+ connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
+
+ QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
+ showNameAction->setToggleAction(TRUE);
+ showNameAction->setOn(configList->showName);
+ connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool)));
+ QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
+ showRangeAction->setToggleAction(TRUE);
+ showRangeAction->setOn(configList->showRange);
+ connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool)));
+ QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
+ showDataAction->setToggleAction(TRUE);
+ showDataAction->setOn(configList->showData);
+ connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool)));
+ QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
+ showAllAction->setToggleAction(TRUE);
+ showAllAction->setOn(configList->showAll);
+ connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool)));
+ QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
+ showDebugAction->setToggleAction(TRUE);
+ showDebugAction->setOn(showDebug);
+ connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
+
+ // init tool bar
+ backAction->addTo(toolBar);
+ toolBar->addSeparator();
+ loadAction->addTo(toolBar);
+ saveAction->addTo(toolBar);
+ toolBar->addSeparator();
+ singleViewAction->addTo(toolBar);
+ splitViewAction->addTo(toolBar);
+ fullViewAction->addTo(toolBar);
+
+ // create config menu
+ QPopupMenu* config = new QPopupMenu(this);
+ menu->insertItem("&File", config);
+ loadAction->addTo(config);
+ saveAction->addTo(config);
+ saveAsAction->addTo(config);
+ config->insertSeparator();
+ quitAction->addTo(config);
+
+ // create options menu
+ QPopupMenu* optionMenu = new QPopupMenu(this);
+ menu->insertItem("&Option", optionMenu);
+ showNameAction->addTo(optionMenu);
+ showRangeAction->addTo(optionMenu);
+ showDataAction->addTo(optionMenu);
+ optionMenu->insertSeparator();
+ showAllAction->addTo(optionMenu);
+ showDebugAction->addTo(optionMenu);
+
+ connect(configList, SIGNAL(menuSelected(struct menu *)),
+ SLOT(changeMenu(struct menu *)));
+ connect(configList, SIGNAL(parentSelected()),
+ SLOT(goBack()));
+ connect(menuList, SIGNAL(menuSelected(struct menu *)),
+ SLOT(changeMenu(struct menu *)));
+
+ connect(configList, SIGNAL(gotFocus(void)),
+ SLOT(listFocusChanged(void)));
+ connect(menuList, SIGNAL(gotFocus(void)),
+ SLOT(listFocusChanged(void)));
+
+ //showFullView();
+ showSplitView();
+}
+
+static QString print_filter(const char *str)
+{
+ QRegExp re("[<>&\"\\n]");
+ QString res = str;
+ for (int i = 0; (i = res.find(re, i)) >= 0;) {
+ switch (res[i].latin1()) {
+ case '<':
+ res.replace(i, 1, "&lt;");
+ i += 4;
+ break;
+ case '>':
+ res.replace(i, 1, "&gt;");
+ i += 4;
+ break;
+ case '&':
+ res.replace(i, 1, "&amp;");
+ i += 5;
+ break;
+ case '"':
+ res.replace(i, 1, "&quot;");
+ i += 6;
+ break;
+ case '\n':
+ res.replace(i, 1, "<br>");
+ i += 4;
+ break;
+ }
+ }
+ return res;
+}
+
+static void expr_print_help(void *data, const char *str)
+{
+ ((QString*)data)->append(print_filter(str));
+}
+
+/*
+ * display a new help entry as soon as a new menu entry is selected
+ */
+void ConfigView::setHelp(QListViewItem* item)
+{
+ struct symbol* sym;
+ struct menu* menu;
+
+ configList->lineEdit->hide();
+ if (item) {
+ QString head, debug, help;
+ menu = ((ConfigItem*)item)->menu;
+ sym = menu->sym;
+ if (sym) {
+ if (menu->prompt) {
+ head += "<big><b>";
+ head += print_filter(menu->prompt->text);
+ head += "</b></big>";
+ if (sym->name) {
+ head += " (";
+ head += print_filter(sym->name);
+ head += ")";
+ }
+ } else if (sym->name) {
+ head += "<big><b>";
+ head += print_filter(sym->name);
+ head += "</b></big>";
+ }
+ head += "<br><br>";
+
+ if (showDebug) {
+ debug += "type: ";
+ debug += print_filter(sym_type_name(sym->type));
+ debug += "<br>";
+ for (struct property *prop = sym->prop; prop; prop = prop->next) {
+ switch (prop->type) {
+ case P_PROMPT:
+ debug += "prompt: ";
+ debug += print_filter(prop->text);
+ debug += "<br>";
+ if (prop->visible.expr) {
+ debug += "&nbsp;&nbsp;dep: ";
+ expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
+ debug += "<br>";
+ }
+ break;
+ case P_DEFAULT:
+ debug += "default: ";
+ if (sym_is_choice(sym))
+ debug += print_filter(prop->def->name);
+ else {
+ sym_calc_value(prop->def);
+ debug += print_filter(sym_get_string_value(prop->def));
+ }
+ debug += "<br>";
+ if (prop->visible.expr) {
+ debug += "&nbsp;&nbsp;dep: ";
+ expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
+ debug += "<br>";
+ }
+ break;
+ case P_CHOICE:
+ break;
+ default:
+ debug += "unknown property: ";
+ debug += prop_get_type_name(prop->type);
+ debug += "<br>";
+ }
+ }
+ debug += "<br>";
+ }
+
+ help = print_filter(sym->help);
+ } else if (menu->prompt) {
+ head += "<big><b>";
+ head += print_filter(menu->prompt->text);
+ head += "</b></big><br><br>";
+ if (showDebug) {
+ if (menu->prompt->visible.expr) {
+ debug += "&nbsp;&nbsp;dep: ";
+ expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
+ debug += "<br>";
+ }
+ }
+ }
+ helpText->setText(head + debug + help);
+ return;
+ }
+ helpText->setText(NULL);
+}
+
+void ConfigView::loadConfig(void)
+{
+ QString s = QFileDialog::getOpenFileName(".config", NULL, this);
+ if (s.isNull())
+ return;
+ if (conf_read(s.latin1()))
+ QMessageBox::information(this, "qconf", "Unable to load configuration!");
+}
+
+void ConfigView::saveConfig(void)
+{
+ if (conf_write(NULL))
+ QMessageBox::information(this, "qconf", "Unable to save configuration!");
+}
+
+void ConfigView::saveConfigAs(void)
+{
+ QString s = QFileDialog::getSaveFileName(".config", NULL, this);
+ if (s.isNull())
+ return;
+ if (conf_write(s.latin1()))
+ QMessageBox::information(this, "qconf", "Unable to save configuration!");
+}
+
+void ConfigView::changeMenu(struct menu *menu)
+{
+ configList->setRootMenu(menu);
+ backAction->setEnabled(TRUE);
+}
+
+void ConfigView::listFocusChanged(void)
+{
+ if (menuList->hasFocus()) {
+ if (menuList->mode == menuMode)
+ configList->clearSelection();
+ setHelp(menuList->selectedItem());
+ } else if (configList->hasFocus()) {
+ setHelp(configList->selectedItem());
+ }
+}
+
+void ConfigView::goBack(void)
+{
+ ConfigItem* item;
+
+ configList->setParentMenu();
+ if (configList->rootEntry == &rootmenu)
+ backAction->setEnabled(FALSE);
+ item = (ConfigItem*)menuList->selectedItem();
+ while (item) {
+ if (item->menu == configList->rootEntry) {
+ menuList->setSelected(item, TRUE);
+ break;
+ }
+ item = (ConfigItem*)item->parent();
+ }
+}
+
+void ConfigView::showSingleView(void)
+{
+ menuList->hide();
+ menuList->setRootMenu(0);
+ configList->mode = singleMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(TRUE);
+ configList->setFocus();
+}
+
+void ConfigView::showSplitView(void)
+{
+ configList->mode = symbolMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(TRUE);
+ configApp->processEvents();
+ menuList->mode = menuMode;
+ menuList->setRootMenu(&rootmenu);
+ menuList->show();
+ menuList->setAllOpen(TRUE);
+ menuList->setFocus();
+}
+
+void ConfigView::showFullView(void)
+{
+ menuList->hide();
+ menuList->setRootMenu(0);
+ configList->mode = fullMode;
+ if (configList->rootEntry == &rootmenu)
+ configList->updateListAll();
+ else
+ configList->setRootMenu(&rootmenu);
+ configList->setAllOpen(FALSE);
+ configList->setFocus();
+}
+
+void ConfigView::setShowAll(bool b)
+{
+ if (configList->showAll == b)
+ return;
+ configList->showAll = b;
+ configList->updateListAll();
+ menuList->showAll = b;
+ menuList->updateListAll();
+}
+
+void ConfigView::setShowDebug(bool b)
+{
+ if (showDebug == b)
+ return;
+ showDebug = b;
+}
+
+void ConfigView::setShowName(bool b)
+{
+ if (configList->showName == b)
+ return;
+ configList->showName = b;
+ configList->reinit();
+}
+
+void ConfigView::setShowRange(bool b)
+{
+ if (configList->showRange == b)
+ return;
+ configList->showRange = b;
+ configList->reinit();
+}
+
+void ConfigView::setShowData(bool b)
+{
+ if (configList->showData == b)
+ return;
+ configList->showData = b;
+ configList->reinit();
+}
+
+/*
+ * ask for saving configuration before quitting
+ * TODO ask only when something changed
+ */
+void ConfigView::closeEvent(QCloseEvent* e)
+{
+ if (!sym_change_count) {
+ e->accept();
+ return;
+ }
+ QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning,
+ QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape);
+ mb.setButtonText(QMessageBox::Yes, "&Save Changes");
+ mb.setButtonText(QMessageBox::No, "&Discard Changes");
+ mb.setButtonText(QMessageBox::Cancel, "Cancel Exit");
+ switch (mb.exec()) {
+ case QMessageBox::Yes:
+ conf_write(NULL);
+ case QMessageBox::No:
+ e->accept();
+ break;
+ case QMessageBox::Cancel:
+ e->ignore();
+ break;
+ }
+}
+
+void fixup_rootmenu(struct menu *menu)
+{
+ struct menu *child;
+
+ if (!menu->prompt || menu->prompt->type != P_MENU)
+ return;
+ menu->prompt->type = P_ROOTMENU;
+ for (child = menu->list; child; child = child->next)
+ fixup_rootmenu(child);
+}
+
+int main(int ac, char** av)
+{
+ ConfigView* v;
+ const char *name;
+
+#ifndef LKC_DIRECT_LINK
+ kconfig_load();
+#endif
+
+ configApp = new QApplication(ac, av);
+ if (ac > 1 && av[1][0] == '-') {
+ switch (av[1][1]) {
+ case 'a':
+ //showAll = 1;
+ break;
+ case 'h':
+ case '?':
+ printf("%s <config>\n", av[0]);
+ exit(0);
+ }
+ name = av[2];
+ } else
+ name = av[1];
+ conf_parse(name);
+ fixup_rootmenu(&rootmenu);
+ conf_read(NULL);
+ //zconfdump(stdout);
+ v = new ConfigView();
+
+ //zconfdump(stdout);
+ v->show();
+ configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
+ configApp->exec();
+ return 0;
+}
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
new file mode 100644
index 0000000..f8f3669
--- a/dev/null
+++ b/scripts/kconfig/qconf.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <qlistview.h>
+
+class ConfigLineEdit;
+class ConfigItem;
+class ConfigView;
+
+enum colIdx {
+ promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
+};
+enum listMode {
+ singleMode, menuMode, symbolMode, fullMode
+};
+
+class ConfigList : public QListView {
+ Q_OBJECT
+ typedef class QListView Parent;
+public:
+ ConfigList(QWidget* p, ConfigView* cview);
+ void reinit(void);
+
+ ConfigLineEdit* lineEdit;
+protected:
+ ConfigView* cview;
+
+ void keyPressEvent(QKeyEvent *e);
+ void contentsMousePressEvent(QMouseEvent *e);
+ void contentsMouseReleaseEvent(QMouseEvent *e);
+ void contentsMouseMoveEvent(QMouseEvent *e);
+ void contentsMouseDoubleClickEvent(QMouseEvent *e);
+ void focusInEvent(QFocusEvent *e);
+public slots:
+ void setRootMenu(struct menu *menu);
+
+ void updateList(ConfigItem *item);
+ void setValue(ConfigItem* item, tristate val);
+ void changeValue(ConfigItem* item);
+ void updateSelection(void);
+signals:
+ void menuSelected(struct menu *menu);
+ void parentSelected(void);
+ void symbolChanged(ConfigItem* item);
+ void gotFocus(void);
+
+public:
+ void updateListAll(void)
+ {
+ updateAll = true;
+ updateList(NULL);
+ updateAll = false;
+ }
+ ConfigList* listView()
+ {
+ return this;
+ }
+ ConfigItem* firstChild() const
+ {
+ return (ConfigItem *)Parent::firstChild();
+ }
+ int mapIdx(colIdx idx)
+ {
+ return colMap[idx];
+ }
+ void addColumn(colIdx idx, const QString& label)
+ {
+ colMap[idx] = Parent::addColumn(label);
+ colRevMap[colMap[idx]] = idx;
+ }
+ void removeColumn(colIdx idx)
+ {
+ int col = colMap[idx];
+ if (col >= 0) {
+ Parent::removeColumn(col);
+ colRevMap[col] = colMap[idx] = -1;
+ }
+ }
+ void setAllOpen(bool open);
+ void setParentMenu(void);
+
+ bool updateAll;
+
+ QPixmap symbolYesPix, symbolModPix, symbolNoPix;
+ QPixmap choiceYesPix, choiceNoPix, menuPix, menuInvPix;
+
+ bool showAll, showName, showRange, showData;
+ enum listMode mode;
+ struct menu *rootEntry;
+ QColorGroup disabledColorGroup;
+ QColorGroup inactivedColorGroup;
+
+private:
+ int colMap[colNr];
+ int colRevMap[colNr];
+};
+
+class ConfigItem : public QListViewItem {
+ typedef class QListViewItem Parent;
+public:
+ ConfigItem(QListView *parent, ConfigItem *after, struct menu *m)
+ : Parent(parent, after), menu(m)
+ {
+ init();
+ }
+ ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m)
+ : Parent(parent, after), menu(m)
+ {
+ init();
+ }
+ ~ConfigItem(void);
+ void init(void);
+#if QT_VERSION >= 300
+ void okRename(int col);
+#endif
+ void updateMenu(void);
+ ConfigList* listView() const
+ {
+ return (ConfigList*)Parent::listView();
+ }
+ ConfigItem* firstChild() const
+ {
+ return (ConfigItem *)Parent::firstChild();
+ }
+ ConfigItem* nextSibling() const
+ {
+ return (ConfigItem *)Parent::nextSibling();
+ }
+ void setText(colIdx idx, const QString& text)
+ {
+ Parent::setText(listView()->mapIdx(idx), text);
+ }
+ QString text(colIdx idx) const
+ {
+ return Parent::text(listView()->mapIdx(idx));
+ }
+ void setPixmap(colIdx idx, const QPixmap& pm)
+ {
+ Parent::setPixmap(listView()->mapIdx(idx), pm);
+ }
+ const QPixmap* pixmap(colIdx idx) const
+ {
+ return Parent::pixmap(listView()->mapIdx(idx));
+ }
+ void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align);
+
+ struct menu *menu;
+ bool visible;
+ bool doInit;
+};
+
+class ConfigLineEdit : public QLineEdit {
+ Q_OBJECT
+ typedef class QLineEdit Parent;
+public:
+ ConfigLineEdit(QWidget * parent)
+ : QLineEdit(parent)
+ { }
+ void show(ConfigItem *i);
+ void keyPressEvent(QKeyEvent *e);
+signals:
+ void lineChanged(ConfigItem *item);
+
+public:
+ ConfigItem *item;
+};
+
+class ConfigView : public QMainWindow {
+ Q_OBJECT
+public:
+ ConfigView(void);
+public slots:
+ void setHelp(QListViewItem* item);
+ void changeMenu(struct menu *);
+ void listFocusChanged(void);
+ void goBack(void);
+ void loadConfig(void);
+ void saveConfig(void);
+ void saveConfigAs(void);
+ void showSingleView(void);
+ void showSplitView(void);
+ void showFullView(void);
+ void setShowAll(bool);
+ void setShowDebug(bool);
+ void setShowRange(bool);
+ void setShowName(bool);
+ void setShowData(bool);
+
+protected:
+ void closeEvent(QCloseEvent *e);
+
+ ConfigList *menuList;
+ ConfigList *configList;
+ QTextView *helpText;
+ QToolBar *toolBar;
+ QAction *backAction;
+
+ bool showDebug;
+};
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
new file mode 100644
index 0000000..59c88d2
--- a/dev/null
+++ b/scripts/kconfig/symbol.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/utsname.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+
+struct symbol symbol_yes = {
+ name: "y",
+ curr: { "y", yes },
+ flags: SYMBOL_YES|SYMBOL_VALID,
+}, symbol_mod = {
+ name: "m",
+ curr: { "m", mod },
+ flags: SYMBOL_MOD|SYMBOL_VALID,
+}, symbol_no = {
+ name: "n",
+ curr: { "n", no },
+ flags: SYMBOL_NO|SYMBOL_VALID,
+}, symbol_empty = {
+ name: "",
+ curr: { "", no },
+ flags: SYMBOL_VALID,
+};
+
+int sym_change_count;
+struct symbol *modules_sym;
+
+void sym_add_default(struct symbol *sym, const char *def)
+{
+ struct property *prop = create_prop(P_DEFAULT);
+ struct property **propp;
+
+ prop->sym = sym;
+ prop->def = sym_lookup(def, 1);
+
+ /* append property to the prop list of symbol */
+ if (prop->sym) {
+ for (propp = &prop->sym->prop; *propp; propp = &(*propp)->next)
+ ;
+ *propp = prop;
+ }
+}
+
+void sym_init(void)
+{
+ struct symbol *sym;
+ struct utsname uts;
+ char *p;
+ static bool inited = false;
+
+ if (inited)
+ return;
+ inited = true;
+
+ uname(&uts);
+
+ sym = sym_lookup("ARCH", 0);
+ sym->type = S_STRING;
+ sym->flags |= SYMBOL_AUTO;
+ p = getenv("ARCH");
+ if (p)
+ sym_add_default(sym, p);
+
+ sym = sym_lookup("KERNELRELEASE", 0);
+ sym->type = S_STRING;
+ sym->flags |= SYMBOL_AUTO;
+ p = getenv("KERNELRELEASE");
+ if (p)
+ sym_add_default(sym, p);
+
+ sym = sym_lookup("UNAME_RELEASE", 0);
+ sym->type = S_STRING;
+ sym->flags |= SYMBOL_AUTO;
+ sym_add_default(sym, uts.release);
+}
+
+int sym_get_type(struct symbol *sym)
+{
+ int type = sym->type;
+ if (type == S_TRISTATE) {
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ type = S_BOOLEAN;
+ else {
+ sym_calc_value(modules_sym);
+ if (S_TRI(modules_sym->curr) == no)
+ type = S_BOOLEAN;
+ }
+ }
+ return type;
+}
+
+const char *sym_type_name(int type)
+{
+ switch (type) {
+ case S_BOOLEAN:
+ return "boolean";
+ case S_TRISTATE:
+ return "tristate";
+ case S_INT:
+ return "integer";
+ case S_HEX:
+ return "hex";
+ case S_STRING:
+ return "string";
+ case S_UNKNOWN:
+ return "unknown";
+ }
+ return "???";
+}
+
+struct property *sym_get_choice_prop(struct symbol *sym)
+{
+ struct property *prop;
+
+ for_all_choices(sym, prop)
+ return prop;
+ return NULL;
+}
+
+struct property *sym_get_default_prop(struct symbol *sym)
+{
+ struct property *prop;
+ tristate visible;
+
+ for_all_defaults(sym, prop) {
+ visible = E_CALC(prop->visible);
+ if (visible != no)
+ return prop;
+ }
+ return NULL;
+}
+
+void sym_calc_visibility(struct symbol *sym)
+{
+ struct property *prop;
+ tristate visible, oldvisible;
+
+ /* any prompt visible? */
+ oldvisible = sym->visible;
+ visible = no;
+ for_all_prompts(sym, prop)
+ visible = E_OR(visible, E_CALC(prop->visible));
+ if (oldvisible != visible) {
+ sym->visible = visible;
+ sym->flags |= SYMBOL_CHANGED;
+ }
+}
+
+void sym_calc_value(struct symbol *sym)
+{
+ struct symbol_value newval, oldval;
+ struct property *prop, *def_prop;
+ struct symbol *def_sym;
+ struct expr *e;
+
+ if (sym->flags & SYMBOL_VALID)
+ return;
+
+ oldval = sym->curr;
+
+ switch (sym->type) {
+ case S_INT:
+ case S_HEX:
+ case S_STRING:
+ newval = symbol_empty.curr;
+ break;
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ newval = symbol_no.curr;
+ break;
+ default:
+ S_VAL(newval) = sym->name;
+ S_TRI(newval) = no;
+ if (sym->flags & SYMBOL_CONST) {
+ goto out;
+ }
+ //newval = symbol_empty.curr;
+ // generate warning somewhere here later
+ //S_TRI(newval) = yes;
+ goto out;
+ }
+ sym->flags |= SYMBOL_VALID;
+ if (!sym_is_choice_value(sym))
+ sym->flags &= ~SYMBOL_WRITE;
+
+ sym_calc_visibility(sym);
+
+ /* set default if recursively called */
+ sym->curr = newval;
+
+ if (sym->visible != no) {
+ sym->flags |= SYMBOL_WRITE;
+ if (!sym_has_value(sym)) {
+ if (!sym_is_choice(sym)) {
+ prop = sym_get_default_prop(sym);
+ if (prop) {
+ sym_calc_value(prop->def);
+ newval = prop->def->curr;
+ }
+ }
+ } else
+ newval = sym->def;
+
+ S_TRI(newval) = E_AND(S_TRI(newval), sym->visible);
+ /* if the symbol is visible and not optionial,
+ * possibly ignore old user choice. */
+ if (!sym_is_optional(sym) && S_TRI(newval) == no)
+ S_TRI(newval) = sym->visible;
+ if (sym_is_choice_value(sym) && sym->visible == yes) {
+ prop = sym_get_choice_prop(sym);
+ S_TRI(newval) = (S_VAL(prop->def->curr) == sym) ? yes : no;
+ }
+ } else {
+ prop = sym_get_default_prop(sym);
+ if (prop) {
+ sym->flags |= SYMBOL_WRITE;
+ sym_calc_value(prop->def);
+ newval = prop->def->curr;
+ }
+ }
+
+ switch (sym_get_type(sym)) {
+ case S_TRISTATE:
+ if (S_TRI(newval) != mod)
+ break;
+ sym_calc_value(modules_sym);
+ if (S_TRI(modules_sym->curr) == no)
+ S_TRI(newval) = yes;
+ break;
+ case S_BOOLEAN:
+ if (S_TRI(newval) == mod)
+ S_TRI(newval) = yes;
+ }
+
+out:
+ sym->curr = newval;
+
+ if (sym_is_choice(sym) && S_TRI(newval) == yes) {
+ def_sym = S_VAL(sym->def);
+ if (def_sym) {
+ sym_calc_visibility(def_sym);
+ if (def_sym->visible == no)
+ def_sym = NULL;
+ }
+ if (!def_sym) {
+ for_all_defaults(sym, def_prop) {
+ if (E_CALC(def_prop->visible) == no)
+ continue;
+ sym_calc_visibility(def_prop->def);
+ if (def_prop->def->visible != no) {
+ def_sym = def_prop->def;
+ break;
+ }
+ }
+ }
+
+ if (!def_sym) {
+ prop = sym_get_choice_prop(sym);
+ for (e = prop->dep; e; e = e->left.expr) {
+ sym_calc_visibility(e->right.sym);
+ if (e->right.sym->visible != no) {
+ def_sym = e->right.sym;
+ break;
+ }
+ }
+ }
+
+ S_VAL(newval) = def_sym;
+ }
+
+ if (memcmp(&oldval, &newval, sizeof(newval)))
+ sym->flags |= SYMBOL_CHANGED;
+ sym->curr = newval;
+
+ if (sym_is_choice(sym)) {
+ int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
+ prop = sym_get_choice_prop(sym);
+ for (e = prop->dep; e; e = e->left.expr)
+ e->right.sym->flags |= flags;
+ }
+}
+
+void sym_clear_all_valid(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym->flags &= ~SYMBOL_VALID;
+ sym_change_count++;
+}
+
+void sym_set_all_changed(void)
+{
+ struct symbol *sym;
+ int i;
+
+ for_all_symbols(i, sym)
+ sym->flags |= SYMBOL_CHANGED;
+}
+
+bool sym_tristate_within_range(struct symbol *sym, tristate val)
+{
+ int type = sym_get_type(sym);
+
+ if (sym->visible == no)
+ return false;
+
+ if (type != S_BOOLEAN && type != S_TRISTATE)
+ return false;
+
+ switch (val) {
+ case no:
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ return false;
+ return sym_is_optional(sym);
+ case mod:
+ if (sym_is_choice_value(sym) && sym->visible == yes)
+ return false;
+ return type == S_TRISTATE;
+ case yes:
+ return type == S_BOOLEAN || sym->visible == yes;
+ }
+ return false;
+}
+
+bool sym_set_tristate_value(struct symbol *sym, tristate val)
+{
+ tristate oldval = sym_get_tristate_value(sym);
+
+ if (oldval != val && !sym_tristate_within_range(sym, val))
+ return false;
+
+ if (sym->flags & SYMBOL_NEW) {
+ sym->flags &= ~SYMBOL_NEW;
+ sym->flags |= SYMBOL_CHANGED;
+ }
+ if (sym_is_choice_value(sym) && val == yes) {
+ struct property *prop = sym_get_choice_prop(sym);
+
+ S_VAL(prop->def->def) = sym;
+ prop->def->flags &= ~SYMBOL_NEW;
+ }
+
+ S_TRI(sym->def) = val;
+ if (oldval != val) {
+ sym_clear_all_valid();
+ if (sym == modules_sym)
+ sym_set_all_changed();
+ }
+
+ return true;
+}
+
+tristate sym_toggle_tristate_value(struct symbol *sym)
+{
+ tristate oldval, newval;
+
+ oldval = newval = sym_get_tristate_value(sym);
+ do {
+ switch (newval) {
+ case no:
+ newval = mod;
+ break;
+ case mod:
+ newval = yes;
+ break;
+ case yes:
+ newval = no;
+ break;
+ }
+ if (sym_set_tristate_value(sym, newval))
+ break;
+ } while (oldval != newval);
+ return newval;
+}
+
+bool sym_string_valid(struct symbol *sym, const char *str)
+{
+ char ch;
+
+ switch (sym->type) {
+ case S_STRING:
+ return true;
+ case S_INT:
+ ch = *str++;
+ if (ch == '-')
+ ch = *str++;
+ if (!isdigit(ch))
+ return false;
+ if (ch == '0' && *str != 0)
+ return false;
+ while ((ch = *str++)) {
+ if (!isdigit(ch))
+ return false;
+ }
+ return true;
+ case S_HEX:
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ str += 2;
+ ch = *str++;
+ do {
+ if (!isxdigit(ch))
+ return false;
+ } while ((ch = *str++));
+ return true;
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (str[0]) {
+ case 'y':
+ case 'Y':
+ return sym_tristate_within_range(sym, yes);
+ case 'm':
+ case 'M':
+ return sym_tristate_within_range(sym, mod);
+ case 'n':
+ case 'N':
+ return sym_tristate_within_range(sym, no);
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+bool sym_set_string_value(struct symbol *sym, const char *newval)
+{
+ const char *oldval;
+ char *val;
+ int size;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ switch (newval[0]) {
+ case 'y':
+ case 'Y':
+ return sym_set_tristate_value(sym, yes);
+ case 'm':
+ case 'M':
+ return sym_set_tristate_value(sym, mod);
+ case 'n':
+ case 'N':
+ return sym_set_tristate_value(sym, no);
+ }
+ return false;
+ default:
+ ;
+ }
+
+ if (!sym_string_valid(sym, newval))
+ return false;
+
+ if (sym->flags & SYMBOL_NEW) {
+ sym->flags &= ~SYMBOL_NEW;
+ sym->flags |= SYMBOL_CHANGED;
+ }
+
+ oldval = S_VAL(sym->def);
+ size = strlen(newval) + 1;
+ if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
+ size += 2;
+ S_VAL(sym->def) = val = malloc(size);
+ *val++ = '0';
+ *val++ = 'x';
+ } else if (!oldval || strcmp(oldval, newval))
+ S_VAL(sym->def) = val = malloc(size);
+ else
+ return true;
+
+ strcpy(val, newval);
+ free((void *)oldval);
+ sym_clear_all_valid();
+
+ return true;
+}
+
+const char *sym_get_string_value(struct symbol *sym)
+{
+ tristate val;
+
+ switch (sym->type) {
+ case S_BOOLEAN:
+ case S_TRISTATE:
+ val = sym_get_tristate_value(sym);
+ switch (val) {
+ case no:
+ return "n";
+ case mod:
+ return "m";
+ case yes:
+ return "y";
+ }
+ break;
+ default:
+ ;
+ }
+ return (const char *)S_VAL(sym->curr);
+}
+
+bool sym_is_changable(struct symbol *sym)
+{
+ if (sym->visible == no)
+ return false;
+ /* at least 'n' and 'y'/'m' is selectable */
+ if (sym_is_optional(sym))
+ return true;
+ /* no 'n', so 'y' and 'm' must be selectable */
+ if (sym_get_type(sym) == S_TRISTATE && sym->visible == yes)
+ return true;
+ return false;
+}
+
+struct symbol *sym_lookup(const char *name, int isconst)
+{
+ struct symbol *symbol;
+ const char *ptr;
+ char *new_name;
+ int hash = 0;
+
+ //printf("lookup: %s -> ", name);
+ if (name) {
+ if (name[0] && !name[1]) {
+ switch (name[0]) {
+ case 'y': return &symbol_yes;
+ case 'm': return &symbol_mod;
+ case 'n': return &symbol_no;
+ }
+ }
+ for (ptr = name; *ptr; ptr++)
+ hash += *ptr;
+ hash &= 0xff;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ if (!strcmp(symbol->name, name)) {
+ if ((isconst && symbol->flags & SYMBOL_CONST) ||
+ (!isconst && !(symbol->flags & SYMBOL_CONST))) {
+ //printf("h:%p\n", symbol);
+ return symbol;
+ }
+ }
+ }
+ new_name = strdup(name);
+ } else {
+ new_name = NULL;
+ hash = 256;
+ }
+
+ symbol = malloc(sizeof(*symbol));
+ memset(symbol, 0, sizeof(*symbol));
+ symbol->name = new_name;
+ symbol->type = S_UNKNOWN;
+ symbol->flags = SYMBOL_NEW;
+ if (isconst)
+ symbol->flags |= SYMBOL_CONST;
+
+ symbol->next = symbol_hash[hash];
+ symbol_hash[hash] = symbol;
+
+ //printf("n:%p\n", symbol);
+ return symbol;
+}
+
+struct symbol *sym_find(const char *name)
+{
+ struct symbol *symbol = NULL;
+ const char *ptr;
+ int hash = 0;
+
+ if (!name)
+ return NULL;
+
+ if (name[0] && !name[1]) {
+ switch (name[0]) {
+ case 'y': return &symbol_yes;
+ case 'm': return &symbol_mod;
+ case 'n': return &symbol_no;
+ }
+ }
+ for (ptr = name; *ptr; ptr++)
+ hash += *ptr;
+ hash &= 0xff;
+
+ for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
+ if (!strcmp(symbol->name, name) &&
+ !(symbol->flags & SYMBOL_CONST))
+ break;
+ }
+
+ return symbol;
+}
+
+const char *prop_get_type_name(enum prop_type type)
+{
+ switch (type) {
+ case P_PROMPT:
+ return "prompt";
+ case P_COMMENT:
+ return "comment";
+ case P_MENU:
+ return "menu";
+ case P_ROOTMENU:
+ return "rootmenu";
+ case P_DEFAULT:
+ return "default";
+ case P_CHOICE:
+ return "choice";
+ default:
+ return "unknown";
+ }
+}
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
new file mode 100644
index 0000000..6d81e5e
--- a/dev/null
+++ b/scripts/kconfig/zconf.l
@@ -0,0 +1,323 @@
+%option backup nostdinit noyywrap full ecs
+%option 8bit backup nodefault perf-report perf-report
+%x COMMAND HELP STRING PARAM
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+#include "zconf.tab.h"
+
+#define START_STRSIZE 16
+
+char *text;
+static char *text_ptr;
+static int text_size, text_asize;
+
+struct buffer {
+ struct buffer *parent;
+ YY_BUFFER_STATE state;
+};
+
+struct buffer *current_buf;
+
+static int last_ts, first_ts;
+
+static void zconf_endhelp(void);
+static struct buffer *zconf_endfile(void);
+
+void new_string(void)
+{
+ text = malloc(START_STRSIZE);
+ text_asize = START_STRSIZE;
+ text_ptr = text;
+ text_size = 0;
+ *text_ptr = 0;
+}
+
+void append_string(const char *str, int size)
+{
+ int new_size = text_size + size + 1;
+ if (new_size > text_asize) {
+ text = realloc(text, new_size);
+ text_asize = new_size;
+ text_ptr = text + text_size;
+ }
+ memcpy(text_ptr, str, size);
+ text_ptr += size;
+ text_size += size;
+ *text_ptr = 0;
+}
+
+void alloc_string(const char *str, int size)
+{
+ text = malloc(size + 1);
+ memcpy(text, str, size);
+ text[size] = 0;
+}
+%}
+
+ws [ \n\t]
+n [A-Za-z0-9_]
+
+%%
+ int str = 0;
+ int ts, i;
+
+[ \t]*#.*\n current_file->lineno++;
+[ \t]*#.*
+
+[ \t]*\n current_file->lineno++; return T_EOL;
+
+[ \t]+ {
+ BEGIN(COMMAND);
+}
+
+. {
+ unput(yytext[0]);
+ //printf("new config: ");
+ //symbol_end(NULL);
+ BEGIN(COMMAND);
+}
+
+
+<COMMAND>{
+ "mainmenu" BEGIN(PARAM); return T_MAINMENU;
+ "menu" BEGIN(PARAM); return T_MENU;
+ "endmenu" BEGIN(PARAM); return T_ENDMENU;
+ "source" BEGIN(PARAM); return T_SOURCE;
+ "choice" BEGIN(PARAM); return T_CHOICE;
+ "endchoice" BEGIN(PARAM); return T_ENDCHOICE;
+ "comment" BEGIN(PARAM); return T_COMMENT;
+ "config" BEGIN(PARAM); return T_CONFIG;
+ "help" BEGIN(PARAM); return T_HELP;
+ "if" BEGIN(PARAM); return T_IF;
+ "endif" BEGIN(PARAM); return T_ENDIF;
+ "depends" BEGIN(PARAM); return T_DEPENDS;
+ "requires" BEGIN(PARAM); return T_REQUIRES;
+ "optional" BEGIN(PARAM); return T_OPTIONAL;
+ "default" BEGIN(PARAM); return T_DEFAULT;
+ "prompt" BEGIN(PARAM); return T_PROMPT;
+ "tristate" BEGIN(PARAM); return T_TRISTATE;
+ "bool" BEGIN(PARAM); return T_BOOLEAN;
+ "boolean" BEGIN(PARAM); return T_BOOLEAN;
+ "int" BEGIN(PARAM); return T_INT;
+ "hex" BEGIN(PARAM); return T_HEX;
+ "string" BEGIN(PARAM); return T_STRING;
+ {n}+ {
+ alloc_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ .
+ \n current_file->lineno++; BEGIN(INITIAL);
+}
+
+<PARAM>{
+ "&&" return T_AND;
+ "||" return T_OR;
+ "(" return T_OPEN_PAREN;
+ ")" return T_CLOSE_PAREN;
+ "!" return T_NOT;
+ "=" return T_EQUAL;
+ "!=" return T_UNEQUAL;
+ "if" return T_IF;
+ "on" return T_ON;
+ \"|\' {
+ str = yytext[0];
+ new_string();
+ BEGIN(STRING);
+ }
+ \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
+ --- /* ignore */
+ ({n}|[-/.])+ {
+ alloc_string(yytext, yyleng);
+ zconflval.string = text;
+ return T_WORD;
+ }
+ .
+}
+
+<STRING>{
+ [^'"\n\\]+ {
+ append_string(yytext, yyleng);
+ }
+ \'|\" {
+ if (str == yytext[0]) {
+ BEGIN(PARAM);
+ zconflval.string = text;
+ //printf("s:%s\n", text);
+ return T_STRING;
+ } else
+ append_string(yytext, 1);
+ }
+ \\[ \t]*\n append_string(yytext+yyleng-1, 1); current_file->lineno++;
+ \\[ \t]* append_string(yytext+1, yyleng-1);
+ \\. append_string(yytext+1, 1);
+ \n {
+ //printf(":%d: open string!\n", current_file->lineno+1);
+ exit(0);
+ }
+ <<EOF>> {
+ //printf(":%d: open string!\n", current_file->lineno+1);
+ exit(0);
+ }
+}
+
+<HELP>{
+ [ \t]+ {
+ ts = 0;
+ for (i = 0; i < yyleng; i++) {
+ if (yytext[i] == '\t')
+ ts = (ts & ~7) + 8;
+ else
+ ts++;
+ }
+ last_ts = ts;
+ if (first_ts) {
+ if (ts < first_ts) {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ ts -= first_ts;
+ while (ts > 8) {
+ append_string(" ", 8);
+ ts -= 8;
+ }
+ append_string(" ", ts);
+ }
+
+ }
+ \n/[^ \t\n] {
+ current_file->lineno++;
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+ [ \t]*\n {
+ current_file->lineno++;
+ append_string("\n", 1);
+ }
+ [^ \t\n].* {
+ append_string(yytext, yyleng);
+ if (!first_ts)
+ first_ts = last_ts;
+ }
+ <<EOF>> {
+ zconf_endhelp();
+ return T_HELPTEXT;
+ }
+}
+
+<<EOF>> {
+ if (current_buf) {
+ zconf_endfile();
+ return T_EOF;
+ }
+ yyterminate();
+}
+
+%%
+void zconf_starthelp(void)
+{
+ new_string();
+ last_ts = first_ts = 0;
+ BEGIN(HELP);
+}
+
+static void zconf_endhelp(void)
+{
+ zconflval.string = text;
+ BEGIN(INITIAL);
+}
+
+void zconf_initscan(const char *name)
+{
+ yyin = fopen(name, "r");
+ if (!yyin) {
+ printf("can't find file %s\n", name);
+ exit(1);
+ }
+ //fprintf(stderr, "zconf_initscan: %s\n", name);
+
+ current_buf = malloc(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 *file = file_lookup(name);
+ struct buffer *buf = malloc(sizeof(*buf));
+ memset(buf, 0, sizeof(*buf));
+
+ current_buf->state = YY_CURRENT_BUFFER;
+ yyin = fopen(name, "r");
+ if (!yyin) {
+ printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
+ exit(1);
+ }
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+ buf->parent = current_buf;
+ current_buf = buf;
+
+ //fprintf(stderr, "zconf_nextfile: %s\n", name);
+
+ if (file->flags & FILE_BUSY) {
+ printf("recursive scan (%s)?\n", name);
+ exit(1);
+ }
+ if (file->flags & FILE_SCANNED) {
+ printf("file %s already scanned?\n", name);
+ exit(1);
+ }
+ file->flags |= FILE_BUSY;
+ file->lineno = 1;
+ file->parent = current_file;
+ current_file = file;
+}
+
+static struct buffer *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;
+ if (parent) {
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(parent->state);
+ }
+ free(current_buf);
+ current_buf = parent;
+
+ return parent;
+}
+
+int zconf_lineno(void)
+{
+ if (current_buf)
+ return current_file->lineno;
+ else
+ return 0;
+}
+
+char *zconf_curname(void)
+{
+ if (current_buf)
+ return current_file->name;
+ else
+ return "<none>";
+}
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
new file mode 100644
index 0000000..79cb983
--- a/dev/null
+++ b/scripts/kconfig/zconf.y
@@ -0,0 +1,651 @@
+%{
+/*
+ * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
+
+#define PRINTD 0x0001
+#define DEBUG_PARSE 0x0002
+
+int cdebug = PRINTD;
+
+extern int zconflex(void);
+static void zconfprint(const char *err, ...);
+static void zconferror(const char *err);
+static bool zconf_endtoken(int token, int starttoken, int endtoken);
+
+struct symbol *symbol_hash[257];
+
+#define YYERROR_VERBOSE
+%}
+%expect 36
+
+%union
+{
+ int token;
+ char *string;
+ struct symbol *symbol;
+ struct expr *expr;
+ struct menu *menu;
+}
+
+%token T_MAINMENU
+%token T_MENU
+%token T_ENDMENU
+%token T_SOURCE
+%token T_CHOICE
+%token T_ENDCHOICE
+%token T_COMMENT
+%token T_CONFIG
+%token T_HELP
+%token <string> T_HELPTEXT
+%token T_IF
+%token T_ENDIF
+%token T_DEPENDS
+%token T_REQUIRES
+%token T_OPTIONAL
+%token T_PROMPT
+%token T_DEFAULT
+%token T_TRISTATE
+%token T_BOOLEAN
+%token T_INT
+%token T_HEX
+%token <string> T_WORD
+%token <string> T_STRING
+%token T_UNEQUAL
+%token T_EOF
+%token T_EOL
+%token T_CLOSE_PAREN
+%token T_OPEN_PAREN
+%token T_ON
+
+%left T_OR
+%left T_AND
+%left T_EQUAL T_UNEQUAL
+%nonassoc T_NOT
+
+%type <string> prompt
+%type <string> source
+%type <symbol> symbol
+%type <expr> expr
+%type <expr> if_expr
+%type <token> end
+
+%{
+#define LKC_DIRECT_LINK
+#include "lkc.h"
+%}
+%%
+input: /* empty */
+ | input block
+;
+
+block: common_block
+ | choice_stmt
+ | menu_stmt
+ | T_MAINMENU prompt nl_or_eof
+ | T_ENDMENU { zconfprint("unexpected 'endmenu' statement"); }
+ | T_ENDIF { zconfprint("unexpected 'endif' statement"); }
+ | T_ENDCHOICE { zconfprint("unexpected 'endchoice' statement"); }
+ | error nl_or_eof { zconfprint("syntax error"); yyerrok; }
+;
+
+common_block:
+ if_stmt
+ | comment_stmt
+ | config_stmt
+ | source_stmt
+ | nl_or_eof
+;
+
+
+/* config entry */
+
+config_entry_start: T_CONFIG T_WORD
+{
+ struct symbol *sym = sym_lookup($2, 0);
+ sym->flags |= SYMBOL_OPTIONAL;
+ menu_add_entry(sym);
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+config_stmt: config_entry_start T_EOL config_option_list
+{
+ menu_end_entry();
+ printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
+};
+
+config_option_list:
+ /* empty */
+ | config_option_list config_option T_EOL
+ | config_option_list depends T_EOL
+ | config_option_list help
+ | config_option_list T_EOL
+{ };
+
+config_option: T_TRISTATE prompt_stmt_opt
+{
+ menu_set_type(S_TRISTATE);
+ printd(DEBUG_PARSE, "%s:%d:tristate\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_BOOLEAN prompt_stmt_opt
+{
+ menu_set_type(S_BOOLEAN);
+ printd(DEBUG_PARSE, "%s:%d:boolean\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_INT prompt_stmt_opt
+{
+ menu_set_type(S_INT);
+ printd(DEBUG_PARSE, "%s:%d:int\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_HEX prompt_stmt_opt
+{
+ menu_set_type(S_HEX);
+ printd(DEBUG_PARSE, "%s:%d:hex\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_STRING prompt_stmt_opt
+{
+ menu_set_type(S_STRING);
+ printd(DEBUG_PARSE, "%s:%d:string\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_PROMPT prompt if_expr
+{
+ menu_add_prop(P_PROMPT, $2, NULL, $3);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+config_option: T_DEFAULT symbol if_expr
+{
+ menu_add_prop(P_DEFAULT, NULL, $2, $3);
+ printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+};
+
+/* choice entry */
+
+choice: T_CHOICE
+{
+ struct symbol *sym = sym_lookup(NULL, 0);
+ sym->flags |= SYMBOL_CHOICE;
+ menu_add_entry(sym);
+ menu_add_prop(P_CHOICE, NULL, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
+};
+
+choice_entry: choice T_EOL choice_option_list
+{
+ menu_end_entry();
+ menu_add_menu();
+};
+
+choice_end: end
+{
+ if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+choice_stmt:
+ choice_entry choice_block choice_end T_EOL
+ | choice_entry choice_block
+{
+ printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
+ zconfnerrs++;
+};
+
+choice_option_list:
+ /* empty */
+ | choice_option_list choice_option T_EOL
+ | choice_option_list depends T_EOL
+ | choice_option_list help
+ | choice_option_list T_EOL
+;
+
+choice_option: T_PROMPT prompt if_expr
+{
+ menu_add_prop(P_PROMPT, $2, NULL, $3);
+ printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_OPTIONAL
+{
+ current_entry->sym->flags |= SYMBOL_OPTIONAL;
+ printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
+};
+
+choice_option: T_DEFAULT symbol
+{
+ menu_add_prop(P_DEFAULT, NULL, $2, NULL);
+ //current_choice->prop->def = $2;
+ printd(DEBUG_PARSE, "%s:%d:default\n", zconf_curname(), zconf_lineno());
+};
+
+choice_block:
+ /* empty */
+ | choice_block common_block
+;
+
+/* if entry */
+
+if: T_IF expr
+{
+ printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
+ menu_add_entry(NULL);
+ //current_entry->prompt = menu_add_prop(T_IF, NULL, NULL, $2);
+ menu_add_dep($2);
+ menu_end_entry();
+ menu_add_menu();
+};
+
+if_end: end
+{
+ if (zconf_endtoken($1, T_IF, T_ENDIF)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+if_stmt:
+ if T_EOL if_block if_end T_EOL
+ | if T_EOL if_block
+{
+ printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
+ zconfnerrs++;
+};
+
+if_block:
+ /* empty */
+ | if_block common_block
+ | if_block menu_stmt
+ | if_block choice_stmt
+;
+
+/* menu entry */
+
+menu: T_MENU prompt
+{
+ menu_add_entry(NULL);
+ menu_add_prop(P_MENU, $2, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
+};
+
+menu_entry: menu T_EOL depends_list
+{
+ menu_end_entry();
+ menu_add_menu();
+};
+
+menu_end: end
+{
+ if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
+ menu_end_menu();
+ printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
+ }
+};
+
+menu_stmt:
+ menu_entry menu_block menu_end T_EOL
+ | menu_entry menu_block
+{
+ printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
+ zconfnerrs++;
+};
+
+menu_block:
+ /* empty */
+ | menu_block common_block
+ | menu_block menu_stmt
+ | menu_block choice_stmt
+ | menu_block error T_EOL { zconfprint("invalid menu option"); yyerrok; }
+;
+
+source: T_SOURCE prompt
+{
+ $$ = $2;
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
+};
+
+source_stmt: source T_EOL
+{
+ zconf_nextfile($1);
+};
+
+/* comment entry */
+
+comment: T_COMMENT prompt
+{
+ menu_add_entry(NULL);
+ menu_add_prop(P_COMMENT, $2, NULL, NULL);
+ printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
+};
+
+comment_stmt: comment T_EOL depends_list
+{
+ menu_end_entry();
+};
+
+/* help option */
+
+help_start: T_HELP T_EOL
+{
+ printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
+ zconf_starthelp();
+};
+
+help: help_start T_HELPTEXT
+{
+ current_entry->sym->help = $2;
+};
+
+/* depends option */
+
+depends_list: /* empty */
+ | depends_list depends T_EOL
+ | depends_list T_EOL
+{ };
+
+depends: T_DEPENDS T_ON expr
+{
+ menu_add_dep($3);
+ printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
+}
+ | T_DEPENDS expr
+{
+ menu_add_dep($2);
+ printd(DEBUG_PARSE, "%s:%d:depends\n", zconf_curname(), zconf_lineno());
+}
+ | T_REQUIRES expr
+{
+ menu_add_dep($2);
+ printd(DEBUG_PARSE, "%s:%d:requires\n", zconf_curname(), zconf_lineno());
+};
+
+/* prompt statement */
+
+prompt_stmt_opt:
+ /* empty */
+ | prompt
+{
+ menu_add_prop(P_PROMPT, $1, NULL, NULL);
+}
+ | prompt T_IF expr
+{
+ menu_add_prop(P_PROMPT, $1, NULL, $3);
+};
+
+prompt: T_WORD
+ | T_STRING
+;
+
+end: T_ENDMENU { $$ = T_ENDMENU; }
+ | T_ENDCHOICE { $$ = T_ENDCHOICE; }
+ | T_ENDIF { $$ = T_ENDIF; }
+;
+
+nl_or_eof:
+ T_EOL | T_EOF;
+
+if_expr: /* empty */ { $$ = NULL; }
+ | T_IF expr { $$ = $2; }
+;
+
+expr: symbol { $$ = expr_alloc_symbol($1); }
+ | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
+ | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
+ | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; }
+ | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); }
+ | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); }
+ | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
+;
+
+symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
+ | T_STRING { $$ = sym_lookup($1, 1); free($1); }
+;
+
+%%
+
+void conf_parse(const char *name)
+{
+ zconf_initscan(name);
+
+ sym_init();
+ menu_init();
+ rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL);
+
+ //zconfdebug = 1;
+ zconfparse();
+ if (zconfnerrs)
+ exit(1);
+ menu_finalize(&rootmenu);
+
+ modules_sym = sym_lookup("MODULES", 0);
+
+ sym_change_count = 1;
+}
+
+const char *zconf_tokenname(int token)
+{
+ switch (token) {
+ case T_MENU: return "menu";
+ case T_ENDMENU: return "endmenu";
+ case T_CHOICE: return "choice";
+ case T_ENDCHOICE: return "endchoice";
+ case T_IF: return "if";
+ case T_ENDIF: return "endif";
+ }
+ return "<token>";
+}
+
+static bool zconf_endtoken(int token, int starttoken, int endtoken)
+{
+ if (token != endtoken) {
+ zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ if (current_menu->file != current_file) {
+ zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
+ zconfprint("location of the '%s'", zconf_tokenname(starttoken));
+ zconfnerrs++;
+ return false;
+ }
+ return true;
+}
+
+static void zconfprint(const char *err, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
+ va_start(ap, err);
+ vfprintf(stderr, err, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void zconferror(const char *err)
+{
+ fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno(), err);
+}
+
+void print_quoted_string(FILE *out, const char *str)
+{
+ const char *p;
+ int len;
+
+ putc('"', out);
+ while ((p = strchr(str, '"'))) {
+ len = p - str;
+ if (len)
+ fprintf(out, "%.*s", len, str);
+ fputs("\\\"", out);
+ str = p + 1;
+ }
+ fputs(str, out);
+ putc('"', out);
+}
+
+void print_symbol(FILE *out, struct menu *menu)
+{
+ struct symbol *sym = menu->sym;
+ struct property *prop;
+
+ //sym->flags |= SYMBOL_PRINTED;
+
+ if (sym_is_choice(sym))
+ fprintf(out, "choice\n");
+ else
+ fprintf(out, "config %s\n", sym->name);
+ switch (sym->type) {
+ case S_BOOLEAN:
+ fputs(" boolean\n", out);
+ break;
+ case S_TRISTATE:
+ fputs(" tristate\n", out);
+ break;
+ case S_STRING:
+ fputs(" string\n", out);
+ break;
+ case S_INT:
+ fputs(" integer\n", out);
+ break;
+ case S_HEX:
+ fputs(" hex\n", out);
+ break;
+ default:
+ fputs(" ???\n", out);
+ break;
+ }
+#if 0
+ if (!expr_is_yes(sym->dep)) {
+ fputs(" depends ", out);
+ expr_fprint(sym->dep, out);
+ fputc('\n', out);
+ }
+#endif
+ for (prop = sym->prop; prop; prop = prop->next) {
+ if (prop->menu != menu)
+ continue;
+ switch (prop->type) {
+ case P_PROMPT:
+ fputs(" prompt ", out);
+ print_quoted_string(out, prop->text);
+ if (prop->def) {
+ fputc(' ', out);
+ if (prop->def->flags & SYMBOL_CONST)
+ print_quoted_string(out, prop->def->name);
+ else
+ fputs(prop->def->name, out);
+ }
+ if (!expr_is_yes(E_EXPR(prop->visible))) {
+ fputs(" if ", out);
+ expr_fprint(E_EXPR(prop->visible), out);
+ }
+ fputc('\n', out);
+ break;
+ case P_DEFAULT:
+ fputs( " default ", out);
+ print_quoted_string(out, prop->def->name);
+ if (!expr_is_yes(E_EXPR(prop->visible))) {
+ fputs(" if ", out);
+ expr_fprint(E_EXPR(prop->visible), out);
+ }
+ fputc('\n', out);
+ break;
+ case P_CHOICE:
+ fputs(" #choice value\n", out);
+ break;
+ default:
+ fprintf(out, " unknown prop %d!\n", prop->type);
+ break;
+ }
+ }
+ if (sym->help) {
+ int len = strlen(sym->help);
+ while (sym->help[--len] == '\n')
+ sym->help[len] = 0;
+ fprintf(out, " help\n%s\n", sym->help);
+ }
+ fputc('\n', out);
+}
+
+void zconfdump(FILE *out)
+{
+ //struct file *file;
+ struct property *prop;
+ struct symbol *sym;
+ struct menu *menu;
+
+ menu = rootmenu.list;
+ while (menu) {
+ if ((sym = menu->sym))
+ print_symbol(out, menu);
+ else if ((prop = menu->prompt)) {
+ switch (prop->type) {
+ //case T_MAINMENU:
+ // fputs("\nmainmenu ", out);
+ // print_quoted_string(out, prop->text);
+ // fputs("\n", out);
+ // break;
+ case P_COMMENT:
+ fputs("\ncomment ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ case P_MENU:
+ fputs("\nmenu ", out);
+ print_quoted_string(out, prop->text);
+ fputs("\n", out);
+ break;
+ //case T_SOURCE:
+ // fputs("\nsource ", out);
+ // print_quoted_string(out, prop->text);
+ // fputs("\n", out);
+ // break;
+ //case T_IF:
+ // fputs("\nif\n", out);
+ default:
+ ;
+ }
+ if (!expr_is_yes(E_EXPR(prop->visible))) {
+ fputs(" depends ", out);
+ expr_fprint(E_EXPR(prop->visible), out);
+ fputc('\n', out);
+ }
+ fputs("\n", out);
+ }
+
+ if (menu->list)
+ menu = menu->list;
+ else if (menu->next)
+ menu = menu->next;
+ else while ((menu = menu->parent)) {
+ if (menu->prompt && menu->prompt->type == P_MENU)
+ fputs("\nendmenu\n", out);
+ if (menu->next) {
+ menu = menu->next;
+ break;
+ }
+ }
+ }
+}
+
+#include "lex.zconf.c"
+#include "confdata.c"
+#include "expr.c"
+#include "symbol.c"
+#include "menu.c"
diff --git a/scripts/lxdialog/BIG.FAT.WARNING b/scripts/lxdialog/BIG.FAT.WARNING
new file mode 100644
index 0000000..a8999d8
--- a/dev/null
+++ b/scripts/lxdialog/BIG.FAT.WARNING
@@ -0,0 +1,4 @@
+This is NOT the official version of dialog. This version has been
+significantly modified from the original. It is for use by the Linux
+kernel configuration script. Please do not bother Savio Lam with
+questions about this program.
diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile
new file mode 100644
index 0000000..75b7bac
--- a/dev/null
+++ b/scripts/lxdialog/Makefile
@@ -0,0 +1,44 @@
+HOST_CFLAGS := -DLOCALE
+HOST_LDFLAGS := -lncurses
+
+ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
+ HOST_CFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
+else
+ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
+ HOST_CFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
+else
+ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
+ HOST_CFLAGS += -DCURSES_LOC="<ncurses.h>"
+else
+ HOST_CFLAGS += -DCURSES_LOC="<curses.h>"
+endif
+endif
+endif
+
+host-progs := lxdialog
+
+lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
+ util.o lxdialog.o msgbox.o
+
+EXTRA_TARGETS := lxdialog
+
+first_rule: ncurses
+
+include $(TOPDIR)/Rules.make
+
+.PHONY: ncurses
+
+ncurses:
+ @echo "main() {}" > lxtemp.c
+ @if $(HOSTCC) $(HOST_CFLAGS) lxtemp.c $(HOST_LDFLAGS); then \
+ rm -f lxtemp.c a.out; \
+ else \
+ rm -f lxtemp.c; \
+ echo -e "\007" ;\
+ echo ">> Unable to find the Ncurses libraries." ;\
+ echo ">>" ;\
+ echo ">> You must have Ncurses installed in order" ;\
+ echo ">> to use 'make menuconfig'" ;\
+ echo ;\
+ exit 1 ;\
+ fi
diff --git a/scripts/lxdialog/checklist.c b/scripts/lxdialog/checklist.c
new file mode 100644
index 0000000..4f78688
--- a/dev/null
+++ b/scripts/lxdialog/checklist.c
@@ -0,0 +1,369 @@
+/*
+ * checklist.c -- implements the checklist box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
+ * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static int list_width, check_x, item_x, checkflag;
+
+/*
+ * Print list item
+ */
+static void
+print_item (WINDOW * win, const char *item, int status,
+ int choice, int selected)
+{
+ int i;
+
+ /* Clear 'residue' of last item */
+ wattrset (win, menubox_attr);
+ wmove (win, choice, 0);
+ for (i = 0; i < list_width; i++)
+ waddch (win, ' ');
+
+ wmove (win, choice, check_x);
+ wattrset (win, selected ? check_selected_attr : check_attr);
+ if (checkflag == FLAG_CHECK)
+ wprintw (win, "[%c]", status ? 'X' : ' ');
+ else
+ wprintw (win, "(%c)", status ? 'X' : ' ');
+
+ wattrset (win, selected ? tag_selected_attr : tag_attr);
+ mvwaddch(win, choice, item_x, item[0]);
+ wattrset (win, selected ? item_selected_attr : item_attr);
+ waddstr (win, (char *)item+1);
+ if (selected) {
+ wmove (win, choice, check_x+1);
+ wrefresh (win);
+ }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int choice, int item_no, int scroll,
+ int y, int x, int height)
+{
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset (win, uarrow_attr);
+ waddch (win, ACS_UARROW);
+ waddstr (win, "(-)");
+ }
+ else {
+ wattrset (win, menubox_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+
+ if ((height < item_no) && (scroll + choice < item_no - 1)) {
+ wattrset (win, darrow_attr);
+ waddch (win, ACS_DARROW);
+ waddstr (win, "(+)");
+ }
+ else {
+ wattrset (win, menubox_border_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+}
+
+/*
+ * Display the termination buttons
+ */
+static void
+print_buttons( WINDOW *dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button (dialog, "Select", y, x, selected == 0);
+ print_button (dialog, " Help ", y, x + 14, selected == 1);
+
+ wmove(dialog, y, x+1 + 14*selected);
+ wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ * The `flag' parameter is used to select between radiolist and checklist.
+ */
+int
+dialog_checklist (const char *title, const char *prompt, int height, int width,
+ int list_height, int item_no, const char * const * items, int flag)
+
+{
+ int i, x, y, box_x, box_y;
+ int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
+ WINDOW *dialog, *list;
+
+ checkflag = flag;
+
+ /* Allocate space for storing item on/off status */
+ if ((status = malloc (sizeof (int) * item_no)) == NULL) {
+ endwin ();
+ fprintf (stderr,
+ "\nCan't allocate memory in dialog_checklist().\n");
+ exit (-1);
+ }
+
+ /* Initializes status */
+ for (i = 0; i < item_no; i++) {
+ status[i] = !strcasecmp (items[i * 3 + 2], "on");
+ if (!choice && status[i])
+ choice = i;
+ }
+
+ max_choice = MIN (list_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ list_width = width - 6;
+ box_y = height - list_height - 5;
+ box_x = (width - list_width) / 2 - 1;
+
+ /* create new window for the list */
+ list = subwin (dialog, list_height, list_width, y+box_y+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,
+ menubox_border_attr, menubox_attr);
+
+ /* Find length of longest item in order to center checklist */
+ check_x = 0;
+ for (i = 0; i < item_no; i++)
+ check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4);
+
+ check_x = (list_width - check_x) / 2;
+ item_x = check_x + 4;
+
+ if (choice >= list_height) {
+ scroll = choice - list_height + 1;
+ choice -= scroll;
+ }
+
+ /* Print the list */
+ for (i = 0; i < max_choice; i++) {
+ print_item (list, items[(scroll+i) * 3 + 1],
+ status[i+scroll], i, i == choice);
+ }
+
+ print_arrows(dialog, choice, item_no, scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ print_buttons(dialog, height, width, 0);
+
+ wnoutrefresh (list);
+ wnoutrefresh (dialog);
+ doupdate ();
+
+ while (key != ESC) {
+ key = wgetch (dialog);
+
+ for (i = 0; i < max_choice; i++)
+ if (toupper(key) == toupper(items[(scroll+i)*3+1][0]))
+ break;
+
+
+ if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||
+ key == '+' || key == '-' ) {
+ if (key == KEY_UP || key == '-') {
+ if (!choice) {
+ if (!scroll)
+ continue;
+ /* Scroll list down */
+ if (list_height > 1) {
+ /* De-highlight current first item */
+ print_item (list, items[scroll * 3 + 1],
+ status[scroll], 0, FALSE);
+ scrollok (list, TRUE);
+ wscrl (list, -1);
+ scrollok (list, FALSE);
+ }
+ scroll--;
+ print_item (list, items[scroll * 3 + 1],
+ status[scroll], 0, TRUE);
+ wnoutrefresh (list);
+
+ print_arrows(dialog, choice, item_no, scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ wrefresh (dialog);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice - 1;
+ } else if (key == KEY_DOWN || key == '+') {
+ if (choice == max_choice - 1) {
+ if (scroll + choice >= item_no - 1)
+ continue;
+ /* Scroll list up */
+ if (list_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1],
+ max_choice - 1, FALSE);
+ scrollok (list, TRUE);
+ scroll (list);
+ scrollok (list, FALSE);
+ }
+ scroll++;
+ print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1],
+ max_choice - 1, TRUE);
+ wnoutrefresh (list);
+
+ print_arrows(dialog, choice, item_no, scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ wrefresh (dialog);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice + 1;
+ }
+ if (i != choice) {
+ /* De-highlight current item */
+ print_item (list, items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, FALSE);
+ /* Highlight new item */
+ choice = i;
+ print_item (list, items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, TRUE);
+ wnoutrefresh (list);
+ wrefresh (dialog);
+ }
+ continue; /* wait for another key press */
+ }
+ switch (key) {
+ case 'H':
+ case 'h':
+ case '?':
+ delwin (dialog);
+ free (status);
+ return 1;
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh (dialog);
+ break;
+ case 'S':
+ case 's':
+ case ' ':
+ case '\n':
+ if (!button) {
+ if (flag == FLAG_CHECK) {
+ status[scroll + choice] = !status[scroll + choice];
+ wmove (list, choice, check_x);
+ wattrset (list, check_selected_attr);
+ wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
+ } else {
+ if (!status[scroll + choice]) {
+ for (i = 0; i < item_no; i++)
+ status[i] = 0;
+ status[scroll + choice] = 1;
+ for (i = 0; i < max_choice; i++)
+ print_item (list, items[(scroll + i) * 3 + 1],
+ status[scroll + i], i, i == choice);
+ }
+ }
+ wnoutrefresh (list);
+ wrefresh (dialog);
+
+ for (i = 0; i < item_no; i++) {
+ if (status[i]) {
+ if (flag == FLAG_CHECK) {
+ fprintf (stderr, "\"%s\" ", items[i * 3]);
+ } else {
+ fprintf (stderr, "%s", items[i * 3]);
+ }
+
+ }
+ }
+ }
+ delwin (dialog);
+ free (status);
+ return button;
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+
+ /* Now, update everything... */
+ doupdate ();
+ }
+
+
+ delwin (dialog);
+ free (status);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/colors.h b/scripts/lxdialog/colors.h
new file mode 100644
index 0000000..d34dd37
--- a/dev/null
+++ b/scripts/lxdialog/colors.h
@@ -0,0 +1,161 @@
+/*
+ * colors.h -- color attribute definitions
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * Default color definitions
+ *
+ * *_FG = foreground
+ * *_BG = background
+ * *_HL = highlight?
+ */
+#define SCREEN_FG COLOR_CYAN
+#define SCREEN_BG COLOR_BLUE
+#define SCREEN_HL TRUE
+
+#define SHADOW_FG COLOR_BLACK
+#define SHADOW_BG COLOR_BLACK
+#define SHADOW_HL TRUE
+
+#define DIALOG_FG COLOR_BLACK
+#define DIALOG_BG COLOR_WHITE
+#define DIALOG_HL FALSE
+
+#define TITLE_FG COLOR_YELLOW
+#define TITLE_BG COLOR_WHITE
+#define TITLE_HL TRUE
+
+#define BORDER_FG COLOR_WHITE
+#define BORDER_BG COLOR_WHITE
+#define BORDER_HL TRUE
+
+#define BUTTON_ACTIVE_FG COLOR_WHITE
+#define BUTTON_ACTIVE_BG COLOR_BLUE
+#define BUTTON_ACTIVE_HL TRUE
+
+#define BUTTON_INACTIVE_FG COLOR_BLACK
+#define BUTTON_INACTIVE_BG COLOR_WHITE
+#define BUTTON_INACTIVE_HL FALSE
+
+#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
+#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
+#define BUTTON_KEY_ACTIVE_HL TRUE
+
+#define BUTTON_KEY_INACTIVE_FG COLOR_RED
+#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
+#define BUTTON_KEY_INACTIVE_HL FALSE
+
+#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
+#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
+#define BUTTON_LABEL_ACTIVE_HL TRUE
+
+#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
+#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
+#define BUTTON_LABEL_INACTIVE_HL TRUE
+
+#define INPUTBOX_FG COLOR_BLACK
+#define INPUTBOX_BG COLOR_WHITE
+#define INPUTBOX_HL FALSE
+
+#define INPUTBOX_BORDER_FG COLOR_BLACK
+#define INPUTBOX_BORDER_BG COLOR_WHITE
+#define INPUTBOX_BORDER_HL FALSE
+
+#define SEARCHBOX_FG COLOR_BLACK
+#define SEARCHBOX_BG COLOR_WHITE
+#define SEARCHBOX_HL FALSE
+
+#define SEARCHBOX_TITLE_FG COLOR_YELLOW
+#define SEARCHBOX_TITLE_BG COLOR_WHITE
+#define SEARCHBOX_TITLE_HL TRUE
+
+#define SEARCHBOX_BORDER_FG COLOR_WHITE
+#define SEARCHBOX_BORDER_BG COLOR_WHITE
+#define SEARCHBOX_BORDER_HL TRUE
+
+#define POSITION_INDICATOR_FG COLOR_YELLOW
+#define POSITION_INDICATOR_BG COLOR_WHITE
+#define POSITION_INDICATOR_HL TRUE
+
+#define MENUBOX_FG COLOR_BLACK
+#define MENUBOX_BG COLOR_WHITE
+#define MENUBOX_HL FALSE
+
+#define MENUBOX_BORDER_FG COLOR_WHITE
+#define MENUBOX_BORDER_BG COLOR_WHITE
+#define MENUBOX_BORDER_HL TRUE
+
+#define ITEM_FG COLOR_BLACK
+#define ITEM_BG COLOR_WHITE
+#define ITEM_HL FALSE
+
+#define ITEM_SELECTED_FG COLOR_WHITE
+#define ITEM_SELECTED_BG COLOR_BLUE
+#define ITEM_SELECTED_HL TRUE
+
+#define TAG_FG COLOR_YELLOW
+#define TAG_BG COLOR_WHITE
+#define TAG_HL TRUE
+
+#define TAG_SELECTED_FG COLOR_YELLOW
+#define TAG_SELECTED_BG COLOR_BLUE
+#define TAG_SELECTED_HL TRUE
+
+#define TAG_KEY_FG COLOR_YELLOW
+#define TAG_KEY_BG COLOR_WHITE
+#define TAG_KEY_HL TRUE
+
+#define TAG_KEY_SELECTED_FG COLOR_YELLOW
+#define TAG_KEY_SELECTED_BG COLOR_BLUE
+#define TAG_KEY_SELECTED_HL TRUE
+
+#define CHECK_FG COLOR_BLACK
+#define CHECK_BG COLOR_WHITE
+#define CHECK_HL FALSE
+
+#define CHECK_SELECTED_FG COLOR_WHITE
+#define CHECK_SELECTED_BG COLOR_BLUE
+#define CHECK_SELECTED_HL TRUE
+
+#define UARROW_FG COLOR_GREEN
+#define UARROW_BG COLOR_WHITE
+#define UARROW_HL TRUE
+
+#define DARROW_FG COLOR_GREEN
+#define DARROW_BG COLOR_WHITE
+#define DARROW_HL TRUE
+
+/* End of default color definitions */
+
+#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
+#define COLOR_NAME_LEN 10
+#define COLOR_COUNT 8
+
+/*
+ * Global variables
+ */
+
+typedef struct {
+ char name[COLOR_NAME_LEN];
+ int value;
+} color_names_st;
+
+extern color_names_st color_names[];
+extern int color_table[][3];
diff --git a/scripts/lxdialog/dialog.h b/scripts/lxdialog/dialog.h
new file mode 100644
index 0000000..0e30d00
--- a/dev/null
+++ b/scripts/lxdialog/dialog.h
@@ -0,0 +1,184 @@
+
+/*
+ * dialog.h -- common declarations for all dialog modules
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include CURSES_LOC
+
+/*
+ * Colors in ncurses 1.9.9e do not work properly since foreground and
+ * background colors are OR'd rather than separately masked. This version
+ * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
+ * with standard curses. The simplest fix (to make this work with standard
+ * curses) uses the wbkgdset() function, not used in the original hack.
+ * Turn it off if we're building with 1.9.9e, since it just confuses things.
+ */
+#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
+#define OLD_NCURSES 1
+#undef wbkgdset
+#define wbkgdset(w,p) /*nothing*/
+#else
+#define OLD_NCURSES 0
+#endif
+
+#define TR(params) _tracef params
+
+#define ESC 27
+#define TAB 9
+#define MAX_LEN 2048
+#define BUF_SIZE (10*1024)
+#define MIN(x,y) (x < y ? x : y)
+#define MAX(x,y) (x > y ? x : y)
+
+
+#ifndef ACS_ULCORNER
+#define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#define ACS_URCORNER '+'
+#endif
+#ifndef ACS_LRCORNER
+#define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#define ACS_VLINE '|'
+#endif
+#ifndef ACS_LTEE
+#define ACS_LTEE '+'
+#endif
+#ifndef ACS_RTEE
+#define ACS_RTEE '+'
+#endif
+#ifndef ACS_UARROW
+#define ACS_UARROW '^'
+#endif
+#ifndef ACS_DARROW
+#define ACS_DARROW 'v'
+#endif
+
+/*
+ * Attribute names
+ */
+#define screen_attr attributes[0]
+#define shadow_attr attributes[1]
+#define dialog_attr attributes[2]
+#define title_attr attributes[3]
+#define border_attr attributes[4]
+#define button_active_attr attributes[5]
+#define button_inactive_attr attributes[6]
+#define button_key_active_attr attributes[7]
+#define button_key_inactive_attr attributes[8]
+#define button_label_active_attr attributes[9]
+#define button_label_inactive_attr attributes[10]
+#define inputbox_attr attributes[11]
+#define inputbox_border_attr attributes[12]
+#define searchbox_attr attributes[13]
+#define searchbox_title_attr attributes[14]
+#define searchbox_border_attr attributes[15]
+#define position_indicator_attr attributes[16]
+#define menubox_attr attributes[17]
+#define menubox_border_attr attributes[18]
+#define item_attr attributes[19]
+#define item_selected_attr attributes[20]
+#define tag_attr attributes[21]
+#define tag_selected_attr attributes[22]
+#define tag_key_attr attributes[23]
+#define tag_key_selected_attr attributes[24]
+#define check_attr attributes[25]
+#define check_selected_attr attributes[26]
+#define uarrow_attr attributes[27]
+#define darrow_attr attributes[28]
+
+/* number of attributes */
+#define ATTRIBUTE_COUNT 29
+
+/*
+ * Global variables
+ */
+extern bool use_colors;
+extern bool use_shadow;
+
+extern chtype attributes[];
+
+extern const char *backtitle;
+
+/*
+ * Function prototypes
+ */
+extern void create_rc (const char *filename);
+extern int parse_rc (void);
+
+
+void init_dialog (void);
+void end_dialog (void);
+void attr_clear (WINDOW * win, int height, int width, chtype attr);
+void dialog_clear (void);
+void color_setup (void);
+void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
+void print_button (WINDOW * win, const char *label, int y, int x, int selected);
+void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
+ chtype border);
+void draw_shadow (WINDOW * win, int y, int x, int height, int width);
+
+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);
+int dialog_menu (const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *choice, int item_no,
+ const char * const * items);
+int dialog_checklist (const char *title, const char *prompt, int height,
+ int width, int list_height, int item_no,
+ const char * const * items, int flag);
+extern unsigned char dialog_input_result[];
+int dialog_inputbox (const char *title, const char *prompt, int height,
+ int width, const char *init);
+
+/*
+ * This is the base for fictitious keys, which activate
+ * the buttons.
+ *
+ * Mouse-generated keys are the following:
+ * -- the first 32 are used as numbers, in addition to '0'-'9'
+ * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
+ * -- uppercase chars are used to invoke the button (M_EVENT + 'O')
+ */
+#define M_EVENT (KEY_MAX+1)
+
+
+/*
+ * The `flag' parameter in checklist is used to select between
+ * radiolist and checklist
+ */
+#define FLAG_CHECK 1
+#define FLAG_RADIO 0
diff --git a/scripts/lxdialog/inputbox.c b/scripts/lxdialog/inputbox.c
new file mode 100644
index 0000000..fa7bebc
--- a/dev/null
+++ b/scripts/lxdialog/inputbox.c
@@ -0,0 +1,240 @@
+/*
+ * inputbox.c -- implements the input box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+unsigned char dialog_input_result[MAX_LEN + 1];
+
+/*
+ * Print the termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button (dialog, " Ok ", y, x, selected==0);
+ print_button (dialog, " Help ", y, x + 14, selected==1);
+
+ wmove(dialog, y, x+1+14*selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int
+dialog_inputbox (const char *title, const char *prompt, int height, int width,
+ const char *init)
+{
+ int i, x, y, box_y, box_x, box_width;
+ int input_x = 0, scroll = 0, key = 0, button = -1;
+ unsigned char *instr = dialog_input_result;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ /* Draw the input field box */
+ box_width = width - 6;
+ getyx (dialog, y, x);
+ box_y = y + 2;
+ box_x = (width - box_width) / 2;
+ draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
+ border_attr, dialog_attr);
+
+ print_buttons(dialog, height, width, 0);
+
+ /* Set up the initial value */
+ wmove (dialog, box_y, box_x);
+ wattrset (dialog, inputbox_attr);
+
+ if (!init)
+ instr[0] = '\0';
+ else
+ strcpy (instr, init);
+
+ input_x = strlen (instr);
+
+ if (input_x >= box_width) {
+ scroll = input_x - box_width + 1;
+ input_x = box_width - 1;
+ for (i = 0; i < box_width - 1; i++)
+ waddch (dialog, instr[scroll + i]);
+ } else
+ waddstr (dialog, instr);
+
+ wmove (dialog, box_y, box_x + input_x);
+
+ wrefresh (dialog);
+
+ while (key != ESC) {
+ key = wgetch (dialog);
+
+ if (button == -1) { /* Input box selected */
+ switch (key) {
+ case TAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ break;
+ case KEY_LEFT:
+ continue;
+ case KEY_RIGHT:
+ continue;
+ case KEY_BACKSPACE:
+ case 127:
+ if (input_x || scroll) {
+ wattrset (dialog, inputbox_attr);
+ 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;
+ } else
+ input_x--;
+ instr[scroll + input_x] = '\0';
+ mvwaddch (dialog, box_y, input_x + box_x, ' ');
+ wmove (dialog, box_y, input_x + box_x);
+ wrefresh (dialog);
+ }
+ continue;
+ default:
+ if (key < 0x100 && isprint (key)) {
+ if (scroll + input_x < MAX_LEN) {
+ wattrset (dialog, inputbox_attr);
+ instr[scroll + input_x] = key;
+ instr[scroll + input_x + 1] = '\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]);
+ } else {
+ wmove (dialog, box_y, input_x++ + box_x);
+ waddch (dialog, key);
+ }
+ wrefresh (dialog);
+ } else
+ flash (); /* Alarm user about overflow */
+ continue;
+ }
+ }
+ }
+ switch (key) {
+ case 'O':
+ case 'o':
+ delwin (dialog);
+ return 0;
+ case 'H':
+ case 'h':
+ delwin (dialog);
+ return 1;
+ case KEY_UP:
+ case KEY_LEFT:
+ switch (button) {
+ case -1:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 0:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove (dialog, box_y, box_x + input_x);
+ wrefresh (dialog);
+ break;
+ case 1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ }
+ break;
+ case TAB:
+ case KEY_DOWN:
+ case KEY_RIGHT:
+ switch (button) {
+ case -1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ case 0:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 1:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove (dialog, box_y, box_x + input_x);
+ wrefresh (dialog);
+ break;
+ }
+ break;
+ case ' ':
+ case '\n':
+ delwin (dialog);
+ return (button == -1 ? 0 : button);
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/lxdialog b/scripts/lxdialog/lxdialog
new file mode 100755
index 0000000..f0dca91
--- a/dev/null
+++ b/scripts/lxdialog/lxdialog
Binary files differ
diff --git a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c
new file mode 100644
index 0000000..6f4c1fd
--- a/dev/null
+++ b/scripts/lxdialog/lxdialog.c
@@ -0,0 +1,226 @@
+/*
+ * dialog - Display simple dialog boxes from shell scripts
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void Usage (const char *name);
+
+typedef int (jumperFn) (const char *title, int argc, const char * const * argv);
+
+struct Mode {
+ char *name;
+ int argmin, argmax, argmod;
+ jumperFn *jumper;
+};
+
+jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox;
+jumperFn j_msgbox, j_infobox;
+
+static struct Mode modes[] =
+{
+ {"--menu", 9, 0, 3, j_menu},
+ {"--checklist", 9, 0, 3, j_checklist},
+ {"--radiolist", 9, 0, 3, j_radiolist},
+ {"--yesno", 5,5,1, j_yesno},
+ {"--textbox", 5,5,1, j_textbox},
+ {"--inputbox", 5, 6, 1, j_inputbox},
+ {"--msgbox", 5, 5, 1, j_msgbox},
+ {"--infobox", 5, 5, 1, j_infobox},
+ {NULL, 0, 0, 0, NULL}
+};
+
+static struct Mode *modePtr;
+
+#ifdef LOCALE
+#include <locale.h>
+#endif
+
+int
+main (int argc, const char * const * argv)
+{
+ int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
+ const char *title = NULL;
+
+#ifdef LOCALE
+ (void) setlocale (LC_ALL, "");
+#endif
+
+#ifdef TRACE
+ trace(TRACE_CALLS|TRACE_UPDATE);
+#endif
+ if (argc < 2) {
+ Usage (argv[0]);
+ exit (-1);
+ }
+
+ while (offset < argc - 1 && !end_common_opts) { /* Common options */
+ if (!strcmp (argv[offset + 1], "--title")) {
+ if (argc - offset < 3 || title != NULL) {
+ Usage (argv[0]);
+ exit (-1);
+ } else {
+ title = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp (argv[offset + 1], "--backtitle")) {
+ if (backtitle != NULL) {
+ Usage (argv[0]);
+ exit (-1);
+ } else {
+ backtitle = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp (argv[offset + 1], "--clear")) {
+ if (clear_screen) { /* Hey, "--clear" can't appear twice! */
+ Usage (argv[0]);
+ exit (-1);
+ } else if (argc == 2) { /* we only want to clear the screen */
+ init_dialog ();
+ refresh (); /* init_dialog() will clear the screen for us */
+ end_dialog ();
+ return 0;
+ } else {
+ clear_screen = 1;
+ offset++;
+ }
+ } else /* no more common options */
+ end_common_opts = 1;
+ }
+
+ if (argc - 1 == offset) { /* no more options */
+ Usage (argv[0]);
+ exit (-1);
+ }
+ /* use a table to look for the requested mode, to avoid code duplication */
+
+ for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
+ if (!strcmp (argv[offset + 1], modePtr->name))
+ break;
+
+ if (!modePtr->name)
+ Usage (argv[0]);
+ if (argc - offset < modePtr->argmin)
+ Usage (argv[0]);
+ if (modePtr->argmax && argc - offset > modePtr->argmax)
+ Usage (argv[0]);
+
+
+
+ init_dialog ();
+ retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
+
+ if (clear_screen) { /* clear screen before exit */
+ attr_clear (stdscr, LINES, COLS, screen_attr);
+ refresh ();
+ }
+ end_dialog();
+
+ exit (retval);
+}
+
+/*
+ * Print program usage
+ */
+static void
+Usage (const char *name)
+{
+ fprintf (stderr, "\
+\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
+\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
+\n modified/gutted for use as a Linux kernel config tool by \
+\n William Roadcap (roadcapw@cfw.com)\
+\n\
+\n* Display dialog boxes from shell scripts *\
+\n\
+\nUsage: %s --clear\
+\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
+\n\
+\nBox options:\
+\n\
+\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
+\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --textbox <file> <height> <width>\
+\n --inputbox <text> <height> <width> [<init>]\
+\n --yesno <text> <height> <width>\
+\n", name, name);
+ exit (-1);
+}
+
+/*
+ * These are the program jumpers
+ */
+
+int
+j_menu (const char *t, int ac, const char * const * av)
+{
+ return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), av[6], (ac - 6) / 2, av + 7);
+}
+
+int
+j_checklist (const char *t, int ac, const char * const * av)
+{
+ return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK);
+}
+
+int
+j_radiolist (const char *t, int ac, const char * const * av)
+{
+ return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO);
+}
+
+int
+j_textbox (const char *t, int ac, const char * const * av)
+{
+ return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4]));
+}
+
+int
+j_yesno (const char *t, int ac, const char * const * av)
+{
+ return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4]));
+}
+
+int
+j_inputbox (const char *t, int ac, const char * const * av)
+{
+ int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]),
+ ac == 6 ? av[5] : (char *) NULL);
+ if (ret == 0)
+ fprintf(stderr, dialog_input_result);
+ return ret;
+}
+
+int
+j_msgbox (const char *t, int ac, const char * const * av)
+{
+ return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1);
+}
+
+int
+j_infobox (const char *t, int ac, const char * const * av)
+{
+ return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0);
+}
+
diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c
new file mode 100644
index 0000000..a234e9f
--- a/dev/null
+++ b/scripts/lxdialog/menubox.c
@@ -0,0 +1,443 @@
+/*
+ * menubox.c -- implements the menu box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Changes by Clifford Wolf (god@clifford.at)
+ *
+ * [ 1998-06-13 ]
+ *
+ * *) A bugfix for the Page-Down problem
+ *
+ * *) 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).
+ *
+ * *) Formerly if I selected something my scrolling would be broken because
+ * lxdialog is re-invoked by the Menuconfig shell script, can't
+ * remember the last scrolling position, and just sets it so that the
+ * cursor is at the bottom of the box. Now it writes the temporary file
+ * lxdialog.scrltmp which contains this information. The file is
+ * deleted by lxdialog if the user leaves a submenu or enters a new
+ * one, but it would be nice if Menuconfig could make another "rm -f"
+ * just to be sure. Just try it out - you will recognise a difference!
+ *
+ * [ 1998-06-14 ]
+ *
+ * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
+ * and menus change their size on the fly.
+ *
+ * *) If for some reason the last scrolling position is not saved by
+ * lxdialog, it sets the scrolling so that the selected item is in the
+ * middle of the menu box, not at the bottom.
+ *
+ * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
+ * fscanf would read in 'scroll', and eventually that value would get used.
+ */
+
+#include "dialog.h"
+
+static int menu_width, item_x;
+
+/*
+ * Print menu item
+ */
+static void
+print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
+{
+ int j;
+ char menu_item[menu_width+1];
+
+ strncpy(menu_item, item, menu_width);
+ menu_item[menu_width] = 0;
+ j = first_alpha(menu_item, "YyNnMm");
+
+ /* Clear 'residue' of last item */
+ wattrset (win, menubox_attr);
+ wmove (win, choice, 0);
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < menu_width; i++)
+ waddch (win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+ wattrset (win, selected ? item_selected_attr : item_attr);
+ mvwaddstr (win, choice, item_x, menu_item);
+ if (hotkey) {
+ wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
+ mvwaddch(win, choice, item_x+j, menu_item[j]);
+ }
+ if (selected) {
+ wmove (win, choice, item_x+1);
+ wrefresh (win);
+ }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int item_no, int scroll,
+ int y, int x, int height)
+{
+ int cur_y, cur_x;
+
+ getyx(win, cur_y, cur_x);
+
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset (win, uarrow_attr);
+ waddch (win, ACS_UARROW);
+ waddstr (win, "(-)");
+ }
+ else {
+ wattrset (win, menubox_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+
+ if ((height < item_no) && (scroll + height < item_no)) {
+ wattrset (win, darrow_attr);
+ waddch (win, ACS_DARROW);
+ waddstr (win, "(+)");
+ }
+ else {
+ wattrset (win, menubox_border_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+
+ wmove(win, cur_y, cur_x);
+}
+
+/*
+ * Display the termination buttons.
+ */
+static void
+print_buttons (WINDOW *win, int height, int width, int selected)
+{
+ int x = width / 2 - 16;
+ int y = height - 2;
+
+ print_button (win, "Select", y, x, selected == 0);
+ print_button (win, " Exit ", y, x + 12, selected == 1);
+ print_button (win, " Help ", y, x + 24, selected == 2);
+
+ wmove(win, y, x+1+12*selected);
+ wrefresh (win);
+}
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int
+dialog_menu (const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *current, int item_no,
+ const char * const * items)
+
+{
+ int i, j, x, y, box_x, box_y;
+ int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
+ WINDOW *dialog, *menu;
+ FILE *f;
+
+ max_choice = MIN (menu_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ wbkgdset (dialog, dialog_attr & A_COLOR);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ menu_width = width - 6;
+ box_y = height - menu_height - 5;
+ box_x = (width - menu_width) / 2 - 1;
+
+ /* create new window for the menu */
+ menu = subwin (dialog, menu_height, menu_width,
+ y + box_y + 1, x + box_x + 1);
+ keypad (menu, TRUE);
+
+ /* draw a box around the menu items */
+ draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /*
+ * Find length of longest item in order to center menu.
+ * Set 'choice' to default item.
+ */
+ item_x = 0;
+ for (i = 0; i < item_no; i++) {
+ item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2));
+ if (strcmp(current, items[i*2]) == 0) choice = i;
+ }
+
+ item_x = (menu_width - item_x) / 2;
+
+ /* get the scroll info from the temp file */
+ if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
+ if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
+ (scroll+max_choice > choice) && (scroll >= 0) &&
+ (scroll+max_choice <= item_no) ) {
+ first_item = scroll;
+ choice = choice - scroll;
+ fclose(f);
+ } else {
+ scroll=0;
+ remove("lxdialog.scrltmp");
+ fclose(f);
+ f=NULL;
+ }
+ }
+ if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
+ if (choice >= item_no-max_choice/2)
+ scroll = first_item = item_no-max_choice;
+ else
+ scroll = first_item = choice - max_choice/2;
+ choice = choice - scroll;
+ }
+
+ /* Print the menu */
+ for (i=0; i < max_choice; i++) {
+ print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice,
+ (items[(first_item + i)*2][0] != ':'));
+ }
+
+ wnoutrefresh (menu);
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x+item_x+1, menu_height);
+
+ print_buttons (dialog, height, width, 0);
+ wmove (menu, choice, item_x+1);
+ wrefresh (menu);
+
+ while (key != ESC) {
+ key = wgetch(menu);
+
+ if (key < 256 && isalpha(key)) key = tolower(key);
+
+ if (strchr("ynm", key))
+ i = max_choice;
+ else {
+ for (i = choice+1; i < max_choice; i++) {
+ j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
+ if (key == tolower(items[(scroll+i)*2+1][j]))
+ break;
+ }
+ if (i == max_choice)
+ for (i = 0; i < max_choice; i++) {
+ j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
+ if (key == tolower(items[(scroll+i)*2+1][j]))
+ break;
+ }
+ }
+
+ if (i < max_choice ||
+ key == KEY_UP || key == KEY_DOWN ||
+ key == '-' || key == '+' ||
+ key == KEY_PPAGE || key == KEY_NPAGE) {
+
+ print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
+ (items[(scroll+choice)*2][0] != ':'));
+
+ if (key == KEY_UP || key == '-') {
+ if (choice < 2 && scroll) {
+ /* Scroll menu down */
+ scrollok (menu, TRUE);
+ wscrl (menu, -1);
+ scrollok (menu, FALSE);
+
+ scroll--;
+
+ print_item (menu, items[scroll * 2 + 1], 0, FALSE,
+ (items[scroll*2][0] != ':'));
+ } else
+ choice = MAX(choice - 1, 0);
+
+ } else if (key == KEY_DOWN || key == '+') {
+
+ print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
+ (items[(scroll+choice)*2][0] != ':'));
+
+ if ((choice > max_choice-3) &&
+ (scroll + max_choice < item_no)
+ ) {
+ /* Scroll menu up */
+ scrollok (menu, TRUE);
+ scroll (menu);
+ scrollok (menu, FALSE);
+
+ scroll++;
+
+ print_item (menu, items[(scroll+max_choice-1)*2+1],
+ max_choice-1, FALSE,
+ (items[(scroll+max_choice-1)*2][0] != ':'));
+ } else
+ choice = MIN(choice+1, max_choice-1);
+
+ } else if (key == KEY_PPAGE) {
+ scrollok (menu, TRUE);
+ for (i=0; (i < max_choice); i++) {
+ if (scroll > 0) {
+ wscrl (menu, -1);
+ scroll--;
+ print_item (menu, items[scroll * 2 + 1], 0, FALSE,
+ (items[scroll*2][0] != ':'));
+ } else {
+ if (choice > 0)
+ choice--;
+ }
+ }
+ scrollok (menu, FALSE);
+
+ } else if (key == KEY_NPAGE) {
+ for (i=0; (i < max_choice); i++) {
+ if (scroll+max_choice < item_no) {
+ scrollok (menu, TRUE);
+ scroll(menu);
+ scrollok (menu, FALSE);
+ scroll++;
+ print_item (menu, items[(scroll+max_choice-1)*2+1],
+ max_choice-1, FALSE,
+ (items[(scroll+max_choice-1)*2][0] != ':'));
+ } else {
+ if (choice+1 < max_choice)
+ choice++;
+ }
+ }
+
+ } else
+ choice = i;
+
+ print_item (menu, items[(scroll+choice)*2+1], choice, TRUE,
+ (items[(scroll+choice)*2][0] != ':'));
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x+item_x+1, menu_height);
+
+ wnoutrefresh (dialog);
+ wrefresh (menu);
+
+ continue; /* wait for another key press */
+ }
+
+ switch (key) {
+ case KEY_LEFT:
+ case TAB:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 2 : (button > 2 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh (menu);
+ break;
+ case ' ':
+ case 's':
+ case 'y':
+ case 'n':
+ case 'm':
+ /* save scroll info */
+ if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
+ fprintf(f,"%d\n",scroll);
+ fclose(f);
+ }
+ delwin (dialog);
+ fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+ switch (key) {
+ case 's': return 3;
+ case 'y': return 3;
+ case 'n': return 4;
+ case 'm': return 5;
+ case ' ': return 6;
+ }
+ return 0;
+ case 'h':
+ case '?':
+ button = 2;
+ case '\n':
+ delwin (dialog);
+ if (button == 2)
+ fprintf(stderr, "%s \"%s\"\n",
+ items[(scroll + choice) * 2],
+ items[(scroll + choice) * 2 + 1] +
+ first_alpha(items[(scroll + choice) * 2 + 1],""));
+ else
+ fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+
+ remove("lxdialog.scrltmp");
+ return button;
+ case 'e':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ remove("lxdialog.scrltmp");
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/msgbox.c b/scripts/lxdialog/msgbox.c
new file mode 100644
index 0000000..93692e1
--- a/dev/null
+++ b/scripts/lxdialog/msgbox.c
@@ -0,0 +1,85 @@
+/*
+ * msgbox.c -- implements the message box and info box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display a message box. Program will pause and display an "OK" button
+ * if the parameter 'pause' is non-zero.
+ */
+int
+dialog_msgbox (const char *title, const char *prompt, int height, int width,
+ int pause)
+{
+ int i, x, y, key = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 2);
+
+ if (pause) {
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ print_button (dialog, " Ok ",
+ height - 2, width / 2 - 4, TRUE);
+
+ wrefresh (dialog);
+ while (key != ESC && key != '\n' && key != ' ' &&
+ key != 'O' && key != 'o' && key != 'X' && key != 'x')
+ key = wgetch (dialog);
+ } else {
+ key = '\n';
+ wrefresh (dialog);
+ }
+
+ delwin (dialog);
+ return key == ESC ? -1 : 0;
+}
diff --git a/scripts/lxdialog/textbox.c b/scripts/lxdialog/textbox.c
new file mode 100644
index 0000000..ecf5541
--- a/dev/null
+++ b/scripts/lxdialog/textbox.c
@@ -0,0 +1,556 @@
+/*
+ * textbox.c -- implements the text box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#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 char *get_line (void);
+static void print_position (WINDOW * win, int height, int width);
+
+static int hscroll = 0, fd, file_size, bytes_read;
+static int begin_reached = 1, end_reached = 0, page_length;
+static char *buf, *page;
+
+/*
+ * Display text from a file in a dialog box.
+ */
+int
+dialog_textbox (const char *title, const char *file, int height, int width)
+{
+ int i, x, y, cur_x, cur_y, fpos, key = 0;
+ int passed_end;
+ char search_term[MAX_LEN + 1];
+ WINDOW *dialog, *text;
+
+ search_term[0] = '\0'; /* no search term entered yet */
+
+ /* Open input file for reading */
+ if ((fd = open (file, O_RDONLY)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nCan't open input file in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Get file size. Actually, 'file_size' is the real file size - 1,
+ since it's only the last byte offset from the beginning */
+ if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Restore file pointer to beginning of file after getting file size */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Allocate space for read buffer */
+ if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
+ endwin ();
+ fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0'; /* mark end of valid data */
+ page = buf; /* page is pointer to start of page to be displayed */
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ /* Create window for text region, used for scrolling text */
+ text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
+ wattrset (text, dialog_attr);
+ wbkgdset (text, dialog_attr & A_COLOR);
+
+ keypad (text, TRUE);
+
+ /* register the new window, along with its borders */
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ wbkgdset (dialog, dialog_attr & A_COLOR);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+ print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
+ wnoutrefresh (dialog);
+ getyx (dialog, cur_y, cur_x); /* Save cursor position */
+
+ /* Print first page of text */
+ attr_clear (text, height - 4, width - 2, dialog_attr);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+
+ while ((key != ESC) && (key != '\n')) {
+ key = wgetch (dialog);
+ switch (key) {
+ case 'E': /* Exit */
+ case 'e':
+ case 'X':
+ case 'x':
+ delwin (dialog);
+ free (buf);
+ close (fd);
+ return 0;
+ case 'g': /* First page */
+ case KEY_HOME:
+ if (!begin_reached) {
+ begin_reached = 1;
+ /* First page not in buffer? */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) { /* Yes, we have to read it in */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf;
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case 'G': /* Last page */
+ case KEY_END:
+
+ end_reached = 1;
+ /* Last page not in buffer? */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if (fpos < file_size) { /* Yes, we have to read it in */
+ if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf + bytes_read;
+ back_lines (height - 4);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ 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 (text, TRUE);
+ wscrl (text, -1); /* Scroll text region down one line */
+ scrollok (text, FALSE);
+ page_length = 0;
+ passed_end = 0;
+ for (i = 0; i < height - 4; i++) {
+ if (!i) {
+ /* print first line of page */
+ print_line (text, 0, width - 2);
+ wnoutrefresh (text);
+ } else
+ /* Called to update 'end_reached' and 'page' */
+ get_line ();
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case 'B': /* Previous page */
+ case 'b':
+ case KEY_PPAGE:
+ if (begin_reached)
+ break;
+ back_lines (page_length + height - 4);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case 'J': /* Next line */
+ case 'j':
+ case KEY_DOWN:
+ if (!end_reached) {
+ begin_reached = 0;
+ scrollok (text, TRUE);
+ scroll (text); /* Scroll text region up one line */
+ scrollok (text, FALSE);
+ print_line (text, height - 5, width - 2);
+ wnoutrefresh (text);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case KEY_NPAGE: /* Next page */
+ case ' ':
+ if (end_reached)
+ break;
+
+ begin_reached = 0;
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case '0': /* Beginning of line */
+ case 'H': /* Scroll left */
+ case 'h':
+ case KEY_LEFT:
+ if (hscroll <= 0)
+ break;
+
+ if (key == '0')
+ hscroll = 0;
+ else
+ hscroll--;
+ /* Reprint current page to scroll horizontally */
+ back_lines (page_length);
+ print_page (text, height - 4, width - 2);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case 'L': /* Scroll right */
+ case 'l':
+ case KEY_RIGHT:
+ if (hscroll >= MAX_LEN)
+ break;
+ hscroll++;
+ /* Reprint current page to scroll horizontally */
+ back_lines (page_length);
+ print_page (text, height - 4, width - 2);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ free (buf);
+ close (fd);
+ return -1; /* ESC pressed */
+}
+
+/*
+ * Go back 'n' lines in text file. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void
+back_lines (int n)
+{
+ int i, fpos;
+
+ begin_reached = 0;
+ /* We have to distinguish between end_reached and !end_reached
+ since at end of file, the line is not ended by a '\n'.
+ The code inside 'if' basically does a '--page' to move one
+ character backward so as to skip '\n' of the previous line */
+ if (!end_reached) {
+ /* Either beginning of buffer or beginning of file reached? */
+ if (page == buf) {
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) { /* Not beginning of file yet */
+ /* We've reached beginning of buffer, but not beginning of
+ file yet, so read previous part of file into buffer.
+ Note that we only move backward for BUF_SIZE/2 bytes,
+ but not BUF_SIZE bytes to avoid re-reading again in
+ print_page() later */
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
+ == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in back_lines().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ if (*(--page) != '\n') { /* '--page' here */
+ /* Something's wrong... */
+ endwin ();
+ fprintf (stderr, "\nInternal error in back_lines().\n");
+ exit (-1);
+ }
+ }
+ /* Go back 'n' lines */
+ for (i = 0; i < n; i++)
+ do {
+ if (page == buf) {
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in back_lines().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) {
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
+ SEEK_CUR) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer"
+ " in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ } while (*(--page) != '\n');
+ page++;
+}
+
+/*
+ * Print a new page of text. Called by dialog_textbox().
+ */
+static void
+print_page (WINDOW * win, int height, int width)
+{
+ int i, passed_end = 0;
+
+ page_length = 0;
+ for (i = 0; i < height; i++) {
+ print_line (win, i, width);
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+ wnoutrefresh (win);
+}
+
+/*
+ * Print a new line of text. Called by dialog_textbox() and print_page().
+ */
+static void
+print_line (WINDOW * win, int row, int width)
+{
+ int y, x;
+ char *line;
+
+ line = get_line ();
+ line += MIN (strlen (line), hscroll); /* Scroll horizontally */
+ wmove (win, row, 0); /* move cursor to correct line */
+ waddch (win, ' ');
+ waddnstr (win, line, MIN (strlen (line), width - 2));
+
+ getyx (win, y, x);
+ /* Clear 'residue' of previous line */
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < width - x; i++)
+ waddch (win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *
+get_line (void)
+{
+ int i = 0, fpos;
+ static char line[MAX_LEN + 1];
+
+ end_reached = 0;
+ while (*page != '\n') {
+ if (*page == '\0') {
+ /* Either end of file or end of buffer reached */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "get_line().\n");
+ exit (-1);
+ }
+ if (fpos < file_size) { /* Not end of file yet */
+ /* We've reached end of buffer, but not end of file yet,
+ so read next part of file into buffer */
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in get_line().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ page = buf;
+ } else {
+ if (!end_reached)
+ end_reached = 1;
+ break;
+ }
+ } else if (i < MAX_LEN)
+ line[i++] = *(page++);
+ else {
+ /* Truncate lines longer than MAX_LEN characters */
+ if (i == MAX_LEN)
+ line[i++] = '\0';
+ page++;
+ }
+ }
+ if (i <= MAX_LEN)
+ line[i] = '\0';
+ if (!end_reached)
+ page++; /* move pass '\n' */
+
+ return line;
+}
+
+/*
+ * Print current position
+ */
+static void
+print_position (WINDOW * win, int height, int width)
+{
+ int fpos, percent;
+
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in print_position().\n");
+ exit (-1);
+ }
+ wattrset (win, position_indicator_attr);
+ wbkgdset (win, position_indicator_attr & A_COLOR);
+ percent = !file_size ?
+ 100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
+ wmove (win, height - 3, width - 9);
+ wprintw (win, "(%3d%%)", percent);
+}
diff --git a/scripts/lxdialog/util.c b/scripts/lxdialog/util.c
new file mode 100644
index 0000000..b3a7af9
--- a/dev/null
+++ b/scripts/lxdialog/util.c
@@ -0,0 +1,359 @@
+/*
+ * util.c
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+
+/* use colors by default? */
+bool use_colors = 1;
+
+const char *backtitle = NULL;
+
+const char *dialog_result;
+
+/*
+ * Attribute values, default is for mono display
+ */
+chtype attributes[] =
+{
+ A_NORMAL, /* screen_attr */
+ A_NORMAL, /* shadow_attr */
+ A_NORMAL, /* dialog_attr */
+ A_BOLD, /* title_attr */
+ A_NORMAL, /* border_attr */
+ A_REVERSE, /* button_active_attr */
+ A_DIM, /* button_inactive_attr */
+ A_REVERSE, /* button_key_active_attr */
+ A_BOLD, /* button_key_inactive_attr */
+ A_REVERSE, /* button_label_active_attr */
+ A_NORMAL, /* button_label_inactive_attr */
+ A_NORMAL, /* inputbox_attr */
+ A_NORMAL, /* inputbox_border_attr */
+ A_NORMAL, /* searchbox_attr */
+ A_BOLD, /* searchbox_title_attr */
+ A_NORMAL, /* searchbox_border_attr */
+ A_BOLD, /* position_indicator_attr */
+ A_NORMAL, /* menubox_attr */
+ A_NORMAL, /* menubox_border_attr */
+ A_NORMAL, /* item_attr */
+ A_REVERSE, /* item_selected_attr */
+ A_BOLD, /* tag_attr */
+ A_REVERSE, /* tag_selected_attr */
+ A_BOLD, /* tag_key_attr */
+ A_REVERSE, /* tag_key_selected_attr */
+ A_BOLD, /* check_attr */
+ A_REVERSE, /* check_selected_attr */
+ A_BOLD, /* uarrow_attr */
+ A_BOLD /* darrow_attr */
+};
+
+
+#include "colors.h"
+
+/*
+ * Table of color values
+ */
+int color_table[][3] =
+{
+ {SCREEN_FG, SCREEN_BG, SCREEN_HL},
+ {SHADOW_FG, SHADOW_BG, SHADOW_HL},
+ {DIALOG_FG, DIALOG_BG, DIALOG_HL},
+ {TITLE_FG, TITLE_BG, TITLE_HL},
+ {BORDER_FG, BORDER_BG, BORDER_HL},
+ {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
+ {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
+ {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
+ {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
+ {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
+ {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
+ BUTTON_LABEL_INACTIVE_HL},
+ {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
+ {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
+ {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
+ {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
+ {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
+ {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
+ {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
+ {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
+ {ITEM_FG, ITEM_BG, ITEM_HL},
+ {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
+ {TAG_FG, TAG_BG, TAG_HL},
+ {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
+ {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
+ {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
+ {CHECK_FG, CHECK_BG, CHECK_HL},
+ {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
+ {UARROW_FG, UARROW_BG, UARROW_HL},
+ {DARROW_FG, DARROW_BG, DARROW_HL},
+}; /* color_table */
+
+/*
+ * Set window to attribute 'attr'
+ */
+void
+attr_clear (WINDOW * win, int height, int width, chtype attr)
+{
+ int i, j;
+
+ wattrset (win, attr);
+ for (i = 0; i < height; i++) {
+ wmove (win, i, 0);
+ for (j = 0; j < width; j++)
+ waddch (win, ' ');
+ }
+ touchwin (win);
+}
+
+void dialog_clear (void)
+{
+ attr_clear (stdscr, LINES, COLS, screen_attr);
+ /* Display background title if it exists ... - SLH */
+ if (backtitle != NULL) {
+ int i;
+
+ wattrset (stdscr, screen_attr);
+ mvwaddstr (stdscr, 0, 1, (char *)backtitle);
+ wmove (stdscr, 1, 1);
+ for (i = 1; i < COLS - 1; i++)
+ waddch (stdscr, ACS_HLINE);
+ }
+ wnoutrefresh (stdscr);
+}
+
+/*
+ * Do some initialization for dialog
+ */
+void
+init_dialog (void)
+{
+ initscr (); /* Init curses */
+ keypad (stdscr, TRUE);
+ cbreak ();
+ noecho ();
+
+
+ if (use_colors) /* Set up colors */
+ color_setup ();
+
+
+ dialog_clear ();
+}
+
+/*
+ * Setup for color display
+ */
+void
+color_setup (void)
+{
+ int i;
+
+ if (has_colors ()) { /* Terminal supports color? */
+ start_color ();
+
+ /* Initialize color pairs */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ init_pair (i + 1, color_table[i][0], color_table[i][1]);
+
+ /* Setup color attributes */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ attributes[i] = C_ATTR (color_table[i][2], i + 1);
+ }
+}
+
+/*
+ * End using dialog functions.
+ */
+void
+end_dialog (void)
+{
+ endwin ();
+}
+
+
+/*
+ * 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
+ * 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;
+
+ 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);
+ } else {
+ cur_x = x;
+ cur_y = y;
+ newl = 1;
+ word = tempstr;
+ while (word && *word) {
+ sp = index(word, ' ');
+ if (sp)
+ *sp++ = 0;
+
+ /* Wrap to next line if either the word does not fit,
+ or it is the first word of a new sentence, and it is
+ short, and the next word does not fit. */
+ room = width - cur_x;
+ wlen = strlen(word);
+ if (wlen > room ||
+ (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
+ && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
+ cur_y++;
+ cur_x = x;
+ }
+ wmove (win, cur_y, cur_x);
+ waddstr (win, word);
+ getyx (win, cur_y, cur_x);
+ cur_x++;
+ if (sp && *sp == ' ') {
+ cur_x++; /* double space */
+ while (*++sp == ' ');
+ newl = 1;
+ } else
+ newl = 0;
+ word = sp;
+ }
+ }
+}
+
+/*
+ * Print a button
+ */
+void
+print_button (WINDOW * win, const char *label, int y, int x, int selected)
+{
+ int i, temp;
+
+ wmove (win, y, x);
+ wattrset (win, selected ? button_active_attr : button_inactive_attr);
+ waddstr (win, "<");
+ temp = strspn (label, " ");
+ label += temp;
+ wattrset (win, selected ? button_label_active_attr
+ : button_label_inactive_attr);
+ for (i = 0; i < temp; i++)
+ waddch (win, ' ');
+ wattrset (win, selected ? button_key_active_attr
+ : button_key_inactive_attr);
+ waddch (win, label[0]);
+ wattrset (win, selected ? button_label_active_attr
+ : button_label_inactive_attr);
+ waddstr (win, (char *)label + 1);
+ wattrset (win, selected ? button_active_attr : button_inactive_attr);
+ waddstr (win, ">");
+ wmove (win, y, x + temp + 1);
+}
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void
+draw_box (WINDOW * win, int y, int x, int height, int width,
+ chtype box, chtype border)
+{
+ int i, j;
+
+ wattrset (win, 0);
+ for (i = 0; i < height; i++) {
+ wmove (win, y + i, x);
+ for (j = 0; j < width; j++)
+ if (!i && !j)
+ waddch (win, border | ACS_ULCORNER);
+ else if (i == height - 1 && !j)
+ waddch (win, border | ACS_LLCORNER);
+ else if (!i && j == width - 1)
+ waddch (win, box | ACS_URCORNER);
+ else if (i == height - 1 && j == width - 1)
+ waddch (win, box | ACS_LRCORNER);
+ else if (!i)
+ waddch (win, border | ACS_HLINE);
+ else if (i == height - 1)
+ waddch (win, box | ACS_HLINE);
+ else if (!j)
+ waddch (win, border | ACS_VLINE);
+ else if (j == width - 1)
+ waddch (win, box | ACS_VLINE);
+ else
+ waddch (win, box | ' ');
+ }
+}
+
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void
+draw_shadow (WINDOW * win, int y, int x, int height, int width)
+{
+ int i;
+
+ if (has_colors ()) { /* Whether terminal supports color? */
+ wattrset (win, shadow_attr);
+ wmove (win, y + height, x + 2);
+ for (i = 0; i < width; i++)
+ waddch (win, winch (win) & A_CHARTEXT);
+ for (i = y + 1; i < y + height + 1; i++) {
+ wmove (win, i, x + width);
+ waddch (win, winch (win) & A_CHARTEXT);
+ waddch (win, winch (win) & A_CHARTEXT);
+ }
+ wnoutrefresh (win);
+ }
+}
+
+/*
+ * Return the position of the first alphabetic character in a string.
+ */
+int
+first_alpha(const char *string, const char *exempt)
+{
+ int i, in_paren=0, c;
+
+ for (i = 0; i < strlen(string); i++) {
+ c = tolower(string[i]);
+
+ if (strchr("<[(", c)) ++in_paren;
+ if (strchr(">])", c)) --in_paren;
+
+ if ((! in_paren) && isalpha(c) &&
+ strchr(exempt, c) == 0)
+ return i;
+ }
+
+ return 0;
+}
diff --git a/scripts/lxdialog/yesno.c b/scripts/lxdialog/yesno.c
new file mode 100644
index 0000000..11fcc25
--- a/dev/null
+++ b/scripts/lxdialog/yesno.c
@@ -0,0 +1,118 @@
+/*
+ * yesno.c -- implements the yes/no box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 10;
+ int y = height - 2;
+
+ print_button (dialog, " Yes ", y, x, selected == 0);
+ print_button (dialog, " No ", y, x + 13, selected == 1);
+
+ wmove(dialog, y, x+1 + 13*selected );
+ wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int
+dialog_yesno (const char *title, const char *prompt, int height, int width)
+{
+ int i, x, y, key = 0, button = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ print_buttons(dialog, height, width, 0);
+
+ while (key != ESC) {
+ key = wgetch (dialog);
+ switch (key) {
+ case 'Y':
+ case 'y':
+ delwin (dialog);
+ return 0;
+ case 'N':
+ case 'n':
+ delwin (dialog);
+ return 1;
+
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh (dialog);
+ break;
+ case ' ':
+ case '\n':
+ delwin (dialog);
+ return button;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ return -1; /* ESC pressed */
+}