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 = ¤t_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 = ¤t_entry->list; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_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, "<"); + i += 4; + break; + case '>': + res.replace(i, 1, ">"); + i += 4; + break; + case '&': + res.replace(i, 1, "&"); + i += 5; + break; + case '"': + res.replace(i, 1, """); + 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 += " 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 += " 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 += " 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 Binary files differnew file mode 100755 index 0000000..f0dca91 --- a/dev/null +++ b/scripts/lxdialog/lxdialog 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 */ +} |