From d6434e1042f3b0a6dfe1b1f615af369486f9b1fa Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 9 Oct 1999 00:00:47 +0000 Subject: Merge with 2.3.19. --- scripts/Configure | 33 +- scripts/MAKEDEV.ide | 12 + scripts/Menuconfig | 130 ++++++- scripts/checkconfig.pl | 10 +- scripts/header.tk | 147 ++++++-- scripts/lxdialog/Makefile | 7 +- scripts/mkdep.c | 107 ++++-- scripts/tail.tk | 6 +- scripts/tkcond.c | 479 ++++++++++++++++++------ scripts/tkgen.c | 937 ++++++++++++++++++++++++++++++++-------------- scripts/tkparse.c | 282 +++++++++++--- scripts/tkparse.h | 48 ++- scripts/ver_linux | 2 +- 13 files changed, 1664 insertions(+), 536 deletions(-) (limited to 'scripts') diff --git a/scripts/Configure b/scripts/Configure index 80eefc7e1..0f89d25a9 100644 --- a/scripts/Configure +++ b/scripts/Configure @@ -143,6 +143,10 @@ function comment () { # define_bool define value # function define_bool () { + define_tristate $1 $2 +} + +function define_tristate () { case "$2" in "y") echo "$1=y" >>$CONFIG @@ -213,11 +217,11 @@ function tristate () { while :; do readln "$1 ($2) [$defprompt] " "$def" "$old" case "$ans" in - [yY] | [yY]es ) define_bool "$2" "y" + [yY] | [yY]es ) define_tristate "$2" "y" break ;; - [nN] | [nN]o ) define_bool "$2" "n" + [nN] | [nN]o ) define_tristate "$2" "n" break ;; - [mM] ) define_bool "$2" "m" + [mM] ) define_tristate "$2" "m" break ;; * ) help "$2" ;; @@ -246,7 +250,7 @@ function dep_tristate () { while [ $# -gt 0 ]; do case "$1" in n) - define_bool "$var" "n" + define_tristate "$var" "n" return ;; m) @@ -268,9 +272,9 @@ function dep_tristate () { while :; do readln "$ques ($var) [$defprompt] " "$def" "$old" case "$ans" in - [nN] | [nN]o ) define_bool "$var" "n" + [nN] | [nN]o ) define_tristate "$var" "n" break ;; - [mM] ) define_bool "$var" "m" + [mM] ) define_tristate "$var" "m" break ;; [yY] | [yY]es ) echo echo " This answer is not allowed, because it is not consistent with" @@ -290,6 +294,23 @@ function dep_tristate () { fi } +function dep_bool () { + ques=$1 + var=$2 + shift 2 + while [ $# -gt 0 ]; do + case "$1" in + m | n) + define_bool "$var" "n" + return + ;; + esac + shift + done + + bool "$ques" "$var" +} + # # define_int sets the value of a integer argument # diff --git a/scripts/MAKEDEV.ide b/scripts/MAKEDEV.ide index 6476860b7..feecb99bb 100644 --- a/scripts/MAKEDEV.ide +++ b/scripts/MAKEDEV.ide @@ -29,6 +29,18 @@ makedevs hde 33 0 makedevs hdf 33 64 makedevs hdg 34 0 makedevs hdh 34 64 +makedevs hdi 56 0 +makedevs hdj 56 64 +makedevs hdk 57 0 +makedevs hdl 57 64 +makedevs hdm 88 0 +makedevs hdn 88 64 +makedevs hdo 89 0 +makedevs hdp 89 64 +makedevs hdq 90 0 +makedevs hdr 90 64 +makedevs hds 91 0 +makedevs hdt 91 64 for tape in 0 1 2 3 4 5 6 7 do diff --git a/scripts/Menuconfig b/scripts/Menuconfig index a25722756..f7e3ef118 100644 --- a/scripts/Menuconfig +++ b/scripts/Menuconfig @@ -68,6 +68,12 @@ # # 24 January 1999, Michael Elizabeth Chastain, # - Improve the exit message (Jeff Ronne). +# +# 06 July 1999, Andrzej M. Krzysztofowicz, +# - Support for multiple conditions in dep_tristate(). +# - Implemented new functions: define_tristate(), define_int(), define_hex(), +# define_string(), dep_bool(). +# # @@ -132,6 +138,22 @@ function define_bool () { eval $1=$2 } +function define_tristate () { + eval $1=$2 +} + +function define_hex () { + eval $1=$2 +} + +function define_int () { + eval $1=$2 +} + +function define_string () { + eval $1="$2" +} + # # Create a boolean (Yes/No) function for our current menu # which calls our local bool function. @@ -188,13 +210,52 @@ function tristate () { # else in the kernel. # function dep_tristate () { - if [ "$3" = "y" ]; then - tristate "$1" "$2" - else if [ "$3" = "m" ]; then - mod_bool "$1" "$2" + ques="$1" + var="$2" + dep=y + shift 2 + while [ $# -gt 0 ]; do + if [ "$1" = y ]; then + shift + elif [ "$1" = m ]; then + dep=m + shift + else + dep=n + shift $# + fi + done + if [ "$dep" = y ]; then + tristate "$ques" "$var" + elif [ "$dep" = m ]; then + mod_bool "$ques" "$var" else - define_bool "$2" n - fi; fi + define_tristate "$var" n + fi +} + +# +# Same as above, but now only Y and N are allowed as dependency +# (i.e. third and next arguments). +# +function dep_bool () { + ques="$1" + var="$2" + dep=y + shift 2 + while [ $# -gt 0 ]; do + if [ "$1" = y ]; then + shift + else + dep=n + shift $# + fi + done + if [ "$dep" = y ]; then + bool "$ques" "$var" + else + define_bool "$var" n + fi } # @@ -633,12 +694,13 @@ function parser(ifile,menu) { printf("submenu %s MCmenu%s\n", $0, menu_no) >>menu + newmenu = sprintf("MCmenu%d", menu_no); printf( "function MCmenu%s () {\n"\ "default=$1\n"\ "menu_name %s\n",\ - menu_no, $0) >"MCmenu"menu_no + menu_no, $0) >newmenu - parser(ifile, "MCmenu"menu_no) + parser(ifile, newmenu) } else if ($1 ~ "endmenu") { printf("}\n") >>menu @@ -988,13 +1050,37 @@ save_configuration () { function tristate () { set_x_info "$2" "n" - eval define_bool "$2" "$x" + eval define_tristate "$2" "$x" } function dep_tristate () { set_x_info "$2" "n" - if [ "$3" = "m" -a "$x" = "y" ]; then x="m"; fi - define_bool "$2" "$x" + var="$2" + shift 2 + while [ $# -gt 0 ]; do + if [ "$1" = y ]; then + shift + elif [ "$1" = m -a "$x" != n ]; then + x=m; shift + else + x=n; shift $# + fi + done + define_tristate "$var" "$x" + } + + function dep_bool () { + set_x_info "$2" "n" + var="$2" + shift 2 + while [ $# -gt 0 ]; do + if [ "$1" = y ]; then + shift + else + x=n; shift $# + fi + done + define_bool "$var" "$x" } function int () { @@ -1015,7 +1101,29 @@ save_configuration () { echo "#define $2 \"$x\"" >>$CONFIG_H } + function define_hex () { + eval $1="$2" + echo "$1=$2" >>$CONFIG + echo "#define $1 0x${2##*[x,X]}" >>$CONFIG_H + } + + function define_int () { + eval $1="$2" + echo "$1=$2" >>$CONFIG + echo "#define $1 ($2)" >>$CONFIG_H + } + + function define_string () { + eval $1="$2" + echo "$1=\"$2\"" >>$CONFIG + echo "#define $1 \"$2\"" >>$CONFIG_H + } + function define_bool () { + define_tristate "$1" "$2" + } + + function define_tristate () { eval $1="$2" case "$2" in diff --git a/scripts/checkconfig.pl b/scripts/checkconfig.pl index b82aa1a8b..fc352e436 100644 --- a/scripts/checkconfig.pl +++ b/scripts/checkconfig.pl @@ -25,12 +25,12 @@ foreach $file (@ARGV) m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1))); # Pick up definitions. - if ( m/^#/o ) + if ( m/^\s*#/o ) { - $iLinuxConfig = $. if m/^#\s*include\s*/o; - $configList{uc $1} = 1 if m/^#\s*include\s*/o; - $configList{$1} = 1 if m/^#\s*define\s+CONFIG_(\w*)/o; - $configList{$1} = 1 if m/^#\s*undef\s+CONFIG_(\w*)/o; + $iLinuxConfig = $. if m/^\s*#\s*include\s*/o; + $configList{uc $1} = 1 if m/^\s*#\s*include\s*/o; + $configList{$1} = 1 if m/^\s*#\s*define\s+CONFIG_(\w*)/o; + $configList{$1} = 1 if m/^\s*#\s*undef\s+CONFIG_(\w*)/o; } # Look for usages. diff --git a/scripts/header.tk b/scripts/header.tk index 8226fe3a7..adb5e0d41 100644 --- a/scripts/header.tk +++ b/scripts/header.tk @@ -32,7 +32,7 @@ proc cget { w option } { proc vfix { var } { global $var if [ catch {eval concat $$var} ] { - set $var 0 + set $var 4 } } @@ -42,6 +42,7 @@ proc vfix { var } { set CONSTANT_Y 1 set CONSTANT_M 2 set CONSTANT_N 0 +set CONSTANT_E 4 # # Create a "reference" object to steal colors from. @@ -67,9 +68,11 @@ proc mainmenu_name { text } { proc menu_option { w menu_num text } { global menus_per_column - if { $menu_num <= $menus_per_column } then { + global processed_top_level + set processed_top_level [expr $processed_top_level + 1] + if { $processed_top_level <= $menus_per_column } then { set myframe left - } elseif { $menu_num <= [expr 2 * $menus_per_column] } then { + } elseif { $processed_top_level <= [expr 2 * $menus_per_column] } then { set myframe middle } else { set myframe right @@ -211,7 +214,7 @@ proc read_config { filename } { } close $file1 update_choices - update_mainmenu .rdupd + update_mainmenu } proc write_comment { file1 file2 text } { puts $file1 "" @@ -223,17 +226,49 @@ proc write_comment { file1 file2 text } { puts $file2 " */" } -proc write_tristate { file1 file2 varname variable dep } { - if { $variable == 0 } \ - then { puts $file1 "# $varname is not set"; \ - puts $file2 "#undef $varname"} \ - elseif { $variable == 2 || ($dep == 2 && $variable == 1) } \ +proc effective_dep { deplist } { + global CONFIG_MODULES + set depend 1 + foreach i $deplist { + if {$i == 0} then {set depend 0} + if {$i == 2 && $depend == 1} then {set depend 2} + } + if {$depend == 2 && $CONFIG_MODULES == 0} then {set depend 0} + return $depend +} + +proc sync_tristate { var dep } { + global CONFIG_MODULES + if {$dep == 0 && ($var == 1 || $var == 2)} then { + set var 0 + } elseif {$dep == 2 && $var == 1} then { + set var 2 + } elseif {$var == 2 && $CONFIG_MODULES == 0} then { + if {$dep == 1} then {set var 1} else {set var 0} + } + return $var +} + +proc sync_bool { var dep } { + set var [sync_tristate $var $dep] + if {$dep == 2} then { + set var 0 + } + return $var +} + +proc write_tristate { file1 file2 varname variable deplist } { + set variable [sync_tristate $variable [effective_dep $deplist]] + if { $variable == 1 }\ + then { puts $file1 "$varname=y"; \ + puts $file2 "#define $varname 1" } \ + elseif { $variable == 2 } \ then { puts $file1 "$varname=m"; \ puts $file2 "#undef $varname"; \ puts $file2 "#define ${varname}_MODULE 1" } \ - elseif { $variable == 1 && $dep != 2 } \ - then { puts $file1 "$varname=y"; \ - puts $file2 "#define $varname 1" } \ + elseif { $variable == 0 } \ + then { puts $file1 "# $varname is not set"; \ + puts $file2 "#undef $varname"} \ else { \ puts stdout "ERROR - Attempting to write value for unconfigured variable ($varname)." \ } @@ -245,7 +280,7 @@ proc write_int { file1 file2 varname variable dep } { puts $file2 "#undef $varname"} \ else { puts $file1 "$varname=$variable"; \ - puts $file2 "#define $varname $variable"; \ + puts $file2 "#define $varname ($variable)"; \ } } @@ -255,7 +290,8 @@ proc write_hex { file1 file2 varname variable dep } { puts $file2 "#undef $varname"} \ else { puts $file1 "$varname=$variable"; \ - puts $file2 "#define $varname 0x$variable"; \ + puts -nonewline $file2 "#define $varname 0x"; \ + puts $file2 [exec echo $variable | sed s/^0\[xX\]//]; \ } } @@ -282,11 +318,11 @@ proc option_name {w mnum line text helpidx} { proc toggle_switch2 {w mnum line text variable} { frame $w.x$line -relief sunken radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \ - -relief groove -width 2 -command "update_menu$mnum .menu$mnum" + -relief groove -width 2 -command "update_active" radiobutton $w.x$line.m -text "-" -variable $variable -value 2 \ - -relief groove -width 2 -command "update_menu$mnum .menu$mnum" + -relief groove -width 2 -command "update_active" radiobutton $w.x$line.n -text "n" -variable $variable -value 0 \ - -relief groove -width 2 -command "update_menu$mnum .menu$mnum" + -relief groove -width 2 -command "update_active" option_name $w $mnum $line $text $variable @@ -296,11 +332,11 @@ proc toggle_switch2 {w mnum line text variable} { proc toggle_switch3 {w mnum line text variable} { frame $w.x$line -relief sunken radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \ - -relief groove -width 2 -command "update_menu$mnum .menu$mnum" + -relief groove -width 2 -command "update_active" radiobutton $w.x$line.m -text "m" -variable $variable -value 2 \ - -relief groove -width 2 -command "update_menu$mnum .menu$mnum" + -relief groove -width 2 -command "update_active" radiobutton $w.x$line.n -text "n" -variable $variable -value 0 \ - -relief groove -width 2 -command "update_menu$mnum .menu$mnum" + -relief groove -width 2 -command "update_active" option_name $w $mnum $line $text $variable @@ -322,10 +358,14 @@ proc tristate {w mnum line text variable } { pack $w.x$line -anchor w -fill both -expand on } -proc dep_tristate {w mnum line text variable depend } { +proc dep_tristate {w mnum line text variable } { tristate $w $mnum $line $text $variable } +proc dep_bool {w mnum line text variable } { + bool $w $mnum $line $text $variable +} + proc int { w mnum line text variable } { frame $w.x$line entry $w.x$line.x -width 18 -relief sunken -borderwidth 2 \ @@ -358,6 +398,18 @@ proc minimenu { w mnum line text variable helpidx } { pack $w.x$line -anchor w -fill both -expand on } +proc submenu { w mnum line text subnum } { + frame $w.x$line + button $w.x$line.l -text "" -width 15 -relief groove + $w.x$line.l configure -activefore [cget $w.x$line.l -fg] \ + -activeback [cget $w.x$line.l -bg] -state disabled + button $w.x$line.m -text "$text" -relief raised -anchor w \ + -command "catch {destroy .menu$subnum}; menu$subnum .menu$subnum \"$text\"" + pack $w.x$line.l -side left -fill both + pack $w.x$line.m -anchor w -side right -fill both -expand on + pack $w.x$line -anchor w -fill both -expand on +} + proc comment {w line text } { #nothing done for comments now. } @@ -417,7 +469,7 @@ ${var}:\\ # frame $w.f2 button $w.f2.ok -text "OK" \ - -width 10 -command "destroy $w; focus $oldFocus" + -width 10 -command "destroy $w; catch {focus $oldFocus}" pack $w.f2.ok -side bottom -pady 6 -anchor n pack $w.f2 -side bottom -padx 10 -anchor s @@ -458,6 +510,55 @@ proc wrapup {w } { } +proc unregister_active {num} { + global active_menus + set index [lsearch -exact $active_menus $num] + if {$index != -1} then {set active_menus [lreplace $active_menus $index $index]} +} + +proc update_active {} { + global active_menus total_menus + set max 0 + if {[llength $active_menus] > 0} then { + set max [lindex $active_menus end] + update_define [toplevel_menu [lindex $active_menus 0]] $max 0 + } + foreach i $active_menus { + if {[winfo exists .menu$i] == 0} then { + unregister_active $i + } else { + update_menu$i + } + } + update_define [expr $max + 1] $total_menus 1 + update_mainmenu +} + +proc configure_entry {w option items} { + foreach i $items { + $w.$i configure -state $option + } +} + +proc validate_int {name val default} { + if {([exec echo $val | sed s/^-//g | tr -d \[:digit:\] ] != "")} then { + global $name; set $name $default + } +} + +proc validate_hex {name val default} { + if {([exec echo $val | tr -d \[:xdigit:\] ] != "")} then { + global $name; set $name $default + } +} + +proc update_define {first last allow_update} { + for {set i $first} {$i <= $last} {incr i} { + update_define_menu$i + if {$allow_update == 1} then update + } +} + # # Next set up the particulars for the top level menu, and define a few # buttons which we will stick down at the bottom. @@ -468,3 +569,5 @@ frame .f0.left frame .f0.middle frame .f0.right +set active_menus [list] +set processed_top_level 0 diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile index 90e192a55..2bad7a12f 100644 --- a/scripts/lxdialog/Makefile +++ b/scripts/lxdialog/Makefile @@ -30,8 +30,11 @@ all: ncurses lxdialog lxdialog: $(OBJS) ncurses: - @x=`find /lib/ /usr/lib/ /usr/local/lib/ -maxdepth 1 -name 'libncurses.*'` ;\ - if [ ! "$$x" ]; then \ + @echo "main() {}" > lxtemp.c + @if $(CC) -lncurses lxtemp.c ; then \ + rm -f lxtemp.c a.out; \ + else \ + rm -f lxtemp.c; \ echo -e "\007" ;\ echo ">> Unable to find the Ncurses libraries." ;\ echo ">>" ;\ diff --git a/scripts/mkdep.c b/scripts/mkdep.c index 8b009041b..e1884e0a6 100644 --- a/scripts/mkdep.c +++ b/scripts/mkdep.c @@ -8,6 +8,16 @@ * I make simple dependency lines for #include <*.h> and #include "*.h". * I also find instances of CONFIG_FOO and generate dependencies * like include/config/foo.h. + * + * 1 August 1999, Michael Elizabeth Chastain, + * - Keith Owens reported a bug in smart config processing. There used + * to be an optimization for "#define CONFIG_FOO ... #ifdef CONFIG_FOO", + * so that the file would not depend on CONFIG_FOO because the file defines + * this symbol itself. But this optimization is bogus! Consider this code: + * "#if 0 \n #define CONFIG_FOO \n #endif ... #ifdef CONFIG_FOO". Here + * the definition is inactivated, but I still used it. It turns out this + * actually happens a few times in the kernel source. The simple way to + * fix this problem is to remove this particular optimization. */ #include @@ -21,9 +31,7 @@ #include #include -#ifndef MAP_AUTOGROW -#define MAP_AUTOGROW 0 -#endif + char __depname[512] = "\n\t@touch "; #define depname (__depname+9) @@ -68,7 +76,7 @@ void grow_config(int len) while (len_config + len > size_config) { str_config = realloc(str_config, size_config *= 2); if (str_config == NULL) - { perror("malloc"); exit(1); } + { perror("malloc config"); exit(1); } } } @@ -95,22 +103,11 @@ int is_defined_config(const char * name, int len) /* * Add a new value to the configuration string. */ -void define_config(int convert, const char * name, int len) +void define_config(const char * name, int len) { grow_config(len + 1); memcpy(str_config+len_config, name, len); - - if (convert) { - int i; - for (i = 0; i < len; i++) { - char c = str_config[len_config+i]; - if (isupper(c)) c = tolower(c); - if (c == '_') c = '/'; - str_config[len_config+i] = c; - } - } - len_config += len; str_config[len_config++] = '\n'; } @@ -123,7 +120,56 @@ void define_config(int convert, const char * name, int len) void clear_config(void) { len_config = 0; - define_config(0, "", 0); + define_config("", 0); +} + + + +/* + * This records all the precious .h filenames. No need for a hash, + * it's a long string of values enclosed in tab and newline. + */ +char * str_precious = NULL; +int size_precious = 0; +int len_precious = 0; + + + +/* + * Grow the precious string to a desired length. + * Usually the first growth is plenty. + */ +void grow_precious(int len) +{ + if (str_precious == NULL) { + len_precious = 0; + size_precious = 4096; + str_precious = malloc(4096); + if (str_precious == NULL) + { perror("malloc precious"); exit(1); } + } + + while (len_precious + len > size_precious) { + str_precious = realloc(str_precious, size_precious *= 2); + if (str_precious == NULL) + { perror("malloc"); exit(1); } + } +} + + + +/* + * Add a new value to the precious string. + */ +void define_precious(const char * filename) +{ + int len = strlen(filename); + grow_precious(len + 4); + *(str_precious+len_precious++) = '\t'; + memcpy(str_precious+len_precious, filename, len); + len_precious += len; + memcpy(str_precious+len_precious, " \\\n", 3); + len_precious += 3; } @@ -139,7 +185,7 @@ void handle_include(int type, const char * name, int len) return; if (len >= 7 && !memcmp(name, "config/", 7)) - define_config(0, name+7, len-7-2); + define_config(name+7, len-7-2); memcpy(path->buffer+path->len, name, len); path->buffer[path->len+len] = '\0'; @@ -178,7 +224,7 @@ void use_config(const char * name, int len) if (is_defined_config(pc, len)) return; - define_config(0, pc, len); + define_config(pc, len); if (!hasdep) { hasdep = 1; @@ -195,7 +241,8 @@ void use_config(const char * name, int len) * Thus, there is one memory access per sizeof(unsigned long) characters. */ -#if defined(__alpha__) || defined(__i386__) || defined(__MIPSEL__) || defined(__arm__) +#if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__MIPSEL__) \ + || defined(__arm__) #define LE_MACHINE #endif @@ -362,7 +409,13 @@ pound_u: GETNEXT NOTCASE('f', __start); goto pound_define_undef; -/* #\s*(define|undef)\s*CONFIG_(\w*) */ +/* + * #\s*(define|undef)\s*CONFIG_(\w*) + * + * this does not define the word, because it could be inside another + * conditional (#if 0). But I do parse the word so that this instance + * does not count as a use. -- mec + */ pound_define_undef: GETNEXT CASE(' ', pound_define_undef); @@ -381,7 +434,6 @@ pound_define_undef_CONFIG_word: GETNEXT if (isalnum(current) || current == '_') goto pound_define_undef_CONFIG_word; - define_config(1, map_dot, next - map_dot - 1); goto __start; /* \ + * - kvariables removed; all variables are stored in a single table now + * - some elimination of options non-valid for current architecture + * implemented. + * - negation (!) eliminated from conditions + * * TO DO: * - xconfig is at the end of its life cycle. Contact if * you are interested in working on the replacement. @@ -28,73 +34,88 @@ /* - * Transform op_variable to op_kvariable. - * - * This works, but it's gross, speed-wise. It would benefit greatly - * from a simple hash table that maps names to cfg. - * - * Note well: this is actually better than the loop structure xconfig - * has been staggering along with for three years, which performs - * this whole procedure inside *another* loop on active conditionals. + * Mark variables which are defined anywhere. */ -void transform_to_kvariable( struct kconfig * scfg ) +static void mark_variables( struct kconfig * scfg ) { struct kconfig * cfg; + int i; + for ( i = 1; i <= max_varnum; i++ ) + vartable[i].defined = 0; for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { - struct condition * cond; - - for ( cond = cfg->cond; cond != NULL; cond = cond->next ) + if ( cfg->token == token_bool + || cfg->token == token_choice_item + || cfg->token == token_define_bool + || cfg->token == token_define_hex + || cfg->token == token_define_int + || cfg->token == token_define_string + || cfg->token == token_define_tristate + || cfg->token == token_dep_bool + || cfg->token == token_dep_tristate + || cfg->token == token_hex + || cfg->token == token_int + || cfg->token == token_string + || cfg->token == token_tristate + || cfg->token == token_unset ) { - if ( cond->op == op_variable ) + if ( cfg->nameindex > 0 ) /* paranoid */ { - /* Here's where it gets DISGUSTING. */ - struct kconfig * cfg1; - - for ( cfg1 = scfg; cfg1 != NULL; cfg1 = cfg1->next ) - { - if ( cfg1->token == token_bool - || cfg1->token == token_choice_item - || cfg1->token == token_dep_tristate - || cfg1->token == token_hex - || cfg1->token == token_int - || cfg1->token == token_string - || cfg1->token == token_tristate ) - { - if ( strcmp( cond->str, cfg1->optionname ) == 0 ) - { - cond->op = op_kvariable; - cond->str = NULL; - cond->cfg = cfg1; - break; - } - } - } + vartable[cfg->nameindex].defined = 1; } + } + } +} -#if 0 - /* - * Maybe someday this will be useful, but right now it - * gives a lot of false positives on files like - * drivers/video/Config.in that are meant for more - * than one architecture. Turn it on if you want to play - * with it though; it does work. -- mec - */ - if ( cond->op == op_variable ) + + +static void free_cond( struct condition *cond ) +{ + struct condition *tmp, *tmp1; + for ( tmp = cond; tmp; tmp = tmp1 ) + { + tmp1 = tmp->next; + free( (void*)tmp ); + } +} + + + +/* + * Remove the bang operator from a condition to avoid priority problems. + * "!" has different priorities as "test" command argument and in + * a tk script. + */ +static struct condition * remove_bang( struct condition * condition ) +{ + struct condition * conda, * condb, * prev = NULL; + + for ( conda = condition; conda; conda = conda->next ) + { + if ( conda->op == op_bang && conda->next && + ( condb = conda->next->next ) ) + { + if ( condb->op == op_eq || condb->op == op_neq ) { - if ( strcmp( cond->str, "ARCH" ) != 0 - && strcmp( cond->str, "CONSTANT_Y" ) != 0 - && strcmp( cond->str, "CONSTANT_M" ) != 0 - && strcmp( cond->str, "CONSTANT_N" ) != 0 ) + condb->op = (condb->op == op_eq) ? op_neq : op_eq; + conda->op = op_nuked; + if ( prev ) { - fprintf( stderr, "warning: $%s used but not defined\n", - cond->str ); + prev->next = conda->next; } + else + { + condition = conda->next; + } + conda->next = NULL; + free_cond( conda ); + conda = condb; } -#endif } + prev = conda; } + return condition; } @@ -103,27 +124,65 @@ void transform_to_kvariable( struct kconfig * scfg ) * Make a new condition chain by joining the current condition stack with * the "&&" operator for glue. */ -struct condition * join_condition_stack( struct condition * conditions [], +static struct condition * join_condition_stack( struct condition * conditions [], int depth ) { struct condition * cond_list; struct condition * cond_last; - int i; + int i, is_first = 1; cond_list = cond_last = NULL; + + for ( i = 0; i < depth; i++ ) + { + if ( conditions[i]->op == op_false ) + { + struct condition * cnew; + + /* It is always false condition */ + cnew = malloc( sizeof(*cnew) ); + memset( cnew, 0, sizeof(*cnew) ); + cnew->op = op_false; + cond_list = cond_last = cnew; + goto join_done; + } + } for ( i = 0; i < depth; i++ ) { struct condition * cond; struct condition * cnew; + int add_paren; + + /* omit always true conditions */ + if ( conditions[i]->op == op_true ) + continue; + + /* if i have another condition, add an '&&' operator */ + if ( !is_first ) + { + cnew = malloc( sizeof(*cnew) ); + memset( cnew, 0, sizeof(*cnew) ); + cnew->op = op_and; + cond_last->next = cnew; + cond_last = cnew; + } - /* add a '(' */ - cnew = malloc( sizeof(*cnew) ); - memset( cnew, 0, sizeof(*cnew) ); - cnew->op = op_lparen; - if ( cond_last == NULL ) - { cond_list = cond_last = cnew; } + if ( conditions[i]->op != op_lparen ) + { + /* add a '(' */ + add_paren = 1; + cnew = malloc( sizeof(*cnew) ); + memset( cnew, 0, sizeof(*cnew) ); + cnew->op = op_lparen; + if ( cond_last == NULL ) + { cond_list = cond_last = cnew; } + else + { cond_last->next = cnew; cond_last = cnew; } + } else - { cond_last->next = cnew; cond_last = cnew; } + { + add_paren = 0; + } /* duplicate the chain */ for ( cond = conditions [i]; cond != NULL; cond = cond->next ) @@ -132,27 +191,23 @@ struct condition * join_condition_stack( struct condition * conditions [], cnew->next = NULL; cnew->op = cond->op; cnew->str = cond->str ? strdup( cond->str ) : NULL; - cnew->cfg = cond->cfg; - cond_last->next = cnew; - cond_last = cnew; + cnew->nameindex = cond->nameindex; + if ( cond_last == NULL ) + { cond_list = cond_last = cnew; } + else + { cond_last->next = cnew; cond_last = cnew; } } - /* add a ')' */ - cnew = malloc( sizeof(*cnew) ); - memset( cnew, 0, sizeof(*cnew) ); - cnew->op = op_rparen; - cond_last->next = cnew; - cond_last = cnew; - - /* if i have another condition, add an '&&' operator */ - if ( i < depth - 1 ) + if ( add_paren ) { + /* add a ')' */ cnew = malloc( sizeof(*cnew) ); memset( cnew, 0, sizeof(*cnew) ); - cnew->op = op_and; + cnew->op = op_rparen; cond_last->next = cnew; cond_last = cnew; } + is_first = 0; } /* @@ -171,7 +226,7 @@ struct condition * join_condition_stack( struct condition * conditions [], cond1e = cond1d->next; if ( cond1e == NULL ) break; cond1f = cond1e->next; if ( cond1f == NULL ) break; - if ( cond1b->op == op_kvariable + if ( cond1b->op == op_variable && ( cond1c->op == op_eq || cond1c->op == op_neq ) && cond1d->op == op_constant && cond1e->op == op_rparen ) @@ -189,8 +244,8 @@ struct condition * join_condition_stack( struct condition * conditions [], cond2f = cond2e->next; /* look for match */ - if ( cond2b->op == op_kvariable - && cond2b->cfg == cond1b->cfg + if ( cond2b->op == op_variable + && cond2b->nameindex == cond1b->nameindex && cond2c->op == cond1c->op && cond2d->op == op_constant && strcmp( cond2d->str, cond1d->str ) == 0 @@ -219,64 +274,159 @@ struct condition * join_condition_stack( struct condition * conditions [], } } +join_done: return cond_list; } +static char * current_arch = NULL; + /* - * This is the main transformation function. + * Eliminating conditions with ARCH = . */ -void fix_conditionals( struct kconfig * scfg ) +static struct condition *eliminate_other_arch( struct condition *list ) { - struct kconfig * cfg; - - /* - * Transform op_variable to op_kvariable. - */ - transform_to_kvariable( scfg ); - - /* - * Transform conditions that use variables from "choice" statements. - * Choice values appear to the user as a collection of booleans, and the - * script can test the individual booleans. But internally, all I have is - * the N-way value of an unnamed temporary for the whole statement. So I - * have to tranform '"$CONFIG_M386" != "y"' - * into '"$tmpvar_N" != "CONFIG_M386"'. - */ - for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) + struct condition *cond1a = list, *cond1b = NULL, *cond1c = NULL, *cond1d = NULL; + if ( current_arch == NULL ) + current_arch = getenv( "ARCH" ); + if ( current_arch == NULL ) { - struct condition * cond; - - for ( cond = cfg->cond; cond != NULL; cond = cond->next ) + fprintf( stderr, "error: ARCH undefined\n" ); + exit( 1 ); + } + if ( cond1a->op == op_variable + && ! strcmp( vartable[cond1a->nameindex].name, "ARCH" ) ) + { + cond1b = cond1a->next; if ( cond1b == NULL ) goto done; + cond1c = cond1b->next; if ( cond1c == NULL ) goto done; + cond1d = cond1c->next; + if ( cond1c->op == op_constant && cond1d == NULL ) { - if ( cond->op == op_kvariable && cond->cfg->token == token_choice_item ) + if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch )) + || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) ) { - /* - * Look two more tokens down for the comparison token. - * It has to be "y" for this trick to work. - * - * If you get this error, don't even think about relaxing the - * strcmp test. You will produce incorrect TK code. Instead, - * look for the place in your Config.in script where you are - * comparing a 'choice' variable to a value other than 'y', - * and rewrite the comparison to be '= "y"' or '!= "y"'. - */ - struct condition * cond2 = cond->next->next; - const char * label; - - if ( strcmp( cond2->str, "y" ) != 0 ) + /* This is for another architecture */ + cond1a->op = op_false; + cond1a->next = NULL; + free_cond( cond1b ); + return cond1a; + } + else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch )) + || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) ) + { + /* This is for current architecture */ + cond1a->op = op_true; + cond1a->next = NULL; + free_cond( cond1b ); + return cond1a; + } + } + else if ( cond1c->op == op_constant && cond1d->op == op_or ) + { + if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch )) + || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) ) + { + /* This is for another architecture */ + cond1b = cond1d->next; + cond1d->next = NULL; + free_cond( cond1a ); + return eliminate_other_arch( cond1b ); + } + else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch )) + || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) ) + { + /* This is for current architecture */ + cond1a->op = op_true; + cond1a->next = NULL; + free_cond( cond1b ); + return cond1a; + } + } + else if ( cond1c->op == op_constant && cond1d->op == op_and ) + { + if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch )) + || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) ) + { + /* This is for another architecture */ + int l_par = 0; + + for ( cond1c = cond1d->next; cond1c; cond1c = cond1c->next ) { - fprintf( stderr, "tkparse choked in fix_choice_cond\n" ); - exit( 1 ); + if ( cond1c->op == op_lparen ) + l_par++; + else if ( cond1c->op == op_rparen ) + l_par--; + else if ( cond1c->op == op_or && l_par == 0 ) + /* Expression too complex - don't touch */ + return cond1a; + else if ( l_par < 0 ) + { + fprintf( stderr, "incorrect condition: programming error ?\n" ); + exit( 1 ); + } } + cond1a->op = op_false; + cond1a->next = NULL; + free_cond( cond1b ); + return cond1a; + } + else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch )) + || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) ) + { + /* This is for current architecture */ + cond1b = cond1d->next; + cond1d->next = NULL; + free_cond( cond1a ); + return eliminate_other_arch( cond1b ); + } + } + } + if ( cond1a->op == op_variable && ! vartable[cond1a->nameindex].defined ) + { + cond1b = cond1a->next; if ( cond1b == NULL ) goto done; + cond1c = cond1b->next; if ( cond1c == NULL ) goto done; + cond1d = cond1c->next; - label = cond->cfg->label; - cond->cfg = cond->cfg->cfg_parent; - cond2->str = strdup( label ); + if ( cond1c->op == op_constant + && ( cond1d == NULL || cond1d->op == op_and ) ) /*???*/ + { + if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) ) + { + cond1a->op = op_false; + cond1a->next = NULL; + free_cond( cond1b ); + return cond1a; + } + } + else if ( cond1c->op == op_constant && cond1d->op == op_or ) + { + if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) ) + { + cond1b = cond1d->next; + cond1d->next = NULL; + free_cond( cond1a ); + return eliminate_other_arch( cond1b ); } } } +done: + return list; +} + + + +/* + * This is the main transformation function. + */ +void fix_conditionals( struct kconfig * scfg ) +{ + struct kconfig * cfg; + + /* + * Transform op_variable to op_kvariable. + */ + mark_variables( scfg ); /* * Walk the statement list, maintaining a stack of current conditions. @@ -290,16 +440,19 @@ void fix_conditionals( struct kconfig * scfg ) { struct condition * cond_stack [32]; int depth = 0; + struct kconfig * prev = NULL; for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { + int good = 1; switch ( cfg->token ) { default: break; case token_if: - cond_stack [depth++] = cfg->cond; + cond_stack [depth++] = + remove_bang( eliminate_other_arch( cfg->cond ) ); cfg->cond = NULL; break; @@ -325,6 +478,8 @@ void fix_conditionals( struct kconfig * scfg ) case op_or: cond->op = op_and1; break; case op_neq: cond->op = op_eq; break; case op_eq: cond->op = op_neq; break; + case op_true: cond->op = op_false;break; + case op_false:cond->op = op_true; break; } } } @@ -336,25 +491,109 @@ void fix_conditionals( struct kconfig * scfg ) case token_bool: case token_choice_item: + case token_choice_header: case token_comment: case token_define_bool: + case token_define_hex: + case token_define_int: + case token_define_string: + case token_define_tristate: case token_hex: case token_int: case token_mainmenu_option: case token_string: case token_tristate: + case token_unset: cfg->cond = join_condition_stack( cond_stack, depth ); + if ( cfg->cond && cfg->cond->op == op_false ) + { + good = 0; + if ( prev ) + prev->next = cfg->next; + else + scfg = cfg->next; + } break; + case token_dep_bool: case token_dep_tristate: /* * Same as the other simple statements, plus an additional * condition for the dependency. */ - cond_stack [depth] = cfg->cond; - cfg->cond = join_condition_stack( cond_stack, depth+1 ); + if ( cfg->cond ) + { + cond_stack [depth] = eliminate_other_arch( cfg->cond ); + cfg->cond = join_condition_stack( cond_stack, depth+1 ); + } + else + { + cfg->cond = join_condition_stack( cond_stack, depth ); + } + if ( cfg->cond && cfg->cond->op == op_false ) + { + good = 0; + if ( prev ) + prev->next = cfg->next; + else + scfg = cfg->next; + } break; } + if ( good ) + prev = cfg; } } } + + + +#if 0 +void dump_condition( struct condition *list ) +{ + struct condition *tmp; + for ( tmp = list; tmp; tmp = tmp->next ) + { + switch (tmp->op) + { + default: + break; + case op_variable: + printf( " %s", vartable[tmp->nameindex].name ); + break; + case op_constant: + printf( " %s", tmp->str ); + break; + case op_eq: + printf( " =" ); + break; + case op_bang: + printf( " !" ); + break; + case op_neq: + printf( " !=" ); + break; + case op_and: + case op_and1: + printf( " -a" ); + break; + case op_or: + printf( " -o" ); + break; + case op_true: + printf( " TRUE" ); + break; + case op_false: + printf( " FALSE" ); + break; + case op_lparen: + printf( " (" ); + break; + case op_rparen: + printf( " )" ); + break; + } + } + printf( "\n" ); +} +#endif diff --git a/scripts/tkgen.c b/scripts/tkgen.c index 279072d78..4a50a82a4 100644 --- a/scripts/tkgen.c +++ b/scripts/tkgen.c @@ -92,33 +92,58 @@ * * 23 January 1999, Michael Elizabeth Chastain * - Remove bug-compatible code. + * + * 07 July 1999, Andrzej M. Krzysztofowicz + * Some bugfixes, including + * - disabling "m" options when CONFIG_MODULES is set to "n" as well as "y" + * option in dep_tristate when dependency is set to "m", + * - deactivating choices which should not be available, + * - basic validation for int and hex introduced if the entered one is not + * valid, + * - updates of all opened menus instead of the active only. I was afraid + * that it would slow down updates, but I don't even see any speed difference + * on my machine. If it slows you can still work with only a single menu + * opened, + * - fixed error when focussing non-existent window (especially Help windows), + * Higher level submenus implemented. */ #include +#include #include +#include #include "tkparse.h" - /* * Total number of menus. */ static int tot_menu_num = 0; - +/* + * Pointers to mainmenu_option and endmenu of each menu. + */ +struct kconfig * menu_first [100]; +struct kconfig * menu_last [100]; /* * Generate portion of wish script for the beginning of a submenu. * The guts get filled in with the various options. */ -static void start_proc( char * label, int menu_num, int flag ) +static void start_proc( char * label, int menu_num, int toplevel ) { - if ( flag ) + if ( toplevel ) printf( "menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label ); printf( "proc menu%d {w title} {\n", menu_num ); - printf( "\tcatch {destroy $w}\n" ); + printf( "\tset oldFocus [focus]\n" ); + if ( menu_first[menu_num]->menu_number != 0 ) + printf( "\tcatch {focus .menu%d}\n", + menu_first[menu_num]->menu_number ); + printf( "\tcatch {destroy $w; unregister_active %d}\n", menu_num ); printf( "\ttoplevel $w -class Dialog\n" ); printf( "\twm withdraw $w\n" ); + printf( "\tglobal active_menus\n" ); + printf( "\tset active_menus [lsort -integer [linsert $active_menus end %d]]\n", menu_num ); printf( "\tmessage $w.m -width 400 -aspect 300 -text \\\n" ); printf( "\t\t\"%s\" -relief raised\n", label ); printf( "\tpack $w.m -pady 10 -side top -padx 10\n" ); @@ -127,16 +152,41 @@ static void start_proc( char * label, int menu_num, int flag ) /* * Attach the "Prev", "Next" and "OK" buttons at the end of the window. */ - printf( "\tset oldFocus [focus]\n" ); printf( "\tframe $w.f\n" ); - printf( "\tbutton $w.f.back -text \"Main Menu\" \\\n" ); - printf( "\t\t-width 15 -command \"destroy $w; focus $oldFocus; update_mainmenu $w\"\n" ); + if ( toplevel ) + printf( "\tbutton $w.f.back -text \"Main Menu\" \\\n" ); + else + printf( "\tbutton $w.f.back -text \"OK\" \\\n" ); + printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d\"\n", + menu_num ); printf( "\tbutton $w.f.next -text \"Next\" \\\n" ); - printf( "\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n", menu_num+1, menu_num+1 ); + printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; " ); + /* + * We are checking which windows should be destroyed and which are + * common parrents with the next one. Remember that menu_num field + * in mainmenu_option record reports number of its *parent* menu. + */ + if ( menu_num < tot_menu_num + && menu_first[menu_num + 1]->menu_number != menu_num ) + { + int to_destr; + + printf( "destroy $w; unregister_active %d; ", menu_num ); + to_destr = menu_first[menu_num]->menu_number; + while ( to_destr > 0 && menu_first[menu_num + 1]->menu_number != to_destr ) + { + printf( "catch {destroy .menu%d}; unregister_active %d; ", + to_destr, to_destr ); + to_destr = menu_first[to_destr]->menu_number; + } + } + printf( "menu%d .menu%d \\\"$title\\\"\"\n", + menu_num+1, menu_num+1 ); if ( menu_num == tot_menu_num ) printf( "\t$w.f.next configure -state disabled\n" ); printf( "\tbutton $w.f.prev -text \"Prev\" \\\n" ); - printf( "\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n", menu_num-1, menu_num-1 ); + printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d; menu%d .menu%d \\\"$title\\\"\"\n", + menu_num, menu_num-1, menu_num-1 ); if ( menu_num == 1 ) printf( "\t$w.f.prev configure -state disabled\n" ); printf( "\tpack $w.f.back $w.f.next $w.f.prev -side left -expand on\n" ); @@ -177,12 +227,11 @@ static void start_proc( char * label, int menu_num, int flag ) * a global declaration so we know whether we need to insert one for a * given function or not. */ -void clear_globalflags( struct kconfig * scfg ) +static void clear_globalflags(void) { - struct kconfig * cfg; - - for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) - cfg->global_written = 0; + int i; + for ( i = 1; i <= max_varnum; i++ ) + vartable[i].global_written = 0; } @@ -194,7 +243,7 @@ void clear_globalflags( struct kconfig * scfg ) */ void global( const char *var ) { - printf( "\tglobal %s; vfix %s\n", var, var ); + printf( "\tglobal %s\n", var ); } @@ -207,6 +256,21 @@ void generate_if( struct kconfig * cfg, struct condition * ocond, int menu_num, int line_num ) { struct condition * cond; + struct dependency * tmp; + struct kconfig * cfg1; + + if ( line_num >= -1 ) + { + if ( cfg->token == token_define_bool || cfg->token == token_define_hex + || cfg->token == token_define_int || cfg->token == token_define_string + || cfg->token == token_define_tristate || cfg->token == token_unset ) + return; + } + else + { + if ( cfg->token == token_string || cfg->token == token_mainmenu_option ) + return; + } /* * First write any global declarations we need for this conditional. @@ -219,14 +283,10 @@ void generate_if( struct kconfig * cfg, struct condition * ocond, break; case op_variable: - global( cond->str ); - break; - - case op_kvariable: - if ( ! cond->cfg->global_written ) + if ( ! vartable[cond->nameindex].global_written ) { - cond->cfg->global_written = 1; - global( cond->cfg->optionname ); + vartable[cond->nameindex].global_written = 1; + global( vartable[cond->nameindex].name ); } break; } @@ -235,10 +295,10 @@ void generate_if( struct kconfig * cfg, struct condition * ocond, /* * Now write this option. */ - if ( ! cfg->global_written && cfg->optionname != NULL ) + if ( cfg->nameindex > 0 && ! vartable[cfg->nameindex].global_written ) { - cfg->global_written = 1; - global( cfg->optionname ); + vartable[cfg->nameindex].global_written = 1; + global( vartable[cfg->nameindex].name ); } /* @@ -262,156 +322,310 @@ void generate_if( struct kconfig * cfg, struct condition * ocond, case op_rparen: printf( ")" ); break; case op_variable: - printf( "$%s", cond->str ); - break; - - case op_kvariable: - printf( "$%s", cond->cfg->optionname ); + printf( "$%s", vartable[cond->nameindex].name ); break; case op_constant: if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" ); else if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" ); else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" ); + else if ( strcmp( cond->str, "" ) == 0 ) printf( "4" ); else printf( "\"%s\"", cond->str ); break; } } - printf( "} then { " ); + printf( "} then {" ); /* * Generate a procedure call to write the value. * This code depends on procedures in header.tk. */ - switch ( cfg->token ) + if ( line_num >= -1 ) { - default: - printf( " }\n" ); - break; - - case token_bool: - printf( ".menu%d.config.f.x%d.y configure -state normal;", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.n configure -state normal;", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.l configure -state normal;", - menu_num, line_num ); - printf( "set %s [expr $%s&15];", - cfg->optionname, cfg->optionname ); - printf( "} else { "); - printf( ".menu%d.config.f.x%d.y configure -state disabled;", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.n configure -state disabled;", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.l configure -state disabled;", - menu_num, line_num ); - printf( "set %s [expr $%s|16];}\n", - cfg->optionname, cfg->optionname ); - break; + switch ( cfg->token ) + { + default: + printf( " }\n" ); + break; - case token_choice_header: - fprintf( stderr, "Internal error on token_choice_header\n" ); - exit( 1 ); + case token_dep_bool: + printf( "\n" ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + if ( ! vartable[get_varnum( tmp->name )].global_written ) + { + global( tmp->name ); + } + printf( "\tset tmpvar_dep [effective_dep [list" ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + printf( " $%s", tmp->name ); + printf( "]];set %s [sync_bool $%s $tmpvar_dep];", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + printf( "if {$tmpvar_dep != 1} then {" ); + printf( "configure_entry .menu%d.config.f.x%d disabled {y};", + menu_num, line_num ); + printf( "} else {" ); + printf( "configure_entry .menu%d.config.f.x%d normal {y};", + menu_num, line_num ); + printf( "}; " ); + case token_bool: + if ( cfg->token == token_bool ) + printf( "\n\t" ); + printf( "configure_entry .menu%d.config.f.x%d normal {n l", + menu_num, line_num ); + if ( cfg->token == token_bool ) + printf( " y" ); + printf( "}" ); + printf( "} else {"); + printf( "configure_entry .menu%d.config.f.x%d disabled {y n l}}\n", + menu_num, line_num ); + break; - case token_choice_item: - fprintf( stderr, "Internal error on token_choice_item\n" ); - exit( 1 ); + case token_choice_header: + printf( "configure_entry .menu%d.config.f.x%d normal {x l}", + menu_num, line_num ); + printf( "} else {" ); + printf( "configure_entry .menu%d.config.f.x%d disabled {x l}", + menu_num, line_num ); + printf( "}\n" ); + break; - case token_define_bool: - printf( "set %s %s } \n", - cfg->optionname, cfg->value ); - break; + case token_choice_item: + fprintf( stderr, "Internal error on token_choice_item\n" ); + exit( 1 ); - case token_dep_tristate: - case token_tristate: - if ( cfg->token == token_dep_tristate ) - { - global( cfg->depend ); - printf( "if { $%s != 1 && $%s != 0 } then {", - cfg->depend, cfg->depend ); - printf( ".menu%d.config.f.x%d.y configure -state disabled;", + case token_dep_tristate: + printf( "\n" ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + if ( ! vartable[get_varnum( tmp->name )].global_written ) + { + global( tmp->name ); + } + printf( "\tset tmpvar_dep [effective_dep [list" ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + printf( " $%s", tmp->name ); + printf( "]];set %s [sync_tristate $%s $tmpvar_dep];", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + printf( "\tif {$tmpvar_dep != 1} then {" ); + printf( "configure_entry .menu%d.config.f.x%d disabled {y}", menu_num, line_num ); printf( "} else {" ); - printf( ".menu%d.config.f.x%d.y configure -state normal;", - menu_num, line_num); + printf( "configure_entry .menu%d.config.f.x%d normal {y}", + menu_num, line_num ); printf( "}; " ); - } - else - { - printf( ".menu%d.config.f.x%d.y configure -state normal;", + printf( "if {$tmpvar_dep == 0} then {" ); + printf( "configure_entry .menu%d.config.f.x%d disabled {m}", + menu_num, line_num ); + printf( "} else {" ); + printf( "configure_entry .menu%d.config.f.x%d normal {m}", + menu_num, line_num ); + printf( "}; " ); + case token_tristate: + if ( cfg->token == token_tristate ) + { + printf( "\n\tconfigure_entry .menu%d.config.f.x%d normal {y}; ", + menu_num, line_num ); + } + printf( "if {($CONFIG_MODULES == 1)} then {" ); + printf( "configure_entry .menu%d.config.f.x%d normal {m}} else {", + menu_num, line_num ); + printf( "configure_entry .menu%d.config.f.x%d disabled {m}}; ", + menu_num, line_num ); + printf( "configure_entry .menu%d.config.f.x%d normal {n l}", + menu_num, line_num ); + + /* + * Or in a bit to the variable - this causes all of the radiobuttons + * to be deselected (i.e. not be red). + */ + printf( "} else {" ); + printf( "configure_entry .menu%d.config.f.x%d disabled {y n m l}}\n", + menu_num, line_num ); + break; + + case token_hex: + case token_int: + case token_string: + printf( ".menu%d.config.f.x%d.x configure -state normal -foreground [ cget .ref -foreground ]; ", + menu_num, line_num ); + printf( ".menu%d.config.f.x%d.l configure -state normal; ", menu_num, line_num ); + printf( "} else {" ); + printf( ".menu%d.config.f.x%d.x configure -state disabled -foreground [ cget .ref -disabledforeground ]; ", + menu_num, line_num ); + printf( ".menu%d.config.f.x%d.l configure -state disabled}\n", + menu_num, line_num ); + break; + + case token_mainmenu_option: + if ( line_num >= 0 ) + { + printf( "configure_entry .menu%d.config.f.x%d normal {m}", + menu_num, line_num ); + printf( "} else {" ); + printf( "configure_entry .menu%d.config.f.x%d disabled {m}}\n", + menu_num, line_num ); + } + else + printf( ".f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n", + menu_num, menu_num ); + break; } + } + else + { + switch ( cfg->token ) + { + default: + printf( " }\n" ); + break; + + case token_dep_bool: + printf( "\n" ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + if ( ! vartable[get_varnum( tmp->name )].global_written ) + { + global( tmp->name ); + } + printf( "\tset tmpvar_dep [effective_dep [list" ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + printf( " $%s", tmp->name ); + printf( "]];set %s [sync_bool $%s $tmpvar_dep];", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + case token_bool: + if ( cfg->token == token_bool ) + printf( "\n\t" ); + printf( "set %s [expr $%s&15]", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + printf( "} else {"); + printf( "set %s [expr $%s|16]}\n", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + break; - printf( ".menu%d.config.f.x%d.n configure -state normal;", - menu_num, line_num ); - printf( "global CONFIG_MODULES; if {($CONFIG_MODULES == 1)} then { .menu%d.config.f.x%d.m configure -state normal };", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.l configure -state normal;", - menu_num, line_num ); + case token_choice_header: + printf( "} else {" ); + for ( cfg1 = cfg->next; + cfg1 != NULL && cfg1->token == token_choice_item; + cfg1 = cfg1->next ) + printf( "set %s 4;", vartable[cfg1->nameindex].name ); + printf( "}\n" ); + break; + case token_choice_item: + fprintf( stderr, "Internal error on token_choice_item\n" ); + exit( 1 ); + + case token_define_bool: + case token_define_tristate: + if ( ! vartable[get_varnum( cfg->value )].global_written ) + { + global( cfg->value ); + } + printf( "set %s $%s }\n", + vartable[cfg->nameindex].name, cfg->value ); + break; + + case token_define_hex: + case token_define_int: + printf( "set %s %s }\n", + vartable[cfg->nameindex].name, cfg->value ); + break; + + case token_define_string: + printf( "set %s \"%s\" }\n", + vartable[cfg->nameindex].name, cfg->value ); + break; + + case token_dep_tristate: + printf( "\n" ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + if ( ! vartable[get_varnum( tmp->name )].global_written ) + { + global( tmp->name ); + } + printf( "\tset tmpvar_dep [effective_dep [list" ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + printf( " $%s", tmp->name ); + printf( "]]; set %s [sync_tristate $%s $tmpvar_dep]; ", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + case token_tristate: + if ( cfg->token == token_tristate ) + printf( "if {($CONFIG_MODULES == 0) && ($%s == 2)} then {set %s 1}; ", + vartable[cfg->nameindex].name, + vartable[cfg->nameindex].name ); /* * Or in a bit to the variable - this causes all of the radiobuttons * to be deselected (i.e. not be red). */ - printf( "set %s [expr $%s&15];", - cfg->optionname, cfg->optionname ); - printf( "} else { " ); - printf( ".menu%d.config.f.x%d.y configure -state disabled;", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.n configure -state disabled;", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.m configure -state disabled;", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.l configure -state disabled;", - menu_num, line_num ); + printf( "set %s [expr $%s&15]", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + printf( "} else {" ); /* * Clear the disable bit to enable the correct radiobutton. */ - printf( "set %s [expr $%s|16];}\n", - cfg->optionname, cfg->optionname ); - break; + printf( "set %s [expr $%s|16]}\n", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + break; - case token_hex: - case token_int: - case token_string: - printf( ".menu%d.config.f.x%d.x configure -state normal -foreground [ cget .ref -foreground ]; ", - menu_num, line_num); - printf( ".menu%d.config.f.x%d.l configure -state normal; ", - menu_num, line_num); - printf( "} else { " ); - printf( ".menu%d.config.f.x%d.x configure -state disabled -foreground [ cget .ref -disabledforeground ];", - menu_num, line_num ); - printf( ".menu%d.config.f.x%d.l configure -state disabled;}\n", - menu_num, line_num ); - break; + case token_hex: + case token_int: + if ( cfg->value && *cfg->value == '$' ) + { + int index = get_varnum( cfg->value+1 ); + printf( "\n" ); + if ( ! vartable[index].global_written ) + { + global( vartable[index].name ); + } + printf( "\t" ); + } + if ( cfg->token == token_hex ) + printf( "validate_hex " ); + else if ( cfg->token == token_int ) + printf( "validate_int " ); + printf( "%s \"$%s\" %s}\n", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name, + cfg->value ); + break; - case token_mainmenu_option: - printf( ".f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n", - menu_num, menu_num ); - break; + case token_unset: + printf( "set %s 4}\n", vartable[cfg->nameindex].name ); + break; + } } } - /* * Generate a line that writes a variable to the output file. */ void generate_writeconfig( struct kconfig * cfg ) { struct condition * cond; - + struct dependency * tmp; + /* * Generate global declaration for this symbol. */ if ( cfg->token != token_comment ) { - if ( ! cfg->global_written ) + if ( cfg->nameindex > 0 && ! vartable[cfg->nameindex].global_written ) + { + vartable[cfg->nameindex].global_written = 1; + global( vartable[cfg->nameindex].name ); + } + if ( cfg->token == token_define_tristate || cfg->token == token_define_bool ) { - cfg->global_written = 1; - printf( "\tglobal %s\n", cfg->optionname ); + if ( ! vartable[get_varnum( cfg->value )].global_written ) + { + vartable[get_varnum( cfg->value )].global_written = 1; + global( cfg->value ); + } + } + else if ( cfg->nameindex <= 0 && cfg->token == token_choice_header ) + { + printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) ); } } @@ -426,14 +640,10 @@ void generate_writeconfig( struct kconfig * cfg ) break; case op_variable: - global( cond->str ); - break; - - case op_kvariable: - if ( ! cond->cfg->global_written ) + if ( ! vartable[cond->nameindex].global_written ) { - cond->cfg->global_written = 1; - global( cond->cfg->optionname ); + vartable[cond->nameindex].global_written = 1; + global( vartable[cond->nameindex].name ); } break; } @@ -442,7 +652,6 @@ void generate_writeconfig( struct kconfig * cfg ) /* * Generate indentation. */ - if ( cfg->token != token_choice_header ) printf( "\t" ); /* @@ -466,17 +675,14 @@ void generate_writeconfig( struct kconfig * cfg ) case op_rparen: printf( ")" ); break; case op_variable: - printf( "$%s", cond->str ); - break; - - case op_kvariable: - printf( "$%s", cond->cfg->optionname ); + printf( "$%s", vartable[cond->nameindex].name ); break; case op_constant: if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" ); else if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" ); else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" ); + else if ( strcmp( cond->str, "" ) == 0 ) printf( "4" ); else printf( "\"%s\"", cond->str ); break; @@ -499,10 +705,8 @@ void generate_writeconfig( struct kconfig * cfg ) case token_bool: case token_tristate: - if ( cfg->cond ) - printf( " " ); - printf( "write_tristate $cfg $autocfg %s $%s $notmod", - cfg->optionname, cfg->optionname ); + printf( "write_tristate $cfg $autocfg %s $%s [list $notmod]", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); @@ -520,12 +724,15 @@ void generate_writeconfig( struct kconfig * cfg ) cfg1 != NULL && cfg1->token == token_choice_item; cfg1 = cfg1->next ) { - printf("\tif { $%s == \"%s\" } then { write_tristate $cfg $autocfg %s 1 $notmod } else { write_tristate $cfg $autocfg %s 0 $notmod }\n", - cfg->optionname, cfg1->label, - cfg1->optionname, - cfg1->optionname ); + printf("\n\tif { $tmpvar_%d == \"%s\" } then { write_tristate $cfg $autocfg %s 1 [list $notmod] } else { write_tristate $cfg $autocfg %s 0 [list $notmod] }", + -(cfg->nameindex), cfg1->label, + vartable[cfg1->nameindex].name, + vartable[cfg1->nameindex].name ); } } + if ( cfg->cond != NULL ) + printf( "}" ); + printf( "\n" ); break; case token_choice_item: @@ -541,53 +748,74 @@ void generate_writeconfig( struct kconfig * cfg ) break; case token_define_bool: + case token_define_tristate: if ( cfg->cond == NULL ) { - printf( "write_tristate $cfg $autocfg %s $%s $notmod\n", - cfg->optionname, cfg->optionname ); + printf( "write_tristate $cfg $autocfg %s $%s [list $notmod]\n", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); } else { - printf( "write_tristate $cfg $autocfg %s %s $notmod }\n", - cfg->optionname, cfg->value ); + printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] }\n", + vartable[cfg->nameindex].name, cfg->value ); } break; + case token_dep_bool: case token_dep_tristate: - if ( cfg->cond ) - printf( " " ); - printf( "write_tristate $cfg $autocfg %s $%s $%s", - cfg->optionname, cfg->optionname, cfg->depend ); + printf( "write_tristate $cfg $autocfg %s $%s [list", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + for ( tmp = cfg->depend; tmp; tmp = tmp->next ) + printf( " $%s", tmp->name ); + printf( "]" ); if ( cfg->cond != NULL ) printf( " }" ); - printf( " \n" ); + printf( "\n" ); break; - case token_hex: + case token_define_hex: + printf( "write_hex $cfg $autocfg %s %s $notmod", + vartable[cfg->nameindex].name, cfg->value ); + if ( cfg->cond != NULL ) + printf( " }" ); + printf( "\n" ); + break; + + case token_define_int: + printf( "write_int $cfg $autocfg %s %s $notmod", + vartable[cfg->nameindex].name, cfg->value ); + if ( cfg->cond != NULL ) + printf( " }" ); + printf( "\n" ); + break; + + case token_define_string: + printf( "write_string $cfg $autocfg %s \"%s\" $notmod", + vartable[cfg->nameindex].name, cfg->value ); if ( cfg->cond != NULL ) - printf( " " ); + printf( " }" ); + printf( "\n" ); + break; + + case token_hex: printf( "write_hex $cfg $autocfg %s $%s $notmod", - cfg->optionname, cfg->optionname ); + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_int: - if ( cfg->cond != NULL ) - printf( " " ); printf( "write_int $cfg $autocfg %s $%s $notmod", - cfg->optionname, cfg->optionname ); + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_string: - if ( cfg->cond != NULL ) - printf( " " ); - printf( "write_string $cfg $autocfg %s $%s $notmod", - cfg->optionname, cfg->optionname ); + printf( "write_string $cfg $autocfg %s \"$%s\" $notmod", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); @@ -595,6 +823,112 @@ void generate_writeconfig( struct kconfig * cfg ) } } +static void generate_update_var( struct kconfig * scfg, int menu_num ) +{ + struct kconfig * cfg; + + if ( menu_num>0 ) + { + printf( "proc update_define_menu%d {} {\n", menu_num ); + printf( "\tupdate_define_mainmenu\n" ); + } + else + printf( "proc update_define_mainmenu {} {\n" ); + clear_globalflags(); + global( "CONFIG_MODULES" ); + vartable[ get_varnum( "CONFIG_MODULES" ) ].global_written = 1; + for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) + { + if ( cfg->menu_number == menu_num && (cfg->token == token_define_bool || cfg->token == token_define_tristate + || cfg->token == token_define_hex || cfg->token == token_define_int + || cfg->token == token_define_string || cfg->token == token_unset + || cfg->token == token_tristate) ) + { + if ( ! vartable[cfg->nameindex].global_written ) + { + vartable[cfg->nameindex].global_written = 1; + global( vartable[cfg->nameindex].name ); + } + } + } + + for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) + { + char tmp[20]; + struct kconfig * cfg1; + + if ( cfg->menu_number == menu_num ) + { + switch ( cfg->token ) + { + default: + case token_choice_item: + break; + case token_choice_header: + sprintf( tmp, "tmpvar_%d", -(cfg->nameindex) ); + global( tmp ); + for ( cfg1 = cfg->next; + cfg1 != NULL && cfg1->token == token_choice_item; + cfg1 = cfg1->next ) + { + vartable[cfg1->nameindex].global_written = 1; + global( vartable[cfg1->nameindex].name ); + printf( "\tif {$tmpvar_%d == \"%s\"} then {set %s 1} else {set %s 0}\n", + -(cfg->nameindex), cfg1->label, + vartable[cfg1->nameindex].name, + vartable[cfg1->nameindex].name ); + } + break; + case token_bool: + case token_define_bool: + case token_define_tristate: + case token_define_hex: + case token_define_int: + case token_define_string: + case token_dep_bool: + case token_dep_tristate: + case token_int: + case token_hex: + case token_mainmenu_option: + case token_tristate: + case token_unset: + if ( cfg->cond != NULL ) + generate_if( cfg, cfg->cond, menu_num, -2 ); + else switch ( cfg->token ) + { + case token_tristate: + printf( "\n\tif {($CONFIG_MODULES == 0)} then {if {($%s == 2)} then {set %s 1}}\n", + vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); + break; + case token_define_bool: + case token_define_tristate: + if ( ! vartable[get_varnum( cfg->value )].global_written ) + { + vartable[get_varnum( cfg->value )].global_written = 1; + global( cfg->value ); + } + printf( "\tset %s $%s\n", vartable[cfg->nameindex].name, + cfg->value ); + break; + case token_define_hex: + case token_define_int: + printf( "\tset %s %s\n", vartable[cfg->nameindex].name, + cfg->value ); + break; + case token_define_string: + printf( "\tset %s \"%s\"\n", vartable[cfg->nameindex].name, + cfg->value ); + break; + case token_unset: + printf( "\tset %s 4\n", vartable[cfg->nameindex].name ); + default: + break; + } + } + } + } + printf( "}\n\n\n" ); +} /* @@ -603,13 +937,24 @@ void generate_writeconfig( struct kconfig * cfg ) static void end_proc( struct kconfig * scfg, int menu_num ) { struct kconfig * cfg; + int i; printf( "\n\n\n" ); printf( "\tfocus $w\n" ); - printf( "\tupdate_menu%d $w.config.f\n", - menu_num ); + printf( "\tupdate_active\n" ); printf( "\tglobal winx; global winy\n" ); - printf( "\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n" ); + if ( menu_first[menu_num]->menu_number != 0 ) + { + printf( "\tif {[winfo exists .menu%d] == 0} then ", + menu_first[menu_num]->menu_number ); + printf( "{menu%d .menu%d \"%s\"}\n", + menu_first[menu_num]->menu_number, menu_first[menu_num]->menu_number, + menu_first[menu_first[menu_num]->menu_number]->label ); + printf( "\tset winx [expr [winfo x .menu%d]+30]; set winy [expr [winfo y .menu%d]+30]\n", + menu_first[menu_num]->menu_number, menu_first[menu_num]->menu_number ); + } + else + printf( "\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n" ); printf( "\twm geometry $w +$winx+$winy\n" ); /* @@ -660,27 +1005,12 @@ static void end_proc( struct kconfig * scfg, int menu_num ) * widgets, and will be called first when the window is mapped, * and each time one of the buttons in the window are clicked. */ - printf( "proc update_menu%d {w} {\n", menu_num ); - printf( "\tupdate_define\n" ); + printf( "proc update_menu%d {} {\n", menu_num ); /* * Clear all of the booleans that are defined in this menu. */ - clear_globalflags( scfg ); - for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) - { - if ( cfg->menu_number == menu_num && cfg->token == token_define_bool - && cfg->optionname != NULL ) - { - if ( ! cfg->global_written ) - { - cfg->global_written = 1; - printf( "\tglobal %s\n", cfg->optionname ); - printf( "\tset %s 0\n", cfg->optionname ); - } - } - } - + clear_globalflags(); for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { if ( cfg->menu_number == menu_num @@ -688,28 +1018,47 @@ static void end_proc( struct kconfig * scfg, int menu_num ) && cfg->token != token_choice_item ) { if ( cfg->cond != NULL ) + { + int i; + if ( (cfg->token == token_tristate || cfg->token == token_dep_tristate) + && ! vartable[i = get_varnum( "CONFIG_MODULES" )].global_written ) + { + global( "CONFIG_MODULES" ); + vartable[i].global_written = 1; + } generate_if( cfg, cfg->cond, cfg->menu_number, cfg->menu_line ); + } else { - /* - * Treat tristate like conditional here. - */ - if ( cfg->token == token_dep_tristate ) + if ( cfg->token == token_tristate ) { - global( cfg->depend ); - printf( "\tif {$%s != 1 && $%s != 0 } then { .menu%d.config.f.x%d.y configure -state disabled } else { .menu%d.config.f.x%d.y configure -state normal}\n", - cfg->depend, cfg->depend, + if ( ! vartable[cfg->nameindex].global_written ) + { + vartable[cfg->nameindex].global_written = 1; + printf( "\tglobal %s\n", vartable[cfg->nameindex].name ); + } + if ( ! vartable[i = get_varnum( "CONFIG_MODULES" )].global_written ) + { + global( "CONFIG_MODULES" ); + vartable[i].global_written = 1; + } + printf( "\n\tif {($CONFIG_MODULES == 1)} then {configure_entry .menu%d.config.f.x%d normal {m}} else {configure_entry .menu%d.config.f.x%d disabled {m}}\n", menu_num, cfg->menu_line, menu_num, cfg->menu_line ); } } } + else if ( cfg->token == token_mainmenu_option + && cfg->menu_number == menu_num + && cfg->cond != NULL ) + { + generate_if( cfg, cfg->cond, menu_num, cfg->menu_line ); + } } - printf("}\n\n\n"); -} - + generate_update_var( scfg, menu_num ); +} /* * This is the top level function for generating the tk script. @@ -718,18 +1067,20 @@ void dump_tk_script( struct kconfig * scfg ) { int menu_depth; int menu_num [64]; - struct kconfig * menu_first [256]; - struct kconfig * menu_last [256]; - int imenu; + int imenu, i; + int top_level_num = 0; struct kconfig * cfg; struct kconfig * cfg1 = NULL; const char * name = "No Name"; /* - * Thread the menu pointers so I can walk each menu separately. - */ + * Mark begin and end of each menu so I can omit submenus when walking + * over a parent menu. + */ tot_menu_num = 0; menu_depth = 0; + menu_num [0] = 0; + for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { switch ( cfg->token ) @@ -744,14 +1095,22 @@ void dump_tk_script( struct kconfig * scfg ) case token_mainmenu_option: if ( ++menu_depth >= 64 ) { fprintf( stderr, "menus too deep\n" ); exit( 1 ); } - if ( ++tot_menu_num >= 256 ) + if ( ++tot_menu_num >= 100 ) { fprintf( stderr, "too many menus\n" ); exit( 1 ); } menu_num [menu_depth] = tot_menu_num; menu_first [tot_menu_num] = cfg; menu_last [tot_menu_num] = cfg; + /* + * Note, that menu_number is set to the number of parent + * (upper level) menu. + */ + cfg->menu_number = menu_num[menu_depth - 1]; + if ( menu_depth == 1 ) + ++top_level_num; break; case token_endmenu: + menu_last [menu_num [menu_depth]] = cfg; /* flatten menus with proper scoping */ if ( --menu_depth < 0 ) { fprintf( stderr, "unmatched endmenu\n" ); exit( 1 ); } @@ -760,19 +1119,24 @@ void dump_tk_script( struct kconfig * scfg ) case token_bool: case token_choice_header: case token_choice_item: + case token_dep_bool: case token_dep_tristate: case token_hex: case token_int: case token_string: case token_tristate: + cfg->menu_number = menu_num[menu_depth]; if ( menu_depth == 0 ) { fprintf( stderr, "statement not in menu\n" ); exit( 1 ); } - menu_last [menu_num [menu_depth]]->menu_next = cfg; - menu_last [menu_num [menu_depth]] = cfg; - cfg->menu_next = NULL; break; case token_define_bool: + case token_define_hex: + case token_define_int: + case token_define_string: + case token_define_tristate: + case token_unset: + cfg->menu_number = menu_num[menu_depth]; break; } } @@ -784,7 +1148,21 @@ void dump_tk_script( struct kconfig * scfg ) * one blank button * add two to round up for division */ - printf( "set menus_per_column %d\n\n", (tot_menu_num + 4 + 1 + 2) / 3 ); + printf( "set menus_per_column %d\n", (top_level_num + 4 + 1 + 2) / 3 ); + printf( "set total_menus %d\n\n", tot_menu_num ); + + printf( "proc toplevel_menu {num} {\n" ); + for ( imenu = 1; imenu <= tot_menu_num; ++imenu ) + { + int parent = 1; + + if ( menu_first[imenu]->menu_number == 0 ) + parent = menu_first[imenu]->menu_number; + else + printf( "\tif {$num == %d} then {return %d}\n", + imenu, menu_first[imenu]->menu_number ); + } + printf( "\treturn $num\n}\n\n" ); /* * Generate the menus. @@ -793,24 +1171,33 @@ void dump_tk_script( struct kconfig * scfg ) for ( imenu = 1; imenu <= tot_menu_num; ++imenu ) { int menu_line = 0; + int nr_submenu = imenu; - clear_globalflags( scfg ); - start_proc( menu_first[imenu]->label, imenu, 1 ); + clear_globalflags(); + start_proc( menu_first[imenu]->label, imenu, + !menu_first[imenu]->menu_number ); - for ( cfg = menu_first[imenu]; cfg != NULL; cfg = cfg->menu_next ) + for ( cfg = menu_first[imenu]->next; cfg != NULL && cfg != menu_last[imenu]; cfg = cfg->next ) { - cfg->menu_number = imenu; - switch ( cfg->token ) { default: break; + case token_mainmenu_option: + while ( menu_first[++nr_submenu]->menu_number > imenu ) + ; + cfg->menu_line = menu_line++; + printf( "\tsubmenu $w.config.f %d %d \"%s\" %d\n", + cfg->menu_number, cfg->menu_line, cfg->label, nr_submenu ); + cfg = menu_last[nr_submenu]; + break; + case token_bool: cfg->menu_line = menu_line++; printf( "\tbool $w.config.f %d %d \"%s\" %s\n", cfg->menu_number, cfg->menu_line, cfg->label, - cfg->optionname ); + vartable[cfg->nameindex].name ); break; case token_choice_header: @@ -819,54 +1206,61 @@ void dump_tk_script( struct kconfig * scfg ) * help text from Documentation/Configure.help. */ cfg->menu_line = menu_line++; - printf( "\tglobal %s\n", cfg->optionname ); - printf( "\tminimenu $w.config.f %d %d \"%s\" %s %s\n", + printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) ); + printf( "\tminimenu $w.config.f %d %d \"%s\" tmpvar_%d %s\n", cfg->menu_number, cfg->menu_line, cfg->label, - cfg->optionname, cfg->next->optionname ); + -(cfg->nameindex), vartable[cfg->next->nameindex].name ); printf( "\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line ); cfg1 = cfg; break; case token_choice_item: /* note: no menu line; uses choice header menu line */ - printf( "\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable %s -value \"%s\" -command \"update_menu%d .menu%d.config.f\"\n", - cfg1->menu_line, cfg->label, cfg1->optionname, - cfg->label, cfg1->menu_number, cfg1->menu_number ); + printf( "\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable tmpvar_%d -value \"%s\" -command \"update_active\"\n", + cfg1->menu_line, cfg->label, -(cfg1->nameindex), + cfg->label ); + break; + + case token_dep_bool: + cfg->menu_line = menu_line++; + printf( "\tdep_bool $w.config.f %d %d \"%s\" %s\n", + cfg->menu_number, cfg->menu_line, cfg->label, + vartable[cfg->nameindex].name ); break; case token_dep_tristate: cfg->menu_line = menu_line++; - printf( "\tdep_tristate $w.config.f %d %d \"%s\" %s %s\n", + printf( "\tdep_tristate $w.config.f %d %d \"%s\" %s\n", cfg->menu_number, cfg->menu_line, cfg->label, - cfg->optionname, cfg->depend ); + vartable[cfg->nameindex].name ); break; case token_hex: cfg->menu_line = menu_line++; printf( "\thex $w.config.f %d %d \"%s\" %s\n", cfg->menu_number, cfg->menu_line, cfg->label, - cfg->optionname ); + vartable[cfg->nameindex].name ); break; case token_int: cfg->menu_line = menu_line++; printf( "\tint $w.config.f %d %d \"%s\" %s\n", cfg->menu_number, cfg->menu_line, cfg->label, - cfg->optionname ); + vartable[cfg->nameindex].name ); break; case token_string: cfg->menu_line = menu_line++; printf( "\tistring $w.config.f %d %d \"%s\" %s\n", cfg->menu_number, cfg->menu_line, cfg->label, - cfg->optionname ); + vartable[cfg->nameindex].name ); break; case token_tristate: cfg->menu_line = menu_line++; printf( "\ttristate $w.config.f %d %d \"%s\" %s\n", cfg->menu_number, cfg->menu_line, cfg->label, - cfg->optionname ); + vartable[cfg->nameindex].name ); break; } } @@ -875,36 +1269,21 @@ void dump_tk_script( struct kconfig * scfg ) } /* - * The top level menu also needs an update function. When we exit a + * The top level menu also needs an update function. When we update a * submenu, we may need to disable one or more of the submenus on * the top level menu, and this procedure will ensure that things are * correct. */ - clear_globalflags( scfg ); - printf( "proc update_mainmenu {w} {\n" ); - for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) + clear_globalflags(); + printf( "proc update_mainmenu {} {\n" ); + for ( imenu = 1; imenu <= tot_menu_num; imenu++ ) { - if ( cfg->token == token_mainmenu_option && cfg->cond != NULL ) - generate_if( cfg, cfg->cond, cfg->menu_number, cfg->menu_line ); + if ( menu_first[imenu]->cond != NULL && menu_first[imenu]->menu_number == 0 ) + generate_if( menu_first[imenu], menu_first[imenu]->cond, imenu, -1 ); } printf( "}\n\n\n" ); -#if 0 - /* - * Generate code to set the variables that are "defined". - */ - for ( cfg = config; cfg != NULL; cfg = cfg->next ) - { - if ( cfg->token == token_define_bool ) - { - if ( cfg->cond != NULL ) - generate_if( cfg, cfg->cond, menu_num, cfg->menu_line ); - else - printf( "\twrite_define %s %s\n", cfg->optionname, cfg->value ); - } - } - #endif - + clear_globalflags(); /* * Generate code to load the default settings into the variables. * The script in tail.tk will attempt to load .config, @@ -919,26 +1298,49 @@ void dump_tk_script( struct kconfig * scfg ) case token_bool: case token_choice_item: + case token_dep_bool: case token_dep_tristate: case token_tristate: - printf( "set %s 0\n", cfg->optionname ); + if ( ! vartable[cfg->nameindex].global_written ) + { + printf( "set %s 0\n", vartable[cfg->nameindex].name ); + vartable[cfg->nameindex].global_written = 1; + } break; case token_choice_header: - printf( "set %s \"(not set)\"\n", cfg->optionname ); + printf( "set tmpvar_%d \"(not set)\"\n", -(cfg->nameindex) ); break; case token_hex: case token_int: - printf( "set %s %s\n", cfg->optionname, cfg->value ? cfg->value : "0"); + if ( ! vartable[cfg->nameindex].global_written ) + { + printf( "set %s %s\n", vartable[cfg->nameindex].name, cfg->value ? cfg->value : "0" ); + vartable[cfg->nameindex].global_written = 1; + } break; case token_string: - printf( "set %s \"%s\"\n", cfg->optionname, cfg->value ? cfg->value : ""); + if ( ! vartable[cfg->nameindex].global_written ) + { + printf( "set %s \"%s\"\n", vartable[cfg->nameindex].name, cfg->value ); + vartable[cfg->nameindex].global_written = 1; + } break; } } + /* + * Define to an empty value all other variables (which are never defined) + */ + for ( i = 1; i <= max_varnum; i++ ) + { + if ( ! vartable[i].global_written + && strncmp( vartable[i].name, "CONSTANT_", 9 ) ) + printf( "set %s 4\n", vartable[i].name ); + } + /* * Generate a function to write all of the variables to a file. */ @@ -956,7 +1358,7 @@ void dump_tk_script( struct kconfig * scfg ) printf( "\tputs $autocfg \" */\"\n" ); printf( "\tputs $autocfg \"#define AUTOCONF_INCLUDED\"\n" ); - clear_globalflags( scfg ); + clear_globalflags(); for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { switch ( cfg->token ) @@ -968,6 +1370,11 @@ void dump_tk_script( struct kconfig * scfg ) case token_choice_header: case token_comment: case token_define_bool: + case token_define_hex: + case token_define_int: + case token_define_string: + case token_define_tristate: + case token_dep_bool: case token_dep_tristate: case token_hex: case token_int: @@ -996,7 +1403,8 @@ void dump_tk_script( struct kconfig * scfg ) cfg1 = cfg1->next ) { printf( "\tglobal %s; set %s 0\n", - cfg1->optionname, cfg1->optionname ); + vartable[cfg1->nameindex].name, + vartable[cfg1->nameindex].name ); } } } @@ -1007,41 +1415,22 @@ void dump_tk_script( struct kconfig * scfg ) { if ( cfg->token == token_choice_header ) { - printf( "\tglobal %s\n", cfg->optionname ); + printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) ); + printf("\tset tmpvar_%d \"%s\"\n", -(cfg->nameindex), cfg->value); for ( cfg1 = cfg->next; cfg1 != NULL && cfg1->token == token_choice_item; cfg1 = cfg1->next ) { - printf( "\tglobal %s\n", cfg1->optionname ); - printf( "\tif { $%s == 1 } then { set %s \"%s\" }\n", - cfg1->optionname, cfg->optionname, cfg1->label ); + printf( "\tglobal %s\n", vartable[cfg1->nameindex].name ); + printf( "\tif { $%s == 1 } then { set tmpvar_%d \"%s\" }\n", + vartable[cfg1->nameindex].name, + -(cfg->nameindex), cfg1->label ); } } } printf( "}\n\n\n" ); - printf( "proc update_define { } {\n" ); - clear_globalflags( scfg ); - for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) - { - if ( cfg->token == token_define_bool ) - { - cfg->global_written = 1; - printf( "\tglobal %s\n", cfg->optionname ); - } - } - - for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) - { - if( cfg->token == token_define_bool ) - { - if ( cfg->cond == NULL ) - printf( "\tset %s %s\n", cfg->optionname, cfg->value ); - else - generate_if( cfg, cfg->cond, -1, 0 ); - } - } - printf( "}\n\n\n" ); + generate_update_var( scfg, 0 ); /* * That's it. We are done. The output of this file will have header.tk diff --git a/scripts/tkparse.c b/scripts/tkparse.c index 4b593fd0a..86924a08d 100644 --- a/scripts/tkparse.c +++ b/scripts/tkparse.c @@ -29,6 +29,17 @@ * 23 January 1999, Michael Elizabeth Chastain, * - Remove bug-compatible code. * + * 07 July 1999, Andrzej M. Krzysztofowicz, + * - Submenus implemented, + * - plenty of option updating/displaying fixes, + * - dep_bool, define_hex, define_int, define_string, define_tristate and + * undef implemented, + * - dep_tristate fixed to support multiple dependencies, + * - handling of variables with an empty value implemented, + * - value checking for int and hex fields, + * - more checking during condition parsing; choice variables are treated as + * all others now, + * * TO DO: * - xconfig is at the end of its life cycle. Contact if * you are interested in working on the replacement. @@ -51,8 +62,6 @@ static void do_source( const char * ); int my_strcmp( const char * s1, const char * s2 ) { return strcmp( s1, s2 ); } #define strcmp my_strcmp - - /* * Report a syntax error. */ @@ -64,6 +73,30 @@ static void syntax_error( const char * msg ) +/* + * Find index of a specyfic variable in the symbol table. + * Create a new entry if it does not exist yet. + */ +#define VARTABLE_SIZE 2048 +struct variable vartable[VARTABLE_SIZE]; +int max_varnum = 0; + +int get_varnum( char * name ) +{ + int i; + + for ( i = 1; i <= max_varnum; i++ ) + if ( strcmp( vartable[i].name, name ) == 0 ) + return i; + if (max_varnum > VARTABLE_SIZE-1) + syntax_error( "Too many variables defined." ); + vartable[++max_varnum].name = malloc( strlen( name )+1 ); + strcpy( vartable[max_varnum].name, name ); + return max_varnum; +} + + + /* * Get a string. */ @@ -138,6 +171,7 @@ static const char * get_qstring( const char * pnt, char ** label ) } + /* * Tokenize an 'if' statement condition. */ @@ -145,6 +179,7 @@ static struct condition * tokenize_if( const char * pnt ) { struct condition * list; struct condition * last; + struct condition * prev; /* eat the open bracket */ while ( *pnt == ' ' || *pnt == '\t' ) @@ -170,30 +205,53 @@ static struct condition * tokenize_if( const char * pnt ) cond = malloc( sizeof(*cond) ); memset( cond, 0, sizeof(*cond) ); if ( last == NULL ) - { list = last = cond; } + { list = last = cond; prev = NULL; } else - { last->next = cond; last = cond; } + { prev = last; last->next = cond; last = cond; } /* determine the token value */ if ( *pnt == '-' && pnt[1] == 'a' ) - { cond->op = op_and; pnt += 2; continue; } + { + if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) ) + syntax_error( "incorrect argument" ); + cond->op = op_and; pnt += 2; continue; + } if ( *pnt == '-' && pnt[1] == 'o' ) - { cond->op = op_or; pnt += 2; continue; } + { + if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) ) + syntax_error( "incorrect argument" ); + cond->op = op_or; pnt += 2; continue; + } if ( *pnt == '!' && pnt[1] == '=' ) - { cond->op = op_neq; pnt += 2; continue; } + { + if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) ) + syntax_error( "incorrect argument" ); + cond->op = op_neq; pnt += 2; continue; + } if ( *pnt == '=' ) - { cond->op = op_eq; pnt += 1; continue; } + { + if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) ) + syntax_error( "incorrect argument" ); + cond->op = op_eq; pnt += 1; continue; + } if ( *pnt == '!' ) - { cond->op = op_bang; pnt += 1; continue; } + { + if ( prev && ( prev->op != op_and && prev->op != op_or + && prev->op != op_bang ) ) + syntax_error( "incorrect argument" ); + cond->op = op_bang; pnt += 1; continue; + } if ( *pnt == '"' ) { const char * word; + if ( prev && ( prev->op == op_variable || prev->op == op_constant ) ) + syntax_error( "incorrect argument" ); /* advance to the word */ pnt++; if ( *pnt == '$' ) @@ -217,7 +275,15 @@ static struct condition * tokenize_if( const char * pnt ) char * str = malloc( pnt - word + 1 ); memcpy( str, word, pnt - word ); str [pnt - word] = '\0'; - cond->str = str; + if ( cond->op == op_variable ) + { + cond->nameindex = get_varnum( str ); + free( str ); + } + else /* op_constant */ + { + cond->str = str; + } } pnt++; @@ -241,6 +307,7 @@ static const char * tokenize_choices( struct kconfig * cfg_choose, for ( ; ; ) { struct kconfig * cfg; + char * buffer = malloc( 64 ); /* skip whitespace */ while ( *pnt == ' ' || *pnt == '\t' ) @@ -262,7 +329,8 @@ static const char * tokenize_choices( struct kconfig * cfg_choose, pnt = get_string( pnt, &cfg->label ); while ( *pnt == ' ' || *pnt == '\t' ) pnt++; - pnt = get_string( pnt, &cfg->optionname ); + pnt = get_string( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); } return pnt; @@ -270,8 +338,6 @@ static const char * tokenize_choices( struct kconfig * cfg_choose, - - /* * Tokenize one line. */ @@ -280,6 +346,8 @@ static void tokenize_line( const char * pnt ) static struct kconfig * last_menuoption = NULL; enum e_token token; struct kconfig * cfg; + struct dependency ** dep_ptr; + char * buffer = malloc( 64 ); /* skip white space */ while ( *pnt == ' ' || *pnt == '\t' ) @@ -313,6 +381,11 @@ static void tokenize_line( const char * pnt ) case 'd': match_token( token_define_bool, "define_bool" ); + match_token( token_define_hex, "define_hex" ); + match_token( token_define_int, "define_int" ); + match_token( token_define_string, "define_string" ); + match_token( token_define_tristate, "define_tristate" ); + match_token( token_dep_bool, "dep_bool" ); match_token( token_dep_tristate, "dep_tristate" ); break; @@ -371,11 +444,13 @@ static void tokenize_line( const char * pnt ) syntax_error( "bogus 'then'" ); } +#if 0 if ( token == token_unset ) { fprintf( stderr, "Ignoring 'unset' command\n" ); return; } +#endif if ( token == token_UNKNOWN ) syntax_error( "unknown command" ); @@ -404,8 +479,9 @@ static void tokenize_line( const char * pnt ) case token_bool: case token_tristate: - pnt = get_qstring ( pnt, &cfg->label ); - pnt = get_string ( pnt, &cfg->optionname ); + pnt = get_qstring ( pnt, &cfg->label ); + pnt = get_string ( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); break; case token_choice_header: @@ -417,9 +493,7 @@ static void tokenize_line( const char * pnt ) pnt = get_qstring ( pnt, &choice_list ); pnt = get_string ( pnt, &cfg->value ); - cfg->optionname = malloc( 32 ); - sprintf( cfg->optionname, "tmpvar_%d", choose_number++ ); - + cfg->nameindex = -(choose_number++); tokenize_choices( cfg, choice_list ); free( choice_list ); } @@ -436,56 +510,133 @@ static void tokenize_line( const char * pnt ) break; case token_define_bool: - pnt = get_string( pnt, &cfg->optionname ); + case token_define_tristate: + pnt = get_string( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); while ( *pnt == ' ' || *pnt == '\t' ) pnt++; - if ( *pnt == 'n' || *pnt == 'N' ) cfg->value = "0"; - else if ( *pnt == 'y' || *pnt == 'Y' ) cfg->value = "1"; - else if ( *pnt == 'm' || *pnt == 'M' ) cfg->value = "2"; + if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N' + || pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' ) + && ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) ) + { + if ( *pnt == 'n' || *pnt == 'N' ) cfg->value = strdup( "CONSTANT_N" ); + else if ( *pnt == 'y' || *pnt == 'Y' ) cfg->value = strdup( "CONSTANT_Y" ); + else if ( *pnt == 'm' || *pnt == 'M' ) cfg->value = strdup( "CONSTANT_M" ); + } + else if ( *pnt == '$' ) + { + pnt++; + pnt = get_string( pnt, &cfg->value ); + } else { syntax_error( "unknown define_bool value" ); } + get_varnum( cfg->value ); + break; + + case token_define_hex: + case token_define_int: + pnt = get_string( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); + pnt = get_string( pnt, &cfg->value ); break; + case token_define_string: + pnt = get_string( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); + pnt = get_qstring( pnt, &cfg->value ); + break; + + case token_dep_bool: case token_dep_tristate: - pnt = get_qstring ( pnt, &cfg->label ); - pnt = get_string ( pnt, &cfg->optionname ); + pnt = get_qstring ( pnt, &cfg->label ); + pnt = get_string ( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); while ( *pnt == ' ' || *pnt == '\t' ) pnt++; - if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N' - || pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' ) - && ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) ) - { - /* dep_tristate 'foo' CONFIG_FOO m */ - if ( pnt[0] == 'Y' || pnt[0] == 'y' ) - cfg->depend = strdup( "CONSTANT_Y" ); - else if ( pnt[0] == 'M' || pnt[0] == 'm' ) - cfg->depend = strdup( "CONSTANT_M" ); + dep_ptr = &(cfg->depend); + + do { + *dep_ptr = (struct dependency *) malloc( sizeof( struct dependency ) ); + (*dep_ptr)->next = NULL; + + if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N' + || pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' ) + && ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) ) + { + /* dep_tristate 'foo' CONFIG_FOO m */ + if ( pnt[0] == 'Y' || pnt[0] == 'y' ) + (*dep_ptr)->name = strdup( "CONSTANT_Y" ); + else if ( pnt[0] == 'N' || pnt[0] == 'n' ) + (*dep_ptr)->name = strdup( "CONSTANT_N" ); + else + (*dep_ptr)->name = strdup( "CONSTANT_M" ); + pnt++; + get_varnum( (*dep_ptr)->name ); + } + else if ( *pnt == '$' ) + { + pnt++; + pnt = get_string( pnt, &(*dep_ptr)->name ); + get_varnum( (*dep_ptr)->name ); + } else - cfg->depend = strdup( "CONSTANT_N" ); - pnt++; - } - else if ( *pnt == '$' ) - { - pnt++; - pnt = get_string( pnt, &cfg->depend ); - } - else - { - syntax_error( "can't handle dep_tristate condition" ); - } + { + syntax_error( "can't handle dep_bool/dep_tristate condition" ); + } + dep_ptr = &(*dep_ptr)->next; + while ( *pnt == ' ' || *pnt == '\t' ) + pnt++; + } while ( *pnt ); /* - * Create a conditional for this object's dependency. + * Create a conditional for this object's dependencies. */ { char fake_if [1024]; - sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then", - cfg->depend, cfg->depend ); - cfg->cond = tokenize_if( fake_if ); + struct dependency * dep; + struct condition ** cond_ptr; + int first = 1; + + cond_ptr = &(cfg->cond); + for ( dep = cfg->depend; dep; dep = dep->next ) + { + if ( token == token_dep_tristate + && ! strcmp( dep->name, "CONSTANT_M" ) ) + { + continue; + } + if ( first ) + { + first = 0; + } + else + { + *cond_ptr = malloc( sizeof(struct condition) ); + memset( *cond_ptr, 0, sizeof(struct condition) ); + (*cond_ptr)->op = op_and; + cond_ptr = &(*cond_ptr)->next; + } + *cond_ptr = malloc( sizeof(struct condition) ); + memset( *cond_ptr, 0, sizeof(struct condition) ); + (*cond_ptr)->op = op_lparen; + if ( token == token_dep_tristate ) + sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" -o \"$%s\" = \"\" ]; then", + dep->name, dep->name, dep->name ); + else + sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"\" ]; then", + dep->name, dep->name ); + (*cond_ptr)->next = tokenize_if( fake_if ); + while ( *cond_ptr ) + cond_ptr = &(*cond_ptr)->next; + *cond_ptr = malloc( sizeof(struct condition) ); + memset( *cond_ptr, 0, sizeof(struct condition) ); + (*cond_ptr)->op = op_rparen; + cond_ptr = &(*cond_ptr)->next; + } } break; @@ -496,15 +647,17 @@ static void tokenize_line( const char * pnt ) case token_hex: case token_int: - pnt = get_qstring ( pnt, &cfg->label ); - pnt = get_string ( pnt, &cfg->optionname ); - pnt = get_string ( pnt, &cfg->value ); + pnt = get_qstring ( pnt, &cfg->label ); + pnt = get_string ( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); + pnt = get_string ( pnt, &cfg->value ); break; case token_string: - pnt = get_qstring ( pnt, &cfg->label ); - pnt = get_string ( pnt, &cfg->optionname ); - pnt = get_qstring ( pnt, &cfg->value ); + pnt = get_qstring ( pnt, &cfg->label ); + pnt = get_string ( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); + pnt = get_qstring ( pnt, &cfg->value ); break; case token_if: @@ -521,8 +674,25 @@ static void tokenize_line( const char * pnt ) else pnt = get_qstring( pnt, &cfg->label ); break; - } + case token_unset: + pnt = get_string( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); + while ( *pnt == ' ' || *pnt == '\t' ) + pnt++; + while (*pnt) + { + cfg->next = (struct kconfig *) malloc( sizeof(struct kconfig) ); + memset( cfg->next, 0, sizeof(struct kconfig) ); + cfg = cfg->next; + cfg->token = token_unset; + pnt = get_string( pnt, &buffer ); + cfg->nameindex = get_varnum( buffer ); + while ( *pnt == ' ' || *pnt == '\t' ) + pnt++; + } + break; + } return; } diff --git a/scripts/tkparse.h b/scripts/tkparse.h index 0478effed..ecb31b654 100644 --- a/scripts/tkparse.h +++ b/scripts/tkparse.h @@ -14,6 +14,11 @@ enum e_token token_choice_item, token_comment, token_define_bool, + token_define_hex, + token_define_int, + token_define_string, + token_define_tristate, + token_dep_bool, token_dep_tristate, token_else, token_endmenu, @@ -46,7 +51,8 @@ enum operator op_rparen, op_constant, op_variable, - op_kvariable, + op_true, + op_false, op_nuked }; @@ -55,21 +61,29 @@ enum operator * Some operators take strings: * * op_constant "foo" - * op_variable "$ARCH", "$CONFIG_PMAC" - * op_kvariable "$CONFIG_EXPERIMENTAL" + * op_variable "$ARCH", "$CONFIG_PMAC", "$CONFIG_EXPERIMENTAL" * * Most "$..." constructs refer to a variable which is defined somewhere - * in the script, so they become op_kvariable's instead. Note that it - * is legal to test variables which are never defined, such as variables - * that are meaningful only on other architectures. + * in the script. Note that it is legal to test variables which are never + * defined, such as variables that are meaningful only on other architectures. */ struct condition { - struct condition * next; - enum operator op; - const char * str; /* op_constant, op_variable */ - struct kconfig * cfg; /* op_kvariable */ + struct condition * next; + enum operator op; + const char * str; /* op_constant */ + int nameindex; /* op_variable */ +}; + +/* + * Dependency list for dep_bool, dep_tristate + */ + +struct dependency +{ + char * name; + struct dependency * next; }; /* @@ -80,21 +94,28 @@ struct kconfig { struct kconfig * next; enum e_token token; - char * optionname; + int nameindex; char * label; char * value; struct condition * cond; - char * depend; /* token_dep_tristate */ + struct dependency * depend; /* token_dep_tristate */ struct kconfig * cfg_parent; /* token_choice_item */ /* used only in tkgen.c */ - char global_written; int menu_number; int menu_line; struct kconfig * menu_next; }; +struct variable +{ + char * name; + char defined; + char global_written; +}; +extern struct variable vartable[]; +extern int max_varnum; /* * Prototypes @@ -102,3 +123,4 @@ struct kconfig extern void fix_conditionals ( struct kconfig * scfg ); /* tkcond.c */ extern void dump_tk_script ( struct kconfig * scfg ); /* tkgen.c */ +extern int get_varnum ( char * name ); /* tkparse.c */ diff --git a/scripts/ver_linux b/scripts/ver_linux index a1b8642a4..b885791dd 100644 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -5,7 +5,7 @@ # differ on your system. # PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH -echo '-- Versions installed: (if some fields are empty or looks' +echo '-- Versions installed: (if some fields are empty or look' echo '-- unusual then possibly you have very old versions)' uname -a insmod -V 2>&1 | awk 'NR==1 {print "Kernel modules ",$NF}' -- cgit v1.2.3