summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
committer <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
commitbeb116954b9b7f3bb56412b2494b562f02b864b1 (patch)
tree120e997879884e1b9d93b265221b939d2ef1ade1 /scripts
parent908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff)
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Configure472
-rw-r--r--scripts/MAKEDEV.ide37
-rw-r--r--scripts/Makefile47
-rw-r--r--scripts/Menuconfig1232
-rw-r--r--scripts/README.Menuconfig194
-rw-r--r--scripts/depend.awk154
-rw-r--r--scripts/header.tk440
-rw-r--r--scripts/hfiles.sh11
-rw-r--r--scripts/ksymoops.cc325
-rw-r--r--scripts/lxdialog/BIG.FAT.WARNING4
-rw-r--r--scripts/lxdialog/Makefile46
-rw-r--r--scripts/lxdialog/checklist.c344
-rw-r--r--scripts/lxdialog/colors.h161
-rw-r--r--scripts/lxdialog/dialog.h166
-rw-r--r--scripts/lxdialog/inputbox.c232
-rw-r--r--scripts/lxdialog/lxdialog.c223
-rw-r--r--scripts/lxdialog/menubox.c350
-rw-r--r--scripts/lxdialog/msgbox.c77
-rw-r--r--scripts/lxdialog/textbox.c537
-rw-r--r--scripts/lxdialog/util.c359
-rw-r--r--scripts/lxdialog/yesno.c110
-rw-r--r--scripts/mkdep.c297
-rw-r--r--scripts/patch-kernel53
-rw-r--r--scripts/pathdown.sh13
-rw-r--r--scripts/tail.tk78
-rw-r--r--scripts/tkcond.c542
-rw-r--r--scripts/tkgen.c1132
-rw-r--r--scripts/tkparse.c751
-rw-r--r--scripts/tkparse.h82
29 files changed, 8469 insertions, 0 deletions
diff --git a/scripts/Configure b/scripts/Configure
new file mode 100644
index 000000000..9bea73153
--- /dev/null
+++ b/scripts/Configure
@@ -0,0 +1,472 @@
+#! /bin/sh
+#
+# This script is used to configure the linux kernel.
+#
+# It was inspired by the challenge in the original Configure script
+# to ``do something better'', combined with the actual need to ``do
+# something better'' because the old configure script wasn't flexible
+# enough.
+#
+# Please send comments / questions / bug fixes to raymondc@microsoft.com.
+#
+# ***** IMPORTANT COMPATIBILITY NOTE ****
+# If configuration changes are made which might adversely effect
+# Menuconfig or xconfig, please notify the respective authors so that
+# those utilities can be updated in parallel.
+#
+# Menuconfig: <roadcapw@cfw.com>
+# xconfig: <apenwarr@foxnet.net> <eric@aib.com>
+# ****************************************
+#
+# Each line in the config file is a command.
+#
+# 050793 - use IFS='@' to get around a bug in a pre-version of bash-1.13
+# with an empty IFS.
+#
+# 030995 (storner@osiris.ping.dk) - added support for tri-state answers,
+# for selecting modules to compile.
+#
+# 180995 Bernhard Kaindl (bkaindl@ping.at) - added dummy functions for
+# use with a config.in modified for make menuconfig.
+#
+# 301195 (boldt@math.ucsb.edu) - added help text support
+#
+# 281295 Paul Gortmaker - make tri_state functions collapse to boolean
+# if module support is not enabled.
+#
+# 010296 Aaron Ucko (ucko@vax1.rockhurst.edu) - fix int and hex to accept
+# arbitrary ranges
+#
+# 150296 Dick Streefland (dicks@tasking.nl) - report new configuration
+# items and ask for a value even when doing a "make oldconfig"
+#
+# 200396 Tom Dyas (tdyas@eden.rutgers.edu) - when the module option is
+# chosen for an item, define the macro <option_name>_MODULE
+
+#
+# Make sure we're really running bash.
+#
+# I would really have preferred to write this script in a language with
+# better string handling, but alas, bash is the only scripting language
+# that I can be reasonable sure everybody has on their linux machine.
+#
+[ -z "$BASH" ] && { echo "Configure requires bash" 1>&2; exit 1; }
+
+# Disable filename globbing once and for all.
+# Enable function cacheing.
+set -f -h
+
+#
+# Dummy functions for use with a config.in modified for menuconf
+#
+function mainmenu_option () {
+ :
+}
+function mainmenu_name () {
+ :
+}
+function endmenu () {
+ :
+}
+
+#
+# help prints the corresponding help text from Configure.help to stdout
+#
+# help variable
+#
+function help () {
+ if [ -f Documentation/Configure.help ]
+ then
+ #first escape regexp special characters in the argument:
+ var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g')
+ #now pick out the right help text:
+ text=$(sed -n "/^$var[ ]*\$/,\${
+ /^$var[ ]*\$/b
+ /^#.*/b
+ /^[ ]*\$/q
+ p
+ }" Documentation/Configure.help)
+ if [ -z "$text" ]
+ then
+ echo; echo " Sorry, no help available for this option yet.";echo
+ else
+ (echo; echo "$text"; echo) | ${PAGER:-more}
+ fi
+ else
+ echo;
+ echo " Can't access the file Documentation/Configure.help which"
+ echo " should contain the help texts."
+ echo
+ fi
+}
+
+
+#
+# readln reads a line into $ans.
+#
+# readln prompt default oldval
+#
+function readln () {
+ if [ "$DEFAULT" = "-d" -a -n "$3" ]; then
+ echo "$1"
+ ans=$2
+ else
+ echo -n "$1"
+ [ -z "$3" ] && echo -n "(NEW) "
+ IFS='@' read ans </dev/tty || exit 1
+ [ -z "$ans" ] && ans=$2
+ fi
+}
+
+#
+# comment does some pretty-printing
+#
+# comment 'xxx'
+#
+function comment () {
+ echo "*"; echo "* $1" ; echo "*"
+ (echo "" ; echo "#"; echo "# $1" ; echo "#") >>$CONFIG
+ (echo "" ; echo "/*"; echo " * $1" ; echo " */") >>$CONFIG_H
+}
+
+#
+# define_bool sets the value of a boolean argument
+#
+# define_bool define value
+#
+function define_bool () {
+ case "$2" in
+ "y")
+ echo "$1=y" >>$CONFIG
+ echo "#define $1 1" >>$CONFIG_H
+ ;;
+
+ "m")
+ echo "$1=m" >>$CONFIG
+ echo "#undef $1" >>$CONFIG_H
+ echo "#define $1_MODULE 1" >>$CONFIG_H
+ ;;
+
+ "n")
+ echo "# $1 is not set" >>$CONFIG
+ echo "#undef $1" >>$CONFIG_H
+ ;;
+ esac
+ eval "$1=$2"
+}
+
+#
+# bool processes a boolean argument
+#
+# bool question define
+#
+function bool () {
+ old=$(eval echo "\${$2}")
+ def=${old:-'n'}
+ case "$def" in
+ "y" | "m") defprompt="Y/n/?"
+ def="y"
+ ;;
+ "n") defprompt="N/y/?"
+ ;;
+ esac
+ while :; do
+ readln "$1 ($2) [$defprompt] " "$def" "$old"
+ case "$ans" in
+ [yY] | [yY]es ) define_bool "$2" "y"
+ break;;
+ [nN] | [nN]o ) define_bool "$2" "n"
+ break;;
+ * ) help "$2"
+ ;;
+ esac
+ done
+}
+
+#
+# tristate processes a tristate argument
+#
+# tristate question define
+#
+function tristate () {
+ if [ "$CONFIG_MODULES" != "y" ]; then
+ bool "$1" "$2"
+ else
+ old=$(eval echo "\${$2}")
+ def=${old:-'n'}
+ case "$def" in
+ "y") defprompt="Y/m/n/?"
+ ;;
+ "m") defprompt="M/n/y/?"
+ ;;
+ "n") defprompt="N/y/m/?"
+ ;;
+ esac
+ while :; do
+ readln "$1 ($2) [$defprompt] " "$def" "$old"
+ case "$ans" in
+ [yY] | [yY]es ) define_bool "$2" "y"
+ break ;;
+ [nN] | [nN]o ) define_bool "$2" "n"
+ break ;;
+ [mM] ) define_bool "$2" "m"
+ break ;;
+ * ) help "$2"
+ ;;
+ esac
+ done
+ fi
+}
+
+#
+# dep_tristate processes a tristate argument that depends upon
+# another option. If the option we depend upon is a module,
+# then the only allowable options are M or N. If Y, then
+# this is a normal tristate. This is used in cases where modules
+# are nested, and one module requires the presence of something
+# else in the kernel.
+#
+# tristate question define default
+#
+function dep_tristate () {
+ old=$(eval echo "\${$2}")
+ def=${old:-'n'}
+ if [ "$3" = "n" ]; then
+ define_bool "$2" "n"
+ elif [ "$3" = "y" ]; then
+ tristate "$1" "$2"
+ else
+ if [ "$CONFIG_MODULES" = "y" ]; then
+ case "$def" in
+ "y" | "m") defprompt="M/n/?"
+ def="m"
+ ;;
+ "n") defprompt="N/m/?"
+ ;;
+ esac
+ while :; do
+ readln "$1 ($2) [$defprompt] " "$def" "$old"
+ case "$ans" in
+ [nN] | [nN]o ) define_bool "$2" "n"
+ break ;;
+ [mM] ) define_bool "$2" "m"
+ break ;;
+ [yY] | [yY]es ) echo
+ echo " This answer is not allowed, because it is not consistent with"
+ echo " your other choices."
+ echo " This driver depends on another one which you chose to compile"
+ echo " as a module. This means that you can either compile this one"
+ echo " as a module as well (with M) or leave it out altogether (N)."
+ echo
+ ;;
+ * ) help "$2"
+ ;;
+ esac
+ done
+ fi
+ fi
+}
+
+#
+# define_int sets the value of a integer argument
+#
+# define_int define value
+#
+function define_int () {
+ echo "$1=$2" >>$CONFIG
+ echo "#define $1 ($2)" >>$CONFIG_H
+ eval "$1=$2"
+}
+
+#
+# int processes an integer argument
+#
+# int question define default
+#
+function int () {
+ old=$(eval echo "\${$2}")
+ def=${old:-$3}
+ while :; do
+ readln "$1 ($2) [$def] " "$def" "$old"
+ if expr "$ans" : '0$\|-?[1-9][0-9]*$' > /dev/null; then
+ define_int "$2" "$ans"
+ break
+ else
+ help "$2"
+ fi
+ done
+}
+#
+# define_hex sets the value of a hexadecimal argument
+#
+# define_hex define value
+#
+function define_hex () {
+ echo "$1=$2" >>$CONFIG
+ echo "#define $1 0x${2#*[x,X]}" >>$CONFIG_H
+ eval "$1=$2"
+}
+
+#
+# hex processes an hexadecimal argument
+#
+# hex question define default
+#
+function hex () {
+ old=$(eval echo "\${$2}")
+ def=${old:-$3}
+ def=${def#*[x,X]}
+ while :; do
+ readln "$1 ($2) [$def] " "$def" "$old"
+ ans=${ans#*[x,X]}
+ if expr "$ans" : '[0-9a-fA-F]+$' > /dev/null; then
+ define_hex "$2" "$ans"
+ break
+ else
+ help "$2"
+ fi
+ done
+}
+
+#
+# choice processes a choice list (1-out-of-n)
+#
+# choice question choice-list default
+#
+# The choice list has a syntax of:
+# NAME WHITESPACE VALUE { WHITESPACE NAME WHITESPACE VALUE }
+# The user may enter any unique prefix of one of the NAMEs and
+# choice will define VALUE as if it were a boolean option.
+# VALUE must be in all uppercase. Normally, VALUE is of the
+# form CONFIG_<something>. Thus, if the user selects <something>,
+# the CPP symbol CONFIG_<something> will be defined and the
+# shell variable CONFIG_<something> will be set to "y".
+#
+function choice () {
+ question="$1"
+ choices="$2"
+ old=
+ def=$3
+
+ # determine default answer:
+ names=""
+ set -- $choices
+ firstvar=$2
+ while [ -n "$2" ]; do
+ if [ -n "$names" ]; then
+ names="$names, $1"
+ else
+ names="$1"
+ fi
+ if [ "$(eval echo \"\${$2}\")" = "y" ]; then
+ old=$1
+ def=$1
+ fi
+ shift; shift
+ done
+
+ val=""
+ while [ -z "$val" ]; do
+ ambg=n
+ readln "$question ($names) [$def] " "$def" "$old"
+ ans=$(echo $ans | tr a-z A-Z)
+ set -- $choices
+ while [ -n "$1" ]; do
+ name=$(echo $1 | tr a-z A-Z)
+ case "$name" in
+ "$ans"* )
+ if [ "$name" = "$ans" ]; then
+ val="$2"
+ break # stop on exact match
+ fi
+ if [ -n "$val" ]; then
+ echo;echo \
+ " Sorry, \"$ans\" is ambiguous; please enter a longer string."
+ echo
+ val=""
+ ambg=y
+ break
+ else
+ val="$2"
+ fi;;
+ esac
+ shift; shift
+ done
+ if [ "$val" = "" -a "$ambg" = "n" ]; then
+ help "$firstvar"
+ fi
+ done
+ set -- $choices
+ while [ -n "$2" ]; do
+ if [ "$2" = "$val" ]; then
+ echo " defined $val"
+ define_bool "$2" "y"
+ else
+ define_bool "$2" "n"
+ fi
+ shift; shift
+ done
+}
+
+CONFIG=.tmpconfig
+CONFIG_H=.tmpconfig.h
+trap "rm -f $CONFIG $CONFIG_H ; exit 1" 1 2
+
+#
+# Make sure we start out with a clean slate.
+#
+echo "#" > $CONFIG
+echo "# Automatically generated make config: don't edit" >> $CONFIG
+echo "#" >> $CONFIG
+
+echo "/*" > $CONFIG_H
+echo " * Automatically generated C config: don't edit" >> $CONFIG_H
+echo " */" >> $CONFIG_H
+
+DEFAULT=""
+if [ "$1" = "-d" ] ; then
+ DEFAULT="-d"
+ shift
+fi
+
+CONFIG_IN=./config.in
+if [ "$1" != "" ] ; then
+ CONFIG_IN=$1
+fi
+
+DEFAULTS=arch/$ARCH/defconfig
+if [ -f .config ]; then
+ DEFAULTS=.config
+fi
+
+if [ -f $DEFAULTS ]; then
+ echo "#"
+ echo "# Using defaults found in" $DEFAULTS
+ echo "#"
+ . $DEFAULTS
+ sed -e 's/# \(.*\) is not.*/\1=n/' < $DEFAULTS > /tmp/conf.$$
+ . /tmp/conf.$$
+ rm /tmp/conf.$$
+else
+ echo "#"
+ echo "# No defaults found"
+ echo "#"
+fi
+
+. $CONFIG_IN
+
+rm -f .config.old
+if [ -f .config ]; then
+ mv .config .config.old
+fi
+mv .tmpconfig .config
+mv .tmpconfig.h include/linux/autoconf.h
+
+echo
+echo "The linux kernel is now hopefully configured for your setup."
+echo "Check the top-level Makefile for additional configuration,"
+echo "and do a 'make dep ; make clean' if you want to be sure all"
+echo "the files are correctly re-made"
+echo
+
+exit 0
diff --git a/scripts/MAKEDEV.ide b/scripts/MAKEDEV.ide
new file mode 100644
index 000000000..6476860b7
--- /dev/null
+++ b/scripts/MAKEDEV.ide
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# This script creates the proper /dev/ entries for IDE devices
+# on the primary, secondary, tertiary, and quaternary interfaces.
+# See ../Documentation/ide.txt for more information.
+#
+makedev () {
+ rm -f /dev/$1
+ echo mknod /dev/$1 $2 $3 $4
+ mknod /dev/$1 $2 $3 $4
+ chown root:disk /dev/$1
+ chmod 660 /dev/$1
+}
+
+makedevs () {
+ rm -f /dev/$1*
+ makedev $1 b $2 $3
+ for part in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ makedev $1$part b $2 `expr $3 + $part`
+ done
+}
+
+makedevs hda 3 0
+makedevs hdb 3 64
+makedevs hdc 22 0
+makedevs hdd 22 64
+makedevs hde 33 0
+makedevs hdf 33 64
+makedevs hdg 34 0
+makedevs hdh 34 64
+
+for tape in 0 1 2 3 4 5 6 7
+do
+ makedev ht$tape c 37 $tape
+ makedev nht$tape c 37 `expr $tape + 128`
+done
diff --git a/scripts/Makefile b/scripts/Makefile
new file mode 100644
index 000000000..a214e709e
--- /dev/null
+++ b/scripts/Makefile
@@ -0,0 +1,47 @@
+HOSTCFLAGS:=$(HOSTCFLAGS) -g -Wall
+HEADER=header.tk
+TAIL=tail.tk
+
+# We allow the Makefile in drivers/sound to decide when to rebuild its
+# files, rather than trying to second-guess it like we did before.
+#
+soundscript:
+ make -C ${TOPDIR}/drivers/sound mkscript
+ @echo
+
+# There is probably a better way to decide when to rebuild kconfig.tk; this
+# one won't catch every last change to the various Config.in files. However,
+# the reliance on ${TOPDIR}/Makefile makes sure we at least rebuild when the
+# kernel version number changes.
+#
+kconfig.tk: soundscript ${TOPDIR}/Makefile ${TOPDIR}/arch/${ARCH}/config.in \
+ tkparse ${HEADER} ${TAIL}
+ ./tkparse < ../arch/${ARCH}/config.in > kconfig.tmp
+ @if [ -f /usr/local/bin/wish ]; then \
+ echo '#!'"/usr/local/bin/wish -f" > kconfig.tk; \
+ else \
+ echo '#!'"/usr/bin/wish -f" > kconfig.tk; \
+ fi
+ cat ${HEADER} >> ./kconfig.tk
+ cat kconfig.tmp >> kconfig.tk
+ rm -f kconfig.tmp
+ echo "set defaults \"arch/${ARCH}/defconfig\"" >> kconfig.tk
+ cat ${TAIL} >> kconfig.tk
+ chmod 755 kconfig.tk
+
+tkparse: tkparse.o tkcond.o tkgen.o
+ ${HOSTCC} -o tkparse tkparse.o tkcond.o tkgen.o
+
+tkparse.o: tkparse.c tkparse.h
+ $(HOSTCC) $(HOSTCFLAGS) -c -o tkparse.o tkparse.c
+
+tkcond.o: tkcond.c tkparse.h
+ $(HOSTCC) $(HOSTCFLAGS) -c -o tkcond.o tkcond.c
+
+tkgen.o: tkgen.c tkparse.h
+ $(HOSTCC) $(HOSTCFLAGS) -c -o tkgen.o tkgen.c
+
+clean:
+ rm -f *~ kconfig.tk *.o tkparse
+
+include $(TOPDIR)/Rules.make
diff --git a/scripts/Menuconfig b/scripts/Menuconfig
new file mode 100644
index 000000000..2f0f8c765
--- /dev/null
+++ b/scripts/Menuconfig
@@ -0,0 +1,1232 @@
+#! /bin/sh
+#
+# This script is used to configure the linux kernel.
+#
+# It was inspired by a desire to not have to hit <enter> 9 million times
+# or startup the X server just to change a single kernel parameter.
+#
+# This script attempts to parse the configuration files, which are
+# scattered throughout the kernel source tree, and creates a temporary
+# set of mini scripts which are in turn used to create nested menus and
+# radiolists.
+#
+# It uses a very modified/mutilated version of the "dialog" utility
+# written by Savio Lam (lam836@cs.cuhk.hk). Savio is not responsible
+# for this script or the version of dialog used by this script.
+# Please do not contact him with questions. The official version of
+# dialog is available at sunsite.unc.edu or a sunsite mirror.
+#
+# Portions of this script were borrowed from the original Configure
+# script.
+#
+# Please send comments / questions / bug fixes to roadcapw@cfw.com
+#
+#----------------------------------------------------------------------------
+
+
+#
+# Change this to TRUE if you prefer all kernel options listed
+# in a single menu rather than the standard menu hierarchy.
+#
+single_menu_mode=
+
+#
+# Make sure we're really running bash.
+#
+[ -z "$BASH" ] && { echo "Menuconfig requires bash" 1>&2; exit 1; }
+
+#
+# Cache function definitions, turn off posix compliance
+#
+set -h +o posix
+
+
+
+
+
+#
+# Load the functions used by the config.in files.
+#
+# I do this because these functions must be redefined depending
+# on whether they are being called for interactive use or for
+# saving a configuration to a file.
+#
+# Thank the heavens bash supports nesting function definitions.
+#
+load_functions () {
+
+#
+# Additional comments
+#
+function comment () {
+ comment_ctr=$[ comment_ctr + 1 ]
+ echo -ne "': $comment_ctr' '--- $1' " >>MCmenu
+}
+
+#
+# Don't need this yet, but we don't want to puke either.
+#
+function define_bool () {
+ :
+}
+
+#
+# Create a boolean (Yes/No) function for our current menu
+# which calls our local bool function.
+#
+function bool () {
+ eval $2=\${$2:-'n'} x=\$$2
+
+ case $x in
+ y|m) flag="*" ;;
+ n) flag=" " ;;
+ esac
+
+ echo -ne "'$2' '[$flag] $1' " >>MCmenu
+
+ echo -e "function $2 () { l_bool '$2' \"\$1\" ;}\n" >>MCradiolists
+}
+
+#
+# Create a tristate (Yes/No/Module) radiolist function
+# which calls our local tristate function.
+#
+# Collapses to a boolean (Yes/No) if module support is disabled.
+#
+function tristate () {
+ if [ "$CONFIG_MODULES" != "y" ]
+ then
+ bool "$1" "$2"
+ else
+ eval $2=\${$2:-'n'} x=\$$2
+
+ case $x in
+ y) flag="*" ;;
+ m) flag="M" ;;
+ *) flag=" " ;;
+ esac
+
+ echo -ne "'$2' '<$flag> $1' " >>MCmenu
+
+ echo -e "
+ function $2 () { l_tristate '$2' \"\$1\" ;}" >>MCradiolists
+ fi
+}
+
+#
+# Create a tristate radiolist function which is dependent on
+# another kernel configuration option.
+#
+# Quote from the original configure script:
+#
+# If the option we depend upon is a module,
+# then the only allowable options are M or N. If Y, then
+# this is a normal tristate. This is used in cases where modules
+# are nested, and one module requires the presence of something
+# else in the kernel.
+#
+function dep_tristate () {
+ if [ "$CONFIG_MODULES" != "y" ]
+ then
+ bool "$1" "$2"
+ else
+ if eval [ "_$3" != "_m" ]
+ then
+ tristate "$1" "$2" $3
+ else
+ mod_bool "$1" "$2"
+ fi
+ fi
+}
+
+#
+# Add a menu item which will call our local int function.
+#
+function int () {
+ eval $2=\${$2:-"$3"} x=\$$2
+
+ echo -ne "'$2' '($x) $1' " >>MCmenu
+
+ echo -e "function $2 () { l_int '$1' '$2' '$3' '$x' ;}" >>MCradiolists
+}
+
+#
+# Add a menu item which will call our local int function.
+#
+function hex () {
+ eval $2=\${$2:-"$3"} x=\${$2##*[x,X]}
+
+ echo -ne "'$2' '($x) $1' " >>MCmenu
+
+ echo -e "function $2 () { l_hex '$1' '$2' '$3' '$x' ;}" >>MCradiolists
+}
+
+#
+# Add a menu item which will call our local One-of-Many choice list.
+#
+function choice () {
+ #
+ # Need to remember params cause they're gonna get reset.
+ #
+ title=$1
+ choices=$2
+ default=$3
+ current=
+
+ #
+ # Find out if one of the choices is already set.
+ # If it's not then make it the default.
+ #
+ set -- $choices
+ firstchoice=$2
+
+ while [ -n "$2" ]
+ do
+ if eval [ "_\$$2" = "_y" ]
+ then
+ current=$1
+ break
+ fi
+ shift ; shift
+ done
+
+ : ${current:=$default}
+
+ echo -ne "'$firstchoice' '($current) $title' " >>MCmenu
+
+ echo -e "
+ function $firstchoice () \
+ { l_choice '$title' \"$choices\" $current ;}" >>MCradiolists
+}
+
+} # END load_functions()
+
+
+
+
+
+#
+# Extract available help for an option from Configure.help
+# and send it to standard output.
+#
+# Most of this function was borrowed from the original kernel
+# Configure script.
+#
+function extract_help () {
+ if [ -f Documentation/Configure.help ]
+ then
+ #first escape regexp special characters in the argument:
+ var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g')
+ #now pick out the right help text:
+ text=$(sed -n "/^$var[ ]*\$/,\${
+ /^$var[ ]*\$/d
+ /^#.*/d
+ /^[ ]*\$/q
+ s/^ //
+ p
+ }" Documentation/Configure.help)
+
+ if [ -z "$text" ]
+ then
+ echo "There is no help available for this kernel option."
+ return 1
+ else
+ echo "$text"
+ fi
+ else
+ echo "There is no help available for this kernel option."
+ return 1
+ fi
+}
+
+#
+# Activate a help dialog.
+#
+function help () {
+ if extract_help $1 >help.out
+ then
+ $DIALOG --backtitle "$backtitle" --title "$2"\
+ --textbox help.out $ROWS $COLS
+ else
+ $DIALOG --backtitle "$backtitle" \
+ --textbox help.out $ROWS $COLS
+ fi
+ rm help.out
+}
+
+#
+# Show the README file.
+#
+function show_readme () {
+ $DIALOG --backtitle "$backtitle" \
+ --textbox scripts/README.Menuconfig $ROWS $COLS
+}
+
+#
+# Begin building the dialog menu command and Initialize the
+# Radiolist function file.
+#
+function menu_name () {
+ echo -ne "$DIALOG --title '$1'\
+ --backtitle '$backtitle' \
+ --menu '$menu_instructions' \
+ $ROWS $COLS $((ROWS-10)) \
+ '$default' " >MCmenu
+ >MCradiolists
+}
+
+#
+# Add a submenu option to the menu currently under construction.
+#
+function submenu () {
+ echo -ne "'activate_menu $2' '$1 --->' " >>MCmenu
+}
+
+#
+# Create a menu entry to handle the traditional sound configuration.
+#
+function soundcfg () {
+ echo -ne "'l_soundcfg' "\
+ "'Old configuration script "\
+ "(For: SM Wave, PSS & AudioTrix Pro) -->' " >>MCmenu
+}
+
+#
+# Startup the traditional sound configuration program.
+#
+function l_soundcfg () {
+ clear
+ $MAKE -C drivers/sound config
+}
+
+#
+# Handle a boolean (Yes/No) option.
+#
+function l_bool () {
+ if [ -n "$2" ]
+ then
+ case "$2" in
+ y|m) eval $1=y ;;
+ c) eval x=\$$1
+ case $x in
+ y) eval $1=n ;;
+ n) eval $1=y ;;
+ esac ;;
+ *) eval $1=n ;;
+ esac
+ else
+ echo -ne "\007"
+ fi
+}
+
+#
+# Same as bool() except options are (Module/No)
+#
+function mod_bool () {
+ eval $2=\${$2:-'n'} x=\$$2
+
+ case $x in
+ y|m) flag='M' ;;
+ *) flag=' ' ;;
+ esac
+
+ echo -ne "'$2' '<$flag> $1' " >>MCmenu
+
+ echo -e "function $2 () { l_mod_bool '$2' \"\$1\" ;}" >>MCradiolists
+}
+
+#
+# Same as l_bool() except options are (Module/No)
+#
+function l_mod_bool() {
+ if [ -n "$2" ]
+ then
+ case "$2" in
+ y) echo -en "\007"
+ ${DIALOG} --backtitle "$backtitle" \
+ --infobox "\
+This feature depends on another which has been configured as a module. \
+As a result, this feature will be built as a module." 4 70
+ sleep 5
+ eval $1=m ;;
+ m) eval $1=m ;;
+ c) eval x=\$$1
+ case $x in
+ m) eval $1=n ;;
+ n) eval $1=m ;;
+ esac ;;
+ *) eval $1=n ;;
+ esac
+ else
+ echo -ne "\007"
+ fi
+}
+
+#
+# Handle a tristate (Yes/No/Module) option.
+#
+function l_tristate () {
+ if [ -n "$2" ]
+ then
+ eval x=\$$1
+
+ case "$2" in
+ y) eval $1=y ;;
+ m) eval $1=m ;;
+ c) eval x=\$$1
+ case $x in
+ y) eval $1=n ;;
+ n) eval $1=m ;;
+ m) eval $1=y ;;
+ esac ;;
+ *) eval $1=n ;;
+ esac
+ else
+ echo -ne "\007"
+ fi
+}
+
+#
+# Create a dialog for entering an integer into a kernel option.
+#
+function l_int () {
+ while true
+ do
+ if $DIALOG --title "$1" \
+ --backtitle "$backtitle" \
+ --inputbox "$inputbox_instructions_int" \
+ 10 75 "$4" 2>MCdialog.out
+ then
+ answer="`cat MCdialog.out`"
+ answer="${answer:-$3}"
+
+ if expr $answer : '0$\|-?[1-9][0-9]*$' >/dev/null
+ then
+ eval $2="$answer"
+ else
+ eval $2="$3"
+ echo -en "\007"
+ ${DIALOG} --backtitle "$backtitle" \
+ --infobox "You have made an invalid entry." 3 43
+ sleep 2
+ fi
+
+ break
+ fi
+
+ help "$2" "$1"
+ done
+}
+
+#
+# Create a dialog for entering a hexadecimal into a kernel option.
+#
+function l_hex () {
+ while true
+ do
+ if $DIALOG --title "$1" \
+ --backtitle "$backtitle" \
+ --inputbox "$inputbox_instructions_hex" \
+ 10 75 "$4" 2>MCdialog.out
+ then
+ answer="`cat MCdialog.out`"
+ answer="${answer:-$3}"
+ answer="${answer##*[x,X]}"
+
+ if expr $answer : '[0-9a-fA-F]+$' >/dev/null
+ then
+ eval $2="$answer"
+ else
+ eval $2="$3"
+ echo -en "\007"
+ ${DIALOG} --backtitle "$backtitle" \
+ --infobox "You have made an invalid entry." 3 43
+ sleep 2
+ fi
+
+ break
+ fi
+
+ help "$2" "$1"
+ done
+}
+
+#
+# Handle a on-of-many choice list.
+#
+function l_choice () {
+ #
+ # Need to remember params cause they're gonna get reset.
+ #
+ title="$1"
+ choices="$2"
+ current="$3"
+
+ #
+ # Scan current value of choices and set radiolist switches.
+ #
+ list=
+ set -- $choices
+ firstchoice=$2
+ while [ -n "$2" ]
+ do
+ case "$1" in
+ "$current") list="$list $2 $1 ON " ;;
+ *) list="$list $2 $1 OFF " ;;
+ esac
+
+ shift ; shift
+ done
+
+ while true
+ do
+ if $DIALOG --title "$title" \
+ --backtitle "$backtitle" \
+ --radiolist "$radiolist_instructions" \
+ 15 70 6 $list 2>MCdialog.out
+ then
+ choice=`cat MCdialog.out`
+ break
+ fi
+
+ help "$firstchoice" "$title"
+ done
+
+ #
+ # Now set the boolean value of each option base on
+ # the selection made from the radiolist.
+ #
+ set -- $choices
+ while [ -n "$2" ]
+ do
+ if [ "$2" = "$choice" ]
+ then
+ eval $2="y"
+ else
+ eval $2="n"
+ fi
+
+ shift ; shift
+ done
+}
+
+
+#
+# A faster awk based recursive parser. (I hope)
+#
+function parser1 () {
+awk '
+BEGIN {
+ menu_no = 0
+ comment_is_option = 0
+ parser("'$CONFIG_IN'","MCmenu0")
+}
+
+function parser(ifile,menu) {
+
+ while (getline <ifile) {
+ if ($1 == "mainmenu_option") {
+ comment_is_option = "1"
+ }
+ else if ($1 == "comment" && comment_is_option == "1") {
+ comment_is_option= "0"
+ sub($1,"",$0)
+ ++menu_no
+
+ printf("submenu %s MCmenu%s\n", $0, menu_no) >>menu
+
+ printf( "function MCmenu%s () {\n"\
+ "default=$1\n"\
+ "menu_name %s\n",\
+ menu_no, $0) >"MCmenu"menu_no
+
+ parser(ifile, "MCmenu"menu_no)
+ }
+ else if ($1 ~ "endmenu") {
+ printf("}\n") >>menu
+ return
+ }
+ else if ($0 ~ /^#|\$MAKE|mainmenu_name/) {
+ printf("") >>menu
+ }
+ else if ($1 == "source") {
+ # Yuk! Blah! Phooey!
+ if ($2 ~ "drivers/sound") {
+ printf("soundcfg\n") >>menu
+ }
+
+ parser($2,menu)
+ }
+ else {
+ print >>menu
+ }
+ }
+}'
+}
+
+#
+# Secondary parser for single menu mode.
+#
+function parser2 () {
+awk '
+BEGIN {
+ parser("'$CONFIG_IN'","MCmenu0")
+}
+
+function parser(ifile,menu) {
+
+ while (getline <ifile) {
+ if ($1 ~ /mainmenu_option|endmenu/) {
+ printf("") >>menu
+ }
+ else if ($0 ~ /^#|$MAKE|mainmenu_name/) {
+ printf("") >>menu
+ }
+ else if ($1 == "source") {
+ if ($2 ~ "drivers/sound") {
+ printf("soundcfg\n") >>menu
+ }
+ parser($2,menu)
+ }
+ else {
+ print >>menu
+ }
+ }
+}'
+}
+
+#
+# Parse all the config.in files into mini scripts.
+#
+function parse_config_files () {
+ rm -f MCmenu*
+
+ echo "function MCmenu0 () {" >MCmenu0
+ echo 'default=$1' >>MCmenu0
+ echo "menu_name 'Main Menu'" >>MCmenu0
+
+ if [ "_$single_menu_mode" = "_TRUE" ]
+ then
+ parser2
+ else
+ parser1
+ fi
+
+ echo "comment ''" >>MCmenu0
+ echo "g_alt_config" >>MCmenu0
+ echo "s_alt_config" >>MCmenu0
+
+ echo "}" >>MCmenu0
+
+ #
+ # These mini scripts must be sourced into the current
+ # environment in order for all of this to work. Leaving
+ # them on the disk as executables screws up the recursion
+ # in activate_menu(), among other things. Once they are
+ # sourced we can discard them.
+ #
+ for i in MCmenu*
+ do
+ source ./$i
+ done
+
+ rm -f MCmenu*
+}
+
+#
+# This is the menu tree's bootstrap.
+#
+# Executes the parsed menus on demand and creates a set of functions,
+# one per configuration option. These functions will in turn execute
+# dialog commands or recursively call other menus.
+#
+function activate_menu () {
+ while true
+ do
+ comment_ctr=0 #So comment lines get unique tags
+
+ $1 "$default" #Create the lxdialog menu & functions
+
+ if [ "$?" != "0" ]
+ then
+ clear
+ cat <<EOM
+
+Menuconfig has encountered a possible error in one of the kernel's
+configuration files and is unable to continue.
+
+Please report this to the author <roadcapw@cfw.com>. You may also
+send a problem report to linux-kernel@vger.rutgers.edu or post a
+message to the linux.dev.kernel news group.
+
+Please indicate the kernel version you are trying to configure and
+which menu you were trying to enter when this error occurred.
+
+EOM
+ cleanup
+ exit 1
+ fi
+
+ . ./MCradiolists #Source the menu's functions
+
+ . ./MCmenu 2>MCdialog.out #Activate the lxdialog menu
+ ret=$?
+
+ read selection <MCdialog.out
+
+ case "$ret" in
+ 0|3|4|5|6)
+ defaults="$selection$defaults" #pseudo stack
+ case "$ret" in
+ 0) eval $selection ;;
+ 3) eval $selection y ;;
+ 4) eval $selection n ;;
+ 5) eval $selection m ;;
+ 6) eval $selection c ;;
+ esac
+ default="${defaults%%*}" defaults="${defaults#*}"
+ ;;
+ 2)
+ default="${selection%%\ *}"
+
+ case "$selection" in
+ *"-->"*|*"alt_config"*)
+ show_readme ;;
+ *)
+ eval help $selection ;;
+ esac
+ ;;
+ 255|1)
+ break
+ ;;
+ 139)
+ stty sane
+ clear
+ cat <<EOM
+
+There seems to be a problem with the lxdialog companion utility which is
+built prior to running Menuconfig. Usually this is an indicator that you
+have upgraded/downgraded your ncurses libraries and did not remove the
+old ncurses header file(s) in /usr/include or /usr/include/ncurses.
+
+It is VERY important that you have only one set of ncurses header files
+and that those files are properly version matched to the ncurses libraries
+installed on your machine.
+
+You may also need to rebuild lxdialog. This can be done by moving to
+the /usr/src/linux/scripts/lxdialog directory and issuing the
+"make clean all" command.
+
+If you have verified that your ncurses install is correct, you may email
+the author <roadcapw@cfw.com> or post a message on the linux.dev.kernel
+news group for additional assistance.
+
+EOM
+ cleanup
+ exit 139
+ ;;
+ esac
+ done
+}
+
+#
+# Create a menu item to load an alternate configuration file.
+#
+g_alt_config () {
+ echo -n "get_alt_config 'Load an Alternate Configuration File' "\
+ >>MCmenu
+}
+
+#
+# Get alternate config file name and load the
+# configuration from it.
+#
+get_alt_config () {
+ set -f ## Switch file expansion OFF
+
+ while true
+ do
+ ALT_CONFIG="${ALT_CONFIG:-$DEFAULTS}"
+
+ $DIALOG --backtitle "$backtitle" \
+ --inputbox "\
+Enter the name of the configuration file you wish to load. \
+Accept the name shown to restore the configuration you \
+last retrieved. Leave blank to abort."\
+ 11 55 "$ALT_CONFIG" 2>MCdialog.out
+
+ if [ "$?" = "0" ]
+ then
+ ALT_CONFIG=`cat MCdialog.out`
+
+ [ "_" = "_$ALT_CONFIG" ] && break
+
+ if eval [ -r "$ALT_CONFIG" ]
+ then
+ eval load_config_file "$ALT_CONFIG"
+ break
+ else
+ echo -ne "\007"
+ $DIALOG --backtitle "$backtitle" \
+ --infobox "File does not exist!" 3 38
+ sleep 2
+ fi
+ else
+ cat <<EOM >help.out
+
+For various reasons, one may wish to keep several different kernel
+configurations available on a single machine.
+
+If you have saved a previous configuration in a file other than the
+kernel's default, entering the name of the file here will allow you
+to modify that configuration.
+
+If you are uncertain, then you have probably never used alternate
+configuration files. You should therefor leave this blank to abort.
+
+EOM
+ $DIALOG --backtitle "$backtitle"\
+ --title "Load Alternate Configuration"\
+ --textbox help.out $ROWS $COLS
+ fi
+ done
+
+ set +f ## Switch file expansion ON
+ rm -f help.out MCdialog.out
+}
+
+#
+# Create a menu item to store an alternate config file.
+#
+s_alt_config () {
+ echo -n "save_alt_config 'Save Configuration to an Alternate File' "\
+ >>MCmenu
+}
+
+#
+# Get an alternate config file name and save the current
+# configuration to it.
+#
+save_alt_config () {
+ set -f ## Switch file expansion OFF
+
+ while true
+ do
+ $DIALOG --backtitle "$backtitle" \
+ --inputbox "\
+Enter a filename to which this configuration should be saved \
+as an alternate. Leave blank to abort."\
+ 10 55 "$ALT_CONFIG" 2>MCdialog.out
+
+ if [ "$?" = "0" ]
+ then
+ ALT_CONFIG=`cat MCdialog.out`
+
+ [ "_" = "_$ALT_CONFIG" ] && break
+
+ if eval touch $ALT_CONFIG 2>/dev/null
+ then
+ eval save_configuration $ALT_CONFIG
+ load_functions ## RELOAD
+ break
+ else
+ echo -ne "\007"
+ $DIALOG --backtitle "$backtitle" \
+ --infobox "Can't create file! Probably a nonexistent directory." 3 60
+ sleep 2
+ fi
+ else
+ cat <<EOM >help.out
+
+For various reasons, one may wish to keep different kernel
+configurations available on a single machine.
+
+Entering a file name here will allow you to later retrieve, modify
+and use the current configuration as an alternate to whatever
+configuration options you have selected at that time.
+
+If you are uncertain what all this means then you should probably
+leave this blank.
+EOM
+ $DIALOG --backtitle "$backtitle"\
+ --title "Save Alternate Configuration"\
+ --textbox help.out $ROWS $COLS
+ fi
+ done
+
+ set +f ## Switch file expansion ON
+ rm -f help.out MCdialog.out
+}
+
+#
+# Load config options from a file.
+# Converts all "# OPTION is not set" lines to "OPTION=n" lines
+#
+function load_config_file () {
+ awk '
+ /# .* is not set.*/ { printf("%s=n\n", $2) }
+ ! /# .* is not set.*/ { print }
+ ' $1 >.tmpconfig
+
+ source ./.tmpconfig
+ rm -f .tmpconfig
+}
+
+#
+# Just what it says.
+#
+save_configuration () {
+ ${DIALOG} --backtitle "$backtitle" \
+ --infobox "Saving your kernel configuration..." 3 40
+
+ #
+ # Now, let's redefine the configuration functions for final
+ # output to the config files.
+ #
+ # Nested function definitions, YIPEE!
+ #
+ function bool () {
+ eval define_bool "$2" "\${$2:-n}"
+ }
+
+ function tristate () {
+ eval define_bool "$2" "\${$2:-n}"
+ }
+
+ function dep_tristate () {
+ eval x=\${$2:-n}
+
+ if eval [ "_$3" = "_m" ]
+ then
+ if [ "$x" = "y" ]
+ then
+ x="m"
+ fi
+ fi
+
+ define_bool "$2" "$x"
+ }
+
+ function int () {
+ eval x=\${$2:-"$3"}
+ echo "$2=$x" >>$CONFIG
+ echo "#define $2 ($x)" >>$CONFIG_H
+ }
+
+ function hex () {
+ eval x=\${$2:-"$3"}
+ echo "$2=$x" >>$CONFIG
+ echo "#define $2 0x${x##*[x,X]}" >>$CONFIG_H
+ }
+
+ function define_bool () {
+ eval $1="$2"
+
+ case "$2" in
+ y)
+ echo "$1=y" >>$CONFIG
+ echo "#define $1 1" >>$CONFIG_H
+ ;;
+
+ m)
+ if [ "$CONFIG_MODULES" = "y" ]
+ then
+ echo "$1=m" >>$CONFIG
+ echo "#undef $1" >>$CONFIG_H
+ echo "#define $1_MODULE 1" >>$CONFIG_H
+ else
+ echo "$1=y" >>$CONFIG
+ echo "#define $1 1" >>$CONFIG_H
+ fi
+ ;;
+
+ n)
+ echo "# $1 is not set" >>$CONFIG
+ echo "#undef $1" >>$CONFIG_H
+ ;;
+ esac
+ }
+
+ function choice () {
+ #
+ # Find the first choice that's already set to 'y'
+ #
+ choices="$2"
+ default="$3"
+ current=
+
+ set -- $choices
+ while [ -n "$2" ]
+ do
+ if eval [ "_\$$2" = "_y" ]
+ then
+ current=$1
+ break
+ fi
+ shift ; shift
+ done
+
+ #
+ # Use the default if none were set.
+ #
+ : ${current:=$default}
+
+ #
+ # Then extract the actual option from the list of choices.
+ #
+ current=${choices#*$current} ; set $current
+
+ define_bool "$1" "y"
+ }
+
+ function mainmenu_name () {
+ :
+ }
+
+ function mainmenu_option () {
+ comment_is_option=TRUE
+ }
+
+ function endmenu () {
+ :
+ }
+
+ function comment () {
+ if [ "$comment_is_option" ]
+ then
+ comment_is_option=
+ echo >>$CONFIG
+ echo "#" >>$CONFIG
+ echo "# $1" >>$CONFIG
+ echo "#" >>$CONFIG
+
+ echo >>$CONFIG_H
+ echo "/*" >>$CONFIG_H
+ echo " * $1" >>$CONFIG_H
+ echo " */" >>$CONFIG_H
+ fi
+ }
+
+ DEF_CONFIG="${1:-.config}"
+ DEF_CONFIG_H="include/linux/autoconf.h"
+
+ CONFIG=.tmpconfig
+ CONFIG_H=.tmpconfig.h
+
+ echo "#" >$CONFIG
+ echo "# Automatically generated by make menuconfig: don't edit" >>$CONFIG
+ echo "#" >>$CONFIG
+
+ echo "/*" >$CONFIG_H
+ echo " * Automatically generated by make menuconfig: don't edit" >>$CONFIG_H
+ echo " */" >>$CONFIG_H
+
+ MAKE=: #To prevent sound Makefile from running.
+
+ if . $CONFIG_IN >>.menuconfig.log 2>&1
+ then
+ if [ "$DEF_CONFIG" = ".config" ]
+ then
+ #
+ # Create the sound driver's config files for cards
+ # Which are compatible with the new config method.
+ #
+ if [ "_$CONFIG_TRIX" != "_y" -a\
+ "_$CONFIG_PSS" != "_y" -a\
+ "_$CONFIG_SMWAVE" != "_y" ]
+ then
+ make -C drivers/sound kernelconfig >>.menuconfig.log 2>&1
+ fi
+
+ mv $CONFIG_H $DEF_CONFIG_H
+ fi
+
+ if [ -f "$DEF_CONFIG" ]
+ then
+ rm -f ${DEF_CONFIG}.old
+ mv $DEF_CONFIG ${DEF_CONFIG}.old
+ fi
+
+ mv $CONFIG $DEF_CONFIG
+
+ return 0
+ else
+ return 1
+ fi
+}
+
+#
+# Remove temporary files
+#
+cleanup () {
+ cleanup1
+ cleanup2
+}
+
+cleanup1 () {
+ rm -f MCmenu* MCradiolists MCdialog.out help.out
+}
+
+cleanup2 () {
+ rm -f .tmpconfig .tmpconfig.h
+}
+
+set_geometry () {
+ # Some distributions export these with incorrect values
+ # which can really screw up some ncurses programs.
+ LINES= COLUMNS=
+
+ ROWS=${1:-24} COLS=${2:-80}
+
+ # Just in case the nasty rlogin bug returns.
+ #
+ [ $ROWS = 0 ] && ROWS=24
+ [ $COLS = 0 ] && COLS=80
+
+ if [ $ROWS -lt 19 -o $COLS -lt 80 ]
+ then
+ echo -e "\n\007Your display is too small to run Menuconfig!"
+ echo "It must be at least 19 lines by 80 columns."
+ exit 0
+ fi
+
+ ROWS=$((ROWS-4)) COLS=$((COLS-5))
+}
+
+
+set_geometry `stty size 2>/dev/null`
+
+menu_instructions="\
+Arrow keys navigate the menu. \
+<Enter> selects submenus --->. \
+Highlighted letters are hotkeys. \
+Pressing <Y> includes, <N> excludes, <M> modularizes features. \
+Press <Esc><Esc> to exit, <?> for Help. \
+Legend: [*] built-in [ ] excluded <M> module < > module capable"
+
+radiolist_instructions="\
+Use the arrow keys to navigate this window or \
+press the hotkey of the item you wish to select \
+followed by the <SPACE BAR>.
+Press <?> for additional information about this option."
+
+inputbox_instructions_int="\
+Please enter a decimal value between 1 and 9999. \
+Fractions will not be accepted. \
+Use the <TAB> key to move from the input field to the buttons below it."
+
+inputbox_instructions_hex="\
+Please enter a hexadecimal value. \
+Use the <TAB> key to move from the input field to the buttons below it."
+
+DIALOG="./scripts/lxdialog/lxdialog"
+
+kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}"
+
+backtitle="Linux Kernel v$kernel_version Configuration"
+
+trap "cleanup ; rm -f .menuconfig ; exit 1" 1 2 15
+
+
+#
+# Locate default files.
+#
+CONFIG_IN=./config.in
+if [ "$1" != "" ] ; then
+ CONFIG_IN=$1
+fi
+
+DEFAULTS=arch/$ARCH/defconfig
+if [ -f .config ]; then
+ DEFAULTS=.config
+fi
+
+if [ -f $DEFAULTS ]
+then
+ echo "#"
+ echo "# Using defaults found in" $DEFAULTS
+ echo "#"
+ load_config_file $DEFAULTS
+else
+ echo "#"
+ echo "# No defaults found"
+ echo "#"
+fi
+
+
+# Fresh new log.
+>.menuconfig.log
+
+$DIALOG --backtitle "$backtitle" \
+ --infobox "Preparing configuration scripts..." 3 40
+
+#
+# Check kernel version of previous menuconfig build.
+# If it's different then we should tell the sound driver
+# to rebuild its Config.in file.
+#
+rebuildsound=TRUE
+if [ -e .menuconfig ]
+then
+ read x <.menuconfig
+ if [ "$x" = "# $kernel_version" ]
+ then
+ rebuildsound=
+ fi
+fi
+
+if [ "$rebuildsound" ]
+then
+ # Activate the Linux compatible sound configuration.
+ # This may not work for all sound cards. (See sound docs)
+ #
+ make -C drivers/sound mkscript kernelconfig >>.menuconfig.log 2>&1
+
+ echo "# $kernel_version" >.menuconfig
+fi
+
+# Load the functions used by the config.in files.
+load_functions
+
+#
+# Read config.in files and parse them into one shell function per menu.
+#
+parse_config_files $CONFIG_IN
+
+#
+# Start the ball rolling from the top.
+#
+activate_menu MCmenu0
+
+#
+# All done!
+#
+cleanup1
+
+#
+# Confirm and Save
+#
+if $DIALOG --backtitle "$backtitle" \
+ --yesno "Do you wish to save your new kernel configuration?" 5 60
+
+then
+ save_configuration
+
+ clear
+ cat <<EOM
+
+
+The linux kernel is now hopefully configured for your setup.
+Check the top-level Makefile for additional configuration,
+and do a 'make dep ; make clean' if you want to be sure all
+the files are correctly re-made.
+
+EOM
+else
+ clear
+ echo -e "Your kernel configuration changes were NOT saved.\n"
+fi
+
+
+exit 0
+
diff --git a/scripts/README.Menuconfig b/scripts/README.Menuconfig
new file mode 100644
index 000000000..b3ec5aaaf
--- /dev/null
+++ b/scripts/README.Menuconfig
@@ -0,0 +1,194 @@
+Menuconfig gives the Linux kernel configuration a long needed face
+lift. Featuring text based color menus and dialogs, it does not
+require X Windows. With this utility you can easily select a kernel
+option to modify without sifting through 100 other options.
+
+Overview
+--------
+Some kernel features may be built directly into the kernel.
+Some may be made into loadable runtime modules. Some features
+may be completely removed altogether. There are also certain
+kernel parameters which are not really features, but must be
+entered in as decimal or hexadecimal numbers or possibly text.
+
+Menu items beginning with [*], <M> or [ ] represent features
+configured to be built in, modularized or removed respectively.
+Pointed brackets <> represent module capable features.
+ more...
+
+To change any of these features, highlight it with the cursor
+keys and press <Y> to build it in, <M> to make it a module or
+<N> to removed it. You may also press the <Space Bar> to cycle
+through the available options (ie. Y->N->M->Y).
+
+Items beginning with numbers or other text within parenthesis can
+be changed by highlighting the item and pressing <Enter>. Then
+enter the new parameter into the dialog box that pops up.
+
+
+Some additional keyboard hints:
+
+Menus
+----------
+o Use the Up/Down arrow keys (cursor keys) to highlight the item
+ you wish to change or submenu wish to select and press <Enter>.
+ Submenus are designated by "--->".
+
+ Shortcut: Press the option's highlighted letter (hotkey).
+ Pressing a hotkey more than once will sequence
+ through all visible items which use that hotkey.
+
+ You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll
+ unseen options into view.
+
+o To exit a menu use the cursor keys to highlight the <Exit> button
+ and press <ENTER>.
+
+ Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey
+ using those letters. You may press a single <ESC>, but
+ there is a delayed response which you may find annoying.
+
+ Also, the <TAB> and cursor keys will cycle between <Select>,
+ <Exit> and <Help>
+
+o To get help with an item, use the cursor keys to highlight <Help>
+ and Press <ENTER>.
+
+ Shortcut: Press <H> or <?>.
+
+
+Radiolists (Choice lists)
+-----------
+o Use the cursor keys to select the option you wish to set and press
+ <S> or the <SPACE BAR>.
+
+ Shortcut: Press the first letter of the option you wish to set then
+ press <S> or <SPACE BAR>.
+
+o To see available help for the item, use the cursor keys to highlight
+ <Help> and Press <ENTER>.
+
+ Shortcut: Press <H> or <?>.
+
+ Also, the <TAB> and cursor keys will cycle between <Select> and
+ <Help>
+
+
+Data Entry
+-----------
+o Enter the requested information and press <ENTER>
+ If you are entering hexadecimal values, it is not necessary to
+ add the '0x' prefix to the entry.
+
+o For help, use the <TAB> or cursor keys to highlight the help option
+ and press <ENTER>. You can try <TAB><H> as well.
+
+
+Text Box (Help Window)
+--------
+o Use the cursor keys to scroll up/down/left/right. The VI editor
+ keys h,j,k,l function here as do <SPACE BAR> and <B> for those
+ who are familiar with less and lynx.
+
+o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.
+
+
+Final Acceptance
+----------------
+With the exception of the old style sound configuration,
+YOUR CHANGES ARE NOT FINAL. You will be given a last chance to
+confirm them prior to exiting Menuconfig.
+
+If Menuconfig quits with an error while saving your configuration,
+you may look in the file /usr/src/linux/.menuconfig.log for
+information which may help you determine the cause.
+
+Alternate Configuration Files
+-----------------------------
+Menuconfig supports the use of alternate configuration files for
+those who, for various reasons, find it necessary to switch
+between different kernel configurations.
+
+At the end of the main menu you will find two options. One is
+for saving the current configuration to a file of your choosing.
+The other option is for loading a previously saved alternate
+configuration.
+
+Even if you don't use alternate configuration files, but you
+find during a Menuconfig session that you have completely messed
+up your settings, you may use the "Load Alternate..." option to
+restore your previously saved settings from ".config" without
+restarting Menuconfig.
+
+Other information
+-----------------
+The windowing utility, lxdialog, will only be rebuilt if your kernel
+source tree is fresh, or changes are patched into it via a kernel
+patch or you do 'make mrproper'. If changes to lxdialog are patched
+in, most likely the rebuild time will be short. You may force a
+complete rebuild of lxdialog by changing to it's directory and doing
+'make clean all'
+
+If you use Menuconfig in an XTERM window make sure you have your
+$TERM variable set to point to a xterm definition which supports color.
+Otherwise, Menuconfig will look rather bad. Menuconfig will not
+display correctly in a RXVT window because rxvt displays only one
+intensity of color, bright.
+
+Menuconfig will display larger menus on screens or xterms which are
+set to display more than the standard 25 row by 80 column geometry.
+In order for this to work, the "stty size" command must be able to
+display the screen's current row and column geometry. I STRONGLY
+RECOMMEND that you make sure you do NOT have the shell variables
+LINES and COLUMNS exported into your environment. Some distributions
+export those variables via /etc/profile. Some ncurses programs can
+become confused when those variables (LINES & COLUMNS) don't reflect
+the true screen size.
+
+
+NOTICE: lxdialog requires the ncurses libraries to compile. If you
+ don't already have ncurses you really should get it.
+
+ The makefile for lxdialog attempts to find your ncurses
+ header file. Although it should find the header for older
+ versions of ncurses, it is probably a good idea to get the
+ latest ncurses anyway.
+
+ If you have upgraded your ncurses libraries, MAKE SURE you
+ remove the old ncurses header files. If you don't you
+ will most certainly get a segmentation fault.
+
+WARNING: It is not recommended that you change any defines in
+ lxdialog's header files. If you have a grayscale display and
+ are brave, you may tinker with color.h to tune the colors to
+ your preference.
+
+COMPATIBILITY ISSUE:
+ There have been some compatibility problems reported with
+ older versions of bash and sed. I am trying to work these
+ out but it is preferable that you upgrade those utilities.
+
+
+******** IMPORTANT, OPTIONAL ALTERNATE PERSONALITY AVAILABLE ********
+******** ********
+If you prefer to have all of the kernel options listed in a single
+menu, rather than the default multimenu hierarchy, you may edit the
+Menuconfig script and change the line "single_menu_mode=" to
+"single_menu_mode=TRUE".
+
+This mode is not recommended unless you have a fairly fast machine.
+*********************************************************************
+
+
+Propaganda
+----------
+The windowing support utility (lxdialog) is a VERY modified version of
+the dialog utility by Savio Lam <lam836@cs.cuhk.hk>. Although lxdialog
+is significantly different from dialog, I have left Savio's copyrights
+intact. Please DO NOT contact Savio with questions about lxdialog.
+He will not be able to assist.
+
+Please feel free to send any questions, comments or suggestions to
+William Roadcap <roadcapw@cfw.com>.
+
+<END OF FILE>
diff --git a/scripts/depend.awk b/scripts/depend.awk
new file mode 100644
index 000000000..93cb0ebbc
--- /dev/null
+++ b/scripts/depend.awk
@@ -0,0 +1,154 @@
+# This is an awk script which does dependencies. We do NOT want it to
+# recursively follow #include directives.
+#
+# The HPATH environment variable should be set to indicate where to look
+# for include files. The -I in front of the path is optional.
+
+#
+# Surely there is a more elegant way to see if a file exists. Anyone know
+# what it is?
+#
+function fileExists(f, TMP, dummy, result) {
+ if(result=FILEHASH[f]) {
+ if(result=="Yes") {
+ return "Yes"
+ } else {return ""}
+ }
+ ERRNO = getline dummy < f
+ if(ERRNO >= 0) {
+ close(f)
+ return FILEHASH[f]="Yes"
+ } else {
+ FILEHASH[f]="No"
+ return ""
+ }
+}
+
+function endfile(f) {
+ if (hasconfig && !needsconfig) {
+ printf "%s doesn't need config\n",f > "/dev/stderr"
+ }
+ if (hasdep) {
+ print cmd
+ }
+}
+
+BEGIN{
+ hasdep=0
+ hasconfig=0
+ needsconfig=0
+ incomment=0
+ if(!(TOPDIR=ENVIRON["TOPDIR"])) {
+ print "Environment variable TOPDIR is not set"
+ exit 1
+ }
+ split(ENVIRON["HPATH"],parray," ")
+ for(path in parray) {
+ sub("^-I","",parray[path])
+ sub("[/ ]*$","",parray[path])
+ }
+}
+
+# eliminate comments
+{
+ # remove all comments fully contained on a single line
+ gsub("\\/\\*.*\\*\\/", "")
+ if (incomment) {
+ if ($0 ~ /\*\//) {
+ incomment = 0;
+ gsub(".*\\*\\/", "")
+ } else {
+ next
+ }
+ } else {
+ # start of multi-line comment
+ if ($0 ~ /\/\*/)
+ {
+ incomment = 1;
+ sub("\\/\\*.*", "")
+ } else if ($0 ~ /\*\//) {
+ incomment = 0;
+ sub(".*\\*\\/", "")
+ }
+ }
+}
+
+/^[ ]*#[ ]*if.*[^A-Za-z_]CONFIG_/ {
+ needsconfig=1
+ if (!hasconfig) {
+ printf "%s needs config but has not included config file\n",FILENAME > "/dev/stderr"
+ # only say it once per file..
+ hasconfig = 1
+ }
+}
+
+/^[ ]*#[ ]*include[ ]*[<"][^ ]*[>"]/{
+ found=0
+ if(LASTFILE!=FILENAME) {
+ endfile(LASTFILE)
+ hasdep=0
+ hasconfig=0
+ needsconfig=0
+ incomment=0
+ cmd=""
+ LASTFILE=FILENAME
+ depname=FILENAME
+ relpath=FILENAME
+ sub("\\.c$",".o: ",depname)
+ sub("\\.S$",".o: ",depname)
+ if (depname==FILENAME) {
+ cmd="\n\t@touch "depname
+ }
+ sub("\\.h$",".h: ",depname)
+ if(relpath ~ "^\\." ) {
+ sub("[^/]*$","", relpath)
+ relpath=relpath"/"
+ sub("//","/", relpath)
+ } else {
+ relpath=""
+ }
+ }
+ fname=$0
+ sub("^#[ ]*include[ ]*[<\"]","",fname)
+ sub("[>\"].*","",fname)
+ if (fname=="linux/config.h") {
+ hasconfig=1
+ }
+ rfname=relpath""fname
+ if(fileExists(rfname)) {
+ found=1
+ if (!hasdep) {
+ printf "%s", depname
+ }
+ hasdep=1
+ printf " \\\n %s", rfname
+ if(fname ~ "^\\." ) {
+ fnd=0;
+ for(i in ARGV) {
+ if(ARGV[i]==rfname) {
+ fnd=1
+ }
+ }
+ if(fnd==0) {
+ ARGV[ARGC]=rfname
+ ++ARGC
+ }
+ }
+ } else {
+ for(path in parray) {
+ if(fileExists(parray[path]"/"fname)) {
+ shortp=parray[path]
+ found=1
+ if (!hasdep) {
+ printf "%s", depname
+ }
+ hasdep=1
+ printf " \\\n %s", parray[path]"/"fname
+ }
+ }
+ }
+}
+
+END{
+ endfile(FILENAME)
+}
diff --git a/scripts/header.tk b/scripts/header.tk
new file mode 100644
index 000000000..763eca6db
--- /dev/null
+++ b/scripts/header.tk
@@ -0,0 +1,440 @@
+#
+# This is a handy replacement for ".widget cget" that requires neither tk4
+# nor additional source code uglification.
+#
+proc cget { w option } {
+ return "[lindex [$w configure $option] 4]"
+}
+
+#
+# Function to compensate for broken config.in scripts like the sound driver,
+# which make dependencies on variables that are never even conditionally
+# defined.
+#
+proc vfix { var } {
+ global $var
+ if [ catch {eval concat $$var} ] {
+ puts stdout "WARNING - broken Config.in! $var was not declared!"
+ set $var 0
+ }
+}
+
+#
+# Create a "reference" object to steal colors from.
+#
+button .ref
+#
+# On monochrome displays, -disabledforeground is blank by default; that's
+# bad. Fill it with -foreground instead.
+#
+if { [cget .ref -disabledforeground] == "" } {
+ .ref configure -disabledforeground [cget .ref -foreground]
+}
+
+
+#
+# Define some macros we will need to parse the config.in file.
+#
+proc mainmenu_name { text } {
+ message .header.message -width 400 -relief raised -text "$text"
+ pack .header.label .header.message -side left -padx 15
+ wm title . "$text"
+}
+
+proc menu_option { w menu_num text } {
+ button .f0.x$menu_num -text "$text" -width 50 -command "$w .$w \"$text\""
+ pack .f0.x$menu_num -pady 1 -expand on
+}
+
+#
+# Not used at the moment, but this runs a command in a subprocess and
+# displays the result in a window with a scrollbar.
+#
+# For now, we just do external "make" commands to stdout with do_make, so
+# this function is never called.
+#
+proc do_cmd { w command } {
+ catch {destroy $w}
+ toplevel $w -class Dialog
+ frame $w.tb
+ text $w.tb.text -relief raised -bd 2 -yscrollcommand "$w.tb.scroll set"
+ scrollbar $w.tb.scroll -command "$w.tb.text yview"
+ pack $w.tb.scroll -side right -fill y
+ pack $w.tb.text -side left
+
+ set oldFocus [focus]
+ frame $w.back
+ button $w.back.ok -text "OK" -width 20 \
+ -command "destroy $w; focus $oldFocus" -state disabled
+ button $w.back.ccl -text "Cancel" -width 20 \
+ -command "destroy $w; focus $oldFocus"
+ pack $w.tb -side top
+ pack $w.back.ok $w.back.ccl -side left
+ pack $w.back -side bottom -pady 10
+
+ focus $w
+ wm geometry $w +30+35
+
+ $w.tb.text delete 1.0 end
+ set f [open |$command]
+ while {![eof $f]} {
+ $w.tb.text insert end [read $f 256]
+ }
+ close $f
+ $w.back.ok configure -state normal
+}
+
+proc load_configfile { w title func } {
+ catch {destroy $w}
+ toplevel $w -class Dialog
+ global loadfile
+ frame $w.x
+ label $w.bm -bitmap questhead
+ pack $w.bm -pady 10 -side top -padx 10
+ label $w.x.l -text "Enter filename:" -relief raised
+ entry $w.x.x -width 35 -relief sunken -borderwidth 2 \
+ -textvariable loadfile
+ pack $w.x.l $w.x.x -anchor w -side left
+ pack $w.x -side top -pady 10
+ wm title $w "$title"
+
+ set oldFocus [focus]
+ frame $w.f
+ button $w.f.back -text "OK" -width 20 \
+ -command "destroy $w; focus $oldFocus;$func .fileio"
+ button $w.f.canc -text "Cancel" \
+ -width 20 -command "destroy $w; focus $oldFocus"
+ pack $w.f.back $w.f.canc -side left -pady 10 -padx 45
+ pack $w.f -pady 10 -side bottom -padx 10 -anchor w
+ focus $w
+ global winx; global winy
+ set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+ wm geometry $w +$winx+$winy
+}
+
+proc maybe_exit { w } {
+ catch {destroy $w}
+ toplevel $w -class Dialog
+ label $w.bm -bitmap questhead
+ pack $w.bm -pady 10 -side top -padx 10
+ message $w.m -width 400 -aspect 300 \
+ -text "Changes will be lost. Are you sure?" -relief flat
+ pack $w.m -pady 10 -side top -padx 10
+ wm title $w "Are you sure?"
+
+ set oldFocus [focus]
+ frame $w.f
+ button $w.f.back -text "OK" -width 20 \
+ -command "exit"
+ button $w.f.canc -text "Cancel" \
+ -width 20 -command "destroy $w; focus $oldFocus"
+ pack $w.f.back $w.f.canc -side left -pady 10 -padx 45
+ pack $w.f -pady 10 -side bottom -padx 10 -anchor w
+ focus $w
+ global winx; global winy
+ set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+ wm geometry $w +$winx+$winy
+}
+
+proc read_config_file { w } {
+ global loadfile
+ if { [string length $loadfile] != 0 && [file readable $loadfile] == 1 } then {
+ read_config $loadfile
+ } else {
+ catch {destroy $w}
+ toplevel $w -class Dialog
+ message $w.m -width 400 -aspect 300 -text \
+ "Unable to read file $loadfile" \
+ -relief raised
+ label $w.bm -bitmap error
+ pack $w.bm $w.m -pady 10 -side top -padx 10
+ wm title $w "Oops"
+
+ set oldFocus [focus]
+ frame $w.f
+ button $w.f.back -text "Bummer" \
+ -width 10 -command "destroy $w; focus $oldFocus"
+ pack $w.f.back -side bottom -pady 10 -anchor s
+ pack $w.f -pady 10 -side top -padx 10 -anchor s
+ focus $w
+ global winx; global winy
+ set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+ wm geometry $w +$winx+$winy
+ }
+}
+
+proc write_config_file { w } {
+ global loadfile
+ if { [string length $loadfile] != 0
+ && ([file writable $loadfile] == 1 || ([file exists $loadfile] == 0 && [file writable [file dirname $loadfile]] == 1)) } then {
+ writeconfig $loadfile /dev/null
+ } else {
+ catch {destroy $w}
+ toplevel $w -class Dialog
+ message $w.m -width 400 -aspect 300 -text \
+ "Unable to write file $loadfile" \
+ -relief raised
+ label $w.bm -bitmap error
+ pack $w.bm $w.m -pady 10 -side top -padx 10
+ wm title $w "Oops"
+
+ set oldFocus [focus]
+ frame $w.f
+ button $w.f.back -text "OK" \
+ -width 10 -command "destroy $w; focus $oldFocus"
+ pack $w.f.back -side bottom -pady 10 -anchor s
+ pack $w.f -pady 10 -side top -padx 10 -anchor s
+ focus $w
+ global winx; global winy
+ set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+ wm geometry $w +$winx+$winy
+ }
+}
+
+proc read_config { filename } {
+ set file1 [open $filename r]
+ clear_choices
+ while { [gets $file1 line] >= 0} {
+ if [regexp {([0-9A-Za-z_]+)=([ynm])} $line foo var value] {
+ if { $value == "y" } then { set cmd "global $var; set $var 1" }
+ if { $value == "n" } then { set cmd "global $var; set $var 0" }
+ if { $value == "m" } then { set cmd "global $var; set $var 2" }
+ eval $cmd
+ }
+ if [regexp {# ([0-9A-Za-z_]+) is not set} $line foo var] {
+ set cmd "global $var; set $var 0"
+ eval $cmd
+ }
+ if [regexp {([0-9A-Za-z_]+)=([0-9A-Fa-f]+)} $line foo var value] {
+ set cmd "global $var; set $var $value"
+ eval $cmd
+ }
+ }
+ close $file1
+ update_choices
+ update_mainmenu .rdupd
+}
+proc write_comment { file1 file2 text } {
+ puts $file1 ""
+ puts $file1 "#"
+ puts $file1 "# $text"
+ puts $file1 "#"
+ puts $file2 "/*"
+ puts $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) } \
+ 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" } \
+ else { \
+ error "Attempting to write value for variable that is not configured ($varname)." \
+ }
+}
+
+proc write_int { file1 file2 varname variable dep } {
+ if { $dep == 0 } \
+ then { puts $file1 "# $varname is not set"; \
+ puts $file2 "#undef $varname"} \
+ else {
+ puts $file1 "$varname=$variable"; \
+ puts $file2 "#define $varname $variable"; \
+ }
+}
+
+proc write_hex { file1 file2 varname variable dep } {
+ if { $dep == 0 } \
+ then { puts $file1 "# $varname is not set"; \
+ puts $file2 "#undef $varname"} \
+ else {
+ puts $file1 "$varname=$variable"; \
+ puts $file2 "#define $varname 0x$variable"; \
+ }
+}
+
+proc option_name {w mnum line text helpidx} {
+ button $w.x$line.l -text "$text" -relief groove -anchor w
+ $w.x$line.l configure -activefore [cget $w.x$line.l -fg] \
+ -activeback [cget $w.x$line.l -bg]
+ button $w.x$line.help -text "Help" -relief raised \
+ -command "dohelp .dohelp $helpidx"
+ pack $w.x$line.help -side right -fill y
+ pack $w.x$line.l -side right -fill both -expand on
+}
+
+proc toggle_switch {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"
+ radiobutton $w.x$line.m -text "m" -variable $variable -value 2 \
+ -relief groove -width 2 -command "update_menu$mnum .menu$mnum"
+ radiobutton $w.x$line.n -text "n" -variable $variable -value 0 \
+ -relief groove -width 2 -command "update_menu$mnum .menu$mnum"
+
+ option_name $w $mnum $line $text $variable
+
+ pack $w.x$line.n $w.x$line.m $w.x$line.y -side right -fill y
+}
+
+proc bool {w mnum line text variable} {
+ toggle_switch $w $mnum $line $text $variable
+ $w.x$line.m configure -state disabled
+ pack $w.x$line -anchor w -fill both -expand on
+}
+
+proc tristate {w mnum line text variable } {
+ toggle_switch $w $mnum $line $text $variable
+ pack $w.x$line -anchor w -fill both -expand on
+}
+
+proc dep_tristate {w mnum line text variable depend } {
+ tristate $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 \
+ -textvariable $variable
+ option_name $w $mnum $line $text $variable
+ pack $w.x$line.x -anchor w -side right -fill y
+ pack $w.x$line -anchor w -fill both -expand on
+}
+
+proc hex { w mnum line text variable } {
+ int $w $mnum $line $text $variable
+}
+
+proc minimenu { w mnum line text variable helpidx } {
+ frame $w.x$line
+ menubutton $w.x$line.x -textvariable $variable -menu \
+ $w.x$line.x.menu -relief raised \
+ -width 15 -anchor w
+ option_name $w $mnum $line $text $helpidx
+ pack $w.x$line.x -anchor w -side right -fill y
+ pack $w.x$line -anchor w -fill both -expand on
+}
+
+proc comment {w line text } {
+#nothing done for comments now.
+}
+
+proc do_make { command } {
+ exec sh -c $command <@stdin >@stdout 2>@stderr
+# do_cmd .make_window "sh -c $command"
+}
+
+proc dohelp {w var } {
+ catch {destroy $w}
+ toplevel $w -class Dialog
+
+ set filefound 0
+ set found 0
+ set lineno 0
+
+ if { [file readable Documentation/Configure.help] == 1} then {
+ set filefound 1
+ set message [exec sed -n "
+ /^$var\[ \]*\$/,\${
+ /^$var\[ \]*\$/c\\
+${var}:\\
+
+ /^#.*/d
+ /^\[ \]*\$/bL
+ H
+ }
+ d
+ :L x
+ s/\\n //
+ s/\\n / /g
+ p
+ q
+ " Documentation/Configure.help]
+ set found [expr [string length "$message"] > 0]
+ }
+
+ frame $w.f1
+
+ if { $found == 0 } then {
+ if { $filefound == 0 } then {
+ message $w.f1.m -width 750 -aspect 300 -relief flat -text \
+ "No help available - unable to open file Documentation/Configure.help. This file should have come with your kernel."
+ } else {
+ message $w.f1.m -width 400 -aspect 300 -relief flat -text \
+ "No help available for $var"
+ }
+ label $w.f1.bm -bitmap error
+ wm title $w "RTFM"
+ } else {
+ message $w.f1.m -width 400 -aspect 300 -text $message \
+ -relief flat
+ label $w.f1.bm -bitmap info
+ wm title $w "Configuration help"
+ }
+ pack $w.f1.bm $w.f1.m -side left -padx 10
+ pack $w.f1 -side top
+ set oldFocus [focus]
+
+ # Do the OK button
+ #
+ frame $w.f2
+ button $w.f2.ok -text "OK" \
+ -width 10 -command "destroy $w; focus $oldFocus"
+ pack $w.f2.ok -side bottom -pady 10 -anchor s
+ pack $w.f2 -side bottom -padx 10 -anchor s
+
+ # Finish off the window
+ #
+ focus $w
+ global winx; global winy
+ set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+ wm geometry $w +$winx+$winy
+}
+
+proc wrapup {w } {
+ catch {destroy $w}
+ toplevel $w -class Dialog
+ message $w.m -width 400 -aspect 300 -text \
+ "The linux kernel is now hopefully configured for your setup. Check the top-level Makefile for additional configuration, and do a 'make dep ; make clean' if you want to be sure all the files are correctly re-made." -relief raised
+ label $w.bm -bitmap info
+ pack $w.bm $w.m -pady 10 -side top -padx 10
+ wm title $w "Kernel build instructions"
+
+ set oldFocus [focus]
+ frame $w.f
+ button $w.f.back -text "OK" \
+ -width 10 -command "exit"
+ pack $w.f.back -side bottom -pady 10 -anchor s
+ pack $w.f -pady 10 -side top -padx 10 -anchor s
+ focus $w
+ global winx; global winy
+ set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+ wm geometry $w +$winx+$winy
+
+}
+
+proc check_sound_config { num } {
+#nothing for now.
+}
+
+proc do_sound {w mnum line} {
+ message $w.x$line -width 400 -aspect 300 -text "Note: The sound drivers cannot as of yet be configured via the X-based interface" -relief raised
+ pack $w.x$line -side top -pady 10
+}
+
+#
+# Next set up the particulars for the top level menu, and define a few
+# buttons which we will stick down at the bottom.
+#
+frame .header
+label .header.label
+
+frame .f0
+
diff --git a/scripts/hfiles.sh b/scripts/hfiles.sh
new file mode 100644
index 000000000..4643194c8
--- /dev/null
+++ b/scripts/hfiles.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+#
+# This script looks to see if a directory contains .h files
+#
+for dir in $@; do
+ for hfile in $dir/*.h; do
+ if [ -f $hfile ]; then echo $dir; fi
+ break
+ done
+done
+exit 0
diff --git a/scripts/ksymoops.cc b/scripts/ksymoops.cc
new file mode 100644
index 000000000..28d93f56f
--- /dev/null
+++ b/scripts/ksymoops.cc
@@ -0,0 +1,325 @@
+// ksymoops.cc v1.7 -- A simple filter to resolve symbols in Linux Oops-logs
+// Copyright (C) 1995 Greg McGary <gkm@magilla.cichlid.com>
+// compile like so: g++ -o ksymoops ksymoops.cc -liostream
+
+//////////////////////////////////////////////////////////////////////////////
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; see the file COPYING. If not, write to the
+// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+// This is a simple filter to resolve EIP and call-trace symbols from
+// a Linux kernel "Oops" log. Supply the symbol-map file name as a
+// command-line argument, and redirect the oops-log into stdin. Out
+// will come the EIP and call-trace in symbolic form.
+
+//////////////////////////////////////////////////////////////////////////////
+
+// BUGS:
+// * Doesn't deal with line-prefixes prepended by syslog--strip
+// these off first, before submitting to ksymoops.
+// * Only resolves operands of jump and call instructions.
+
+#include <fstream.h>
+#include <iomanip.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+
+inline int strequ(char const* x, char const* y) { return (::strcmp(x, y) == 0); }
+inline int strnequ(char const* x, char const* y, size_t n) { return (::strncmp(x, y, n) == 0); }
+
+const int code_size = 20;
+
+//////////////////////////////////////////////////////////////////////////////
+
+class KSym
+{
+ friend class NameList;
+
+ private:
+ unsigned long address_;
+ char* name_;
+ long offset_;
+ long extent_;
+
+ private:
+ istream& scan(istream&);
+ ostream& print(ostream&) const;
+ void set_extent(KSym const& next_ksym) { extent_ = next_ksym.address_ - address_; }
+
+ public:
+ friend istream& operator >> (istream& is, KSym& k) { return k.scan(is); }
+ friend ostream& operator << (ostream& os, const KSym& k) { return k.print(os); }
+};
+
+istream&
+KSym::scan(istream& is)
+{
+ is >> ::hex >> address_;
+ char type;
+ is >> type;
+ char name[128];
+ is >> name;
+ name_ = new char [strlen(name)+1];
+ strcpy(name_, name);
+ offset_ = 0;
+ return is;
+}
+
+ostream&
+KSym::print(ostream& os) const
+{
+ os << ::hex << address_ + offset_ << ' ' << '<' << name_;
+ if (offset_)
+ os << '+' << ::hex << offset_ << '/' << ::hex << extent_;
+ return os << '>';
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class NameList
+{
+ private:
+ // Caution: Fixed Allocation!
+ // This should suffice for awhile since 1.1.86 has only 2482 symbols.
+ KSym ksyms_0_[8000];
+ int cardinality_;
+
+ public:
+ NameList() : cardinality_(0) { }
+
+ private:
+ istream& scan(istream&);
+
+ public:
+ int valid() { return (cardinality_ > 0); }
+
+ KSym* find(unsigned long address);
+ void decode(unsigned char* code, long eip_addr);
+
+ public:
+ friend istream& operator >> (istream& is, NameList& n) { return n.scan(is); }
+};
+
+KSym*
+NameList::find(unsigned long address)
+{
+ if (!valid())
+ return 0;
+ KSym* start = ksyms_0_;
+ KSym* end = &ksyms_0_[cardinality_ - 1];
+ if (address < start->address_ || address >= end->address_)
+ return 0;
+
+ KSym* mid;
+ while (start <= end) {
+ mid = &start[(end - start) / 2];
+ if (mid->address_ < address)
+ start = mid + 1;
+ else if (mid->address_ > address)
+ end = mid - 1;
+ else
+ return mid;
+ }
+ while (mid->address_ > address)
+ --mid;
+ mid->offset_ = address - mid->address_;
+ if (mid->offset_ > mid->extent_)
+ clog << "Oops! " << *mid << endl;
+ return mid;
+}
+
+void
+NameList::decode(unsigned char* code, long eip_addr)
+{
+ /* This is a hack to avoid using gcc. We create an object file by
+ concatenating objfile_head, the twenty bytes of code, and
+ objfile_tail. */
+ unsigned char objfile_head[] = {
+ 0x07, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ unsigned char objfile_tail[] = {
+ 0x00, 0x90, 0x90, 0x90,
+ 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x25, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
+ 'g', 'c', 'c', '2', '_', 'c', 'o', 'm',
+ 'p', 'i', 'l', 'e', 'd', '.', '\0', '_',
+ 'E', 'I', 'P', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+ '\0', '\0', '\0', '\0', '\0', '\0'
+ };
+ char const* objdump_command = "objdump -d oops_decode.o";
+ char const* objfile_name = &objdump_command[11];
+ ofstream objfile_stream(objfile_name);
+
+ objfile_stream.write(objfile_head, sizeof(objfile_head));
+ objfile_stream.write(code, code_size);
+ objfile_stream.write(objfile_tail, sizeof(objfile_tail));
+ objfile_stream.close();
+
+ FILE* objdump_FILE = popen(objdump_command, "r");
+ if (objdump_FILE == 0) {
+ clog << "Sorry, without " << objdump_command << ", I can't disassemble the `Code' section." << endl;
+ return;
+ }
+
+ char buf[1024];
+ int lines = 0;
+ while (fgets(buf, sizeof(buf), objdump_FILE)) {
+ if (!strnequ(&buf[9], "<_EIP", 5))
+ continue;
+ if (strstr(buf, " is out of bounds"))
+ break;
+ lines++;
+ cout << "Code: ";
+ if (!valid()) {
+ cout << buf;
+ continue;
+ }
+ long offset = strtol(buf, 0, 16);
+ char* bp_0 = strchr(buf, '>') + 2;
+ KSym* ksym = find(eip_addr + offset);
+ if (ksym)
+ cout << *ksym << ' ';
+ char* bp = bp_0;
+ while (!isspace(*bp))
+ bp++;
+ while (isspace(*bp))
+ bp++;
+ if (*bp != '0') {
+ cout << bp_0;
+ } else if (*bp_0 == 'j' || strnequ(bp_0, "call", 4)) { // a jump or call insn
+ long rel_addr = strtol(bp, 0, 16);
+ ksym = find(eip_addr + rel_addr);
+ if (ksym) {
+ *bp++ = '\0';
+ cout << bp_0 << *ksym << endl;
+ } else
+ cout << bp_0;
+ } else {
+ cout << bp_0;
+ }
+ }
+ if (!lines)
+ clog << "Sorry, your " << objdump_command << " can't disassemble--you must upgrade your binutils." << endl;
+ pclose(objdump_FILE);
+ unlink(objfile_name);
+}
+
+istream&
+NameList::scan(istream& is)
+{
+ KSym* ksyms = ksyms_0_;
+ int cardinality = 0;
+ while (!is.eof()) {
+ is >> *ksyms;
+ if (cardinality++ > 0)
+ ksyms[-1].set_extent(*ksyms);
+ ksyms++;
+ }
+ cardinality_ = --cardinality;
+ return is;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+char const* program_name;
+
+void
+usage()
+{
+ clog << "Usage: " << program_name << " [ System.map ] < oops-log" << endl;
+ exit(1);
+}
+
+int
+main(int argc, char** argv)
+{
+ char c;
+ program_name = (argc--, *argv++);
+
+ NameList names;
+ if (argc > 1)
+ usage();
+ else if (argc == 1) {
+ char const* map_file_name = (argc--, *argv++);
+ ifstream map(map_file_name);
+ if (map.bad())
+ clog << program_name << ": Can't open `" << map_file_name << "'" << endl;
+ else {
+ map >> names;
+ cout << "Using `" << map_file_name << "' to map addresses to symbols." << endl;
+ }
+ }
+ if (!names.valid())
+ cout << "No symbol map. I'll only show you disassembled code." << endl;
+ cout << endl;
+
+ char buffer[1024];
+ while (!cin.eof())
+ {
+ long eip_addr;
+ cin >> buffer;
+ if (strequ(buffer, "EIP:") && names.valid()) {
+ cin >> ::hex >> eip_addr;
+ cin >> c >> c >> c;
+ cin >> ::hex >> eip_addr;
+ cin >> c >> c >> buffer;
+ if (!strequ(buffer, "EFLAGS:")) {
+ clog << "Please strip the line-prefixes and rerun " << program_name << endl;
+ exit(1);
+ }
+ KSym* ksym = names.find(eip_addr);
+ if (ksym)
+ cout << ">>EIP: " << *ksym << endl;
+ } else if (strequ(buffer, "Trace:") && names.valid()) {
+ unsigned long address;
+ while ((cin >> buffer) &&
+ (sscanf(buffer, " [<%x>]", &address) == 1) &&
+ address > 0xc) {
+ cout << "Trace: ";
+ KSym* ksym = names.find(address);
+ if (ksym)
+ cout << *ksym;
+ else
+ cout << ::hex << address;
+ cout << endl;
+ }
+ cout << endl;
+ }
+ if (strequ(buffer, "ode:") || strequ(buffer, "Code:")) {
+ // The 'C' might have been consumed as a hex number
+ unsigned char code[code_size];
+ unsigned char* cp = code;
+ unsigned char* end = &code[code_size];
+ while (cp < end) {
+ int c;
+ cin >> ::hex >> c;
+ *cp++ = c;
+ }
+ names.decode(code, eip_addr);
+ }
+ }
+ cout << flush;
+
+ return 0;
+}
diff --git a/scripts/lxdialog/BIG.FAT.WARNING b/scripts/lxdialog/BIG.FAT.WARNING
new file mode 100644
index 000000000..a8999d82b
--- /dev/null
+++ b/scripts/lxdialog/BIG.FAT.WARNING
@@ -0,0 +1,4 @@
+This is NOT the official version of dialog. This version has been
+significantly modified from the original. It is for use by the Linux
+kernel configuration script. Please do not bother Savio Lam with
+questions about this program.
diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile
new file mode 100644
index 000000000..fc5ee7ffd
--- /dev/null
+++ b/scripts/lxdialog/Makefile
@@ -0,0 +1,46 @@
+CC = gcc
+CPP = gcc -E
+OPTIM = -O2 -Wall -fomit-frame-pointer
+
+CFLAGS = $(OPTIM) -DLOCALE
+LDFLAGS = -s -L .
+LDLIBS = -lncurses
+
+ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
+ CFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
+else
+ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
+ CFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
+else
+ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
+ CFLAGS += -DCURSES_LOC="<ncurses.h>"
+else
+ CFLAGS += -DCURSES_LOC="<curses.h>"
+endif
+endif
+endif
+
+
+OBJS = checklist.o menubox.o textbox.o yesno.o inputbox.o \
+ util.o lxdialog.o msgbox.o
+SRCS = $(OBJS:.o=.c)
+
+
+all: ncurses lxdialog
+
+lxdialog: $(OBJS)
+
+ncurses:
+ @x=`find /lib/ /usr/lib/ /usr/local/lib/ -maxdepth 1 -name 'libncurses.*'` ;\
+ if [ ! "$$x" ]; then \
+ echo -e "\007" ;\
+ echo ">> Unable to find the Ncurses libraries." ;\
+ echo ">>" ;\
+ echo ">> You must have Ncurses installed in order" ;\
+ echo ">> to use 'make menuconfig'" ;\
+ echo ;\
+ exit 1 ;\
+ fi
+
+clean:
+ rm -f core *.o *~ lxdialog
diff --git a/scripts/lxdialog/checklist.c b/scripts/lxdialog/checklist.c
new file mode 100644
index 000000000..b986b3a2e
--- /dev/null
+++ b/scripts/lxdialog/checklist.c
@@ -0,0 +1,344 @@
+/*
+ * checklist.c -- implements the checklist box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
+ * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static int list_width, check_x, item_x, checkflag;
+
+/*
+ * Print list item
+ */
+static void
+print_item (WINDOW * win, const char *item, int status,
+ int choice, int selected)
+{
+ int i;
+
+ /* Clear 'residue' of last item */
+ wattrset (win, menubox_attr);
+ wmove (win, choice, 0);
+ for (i = 0; i < list_width; i++)
+ waddch (win, ' ');
+
+ wmove (win, choice, check_x);
+ wattrset (win, selected ? check_selected_attr : check_attr);
+ if (checkflag == FLAG_CHECK)
+ wprintw (win, "[%c]", status ? 'X' : ' ');
+ else
+ wprintw (win, "(%c)", status ? 'X' : ' ');
+
+ wattrset (win, selected ? tag_selected_attr : tag_attr);
+ mvwaddch(win, choice, item_x, item[0]);
+ wattrset (win, selected ? item_selected_attr : item_attr);
+ waddstr (win, (char *)item+1);
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int choice, int item_no, int scroll,
+ int y, int x, int height)
+{
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset (win, uarrow_attr);
+ waddch (win, ACS_UARROW);
+ waddstr (win, "(-)");
+ }
+ else {
+ wattrset (win, menubox_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+
+ if ((height < item_no) && (scroll + choice < item_no - 1)) {
+ wattrset (win, darrow_attr);
+ waddch (win, ACS_DARROW);
+ waddstr (win, "(+)");
+ }
+ else {
+ wattrset (win, menubox_border_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+}
+
+/*
+ * Display the termination buttons
+ */
+static void
+print_buttons( WINDOW *dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button (dialog, "Select", y, x, selected == 0);
+ print_button (dialog, " Help ", y, x + 14, selected == 1);
+
+ wmove(dialog, y, x+1 + 14*selected);
+ wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ * The `flag' parameter is used to select between radiolist and checklist.
+ */
+int
+dialog_checklist (const char *title, const char *prompt, int height, int width,
+ int list_height, int item_no, const char * const * items, int flag)
+
+{
+ int i, x, y, box_x, box_y;
+ int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
+ WINDOW *dialog, *list;
+
+ checkflag = flag;
+
+ /* Allocate space for storing item on/off status */
+ if ((status = malloc (sizeof (int) * item_no)) == NULL) {
+ endwin ();
+ fprintf (stderr,
+ "\nCan't allocate memory in dialog_checklist().\n");
+ exit (-1);
+ }
+
+ /* Initializes status */
+ for (i = 0; i < item_no; i++) {
+ status[i] = !strcasecmp (items[i * 3 + 2], "on");
+ if (!choice && status[i])
+ choice = i;
+ }
+
+ max_choice = MIN (list_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ list_width = width - 6;
+ box_y = height - list_height - 5;
+ box_x = (width - list_width) / 2 - 1;
+
+ /* create new window for the list */
+ list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
+
+ keypad (list, TRUE);
+
+ /* draw a box around the list items */
+ draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /* Find length of longest item in order to center checklist */
+ check_x = 0;
+ for (i = 0; i < item_no; i++)
+ check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4);
+
+ check_x = (list_width - check_x) / 2;
+ item_x = check_x + 4;
+
+ /* Print the list */
+ for (i = 0; i < max_choice; i++)
+ print_item (list, items[i * 3 + 1], status[i], i, i == choice);
+
+ wnoutrefresh (list);
+
+ print_arrows(dialog, choice, item_no, scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ print_buttons(dialog, height, width, 0);
+
+ while (key != ESC) {
+ key = wgetch (dialog);
+
+ for (i = 0; i < max_choice; i++)
+ if (toupper(key) == toupper(items[(scroll+i)*3+1][0]))
+ break;
+
+
+ if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||
+ key == '+' || key == '-' ) {
+ if (key == KEY_UP || key == '-') {
+ if (!choice) {
+ if (!scroll)
+ continue;
+ /* Scroll list down */
+ if (list_height > 1) {
+ /* De-highlight current first item */
+ print_item (list, items[scroll * 3 + 1],
+ status[scroll], 0, FALSE);
+ scrollok (list, TRUE);
+ wscrl (list, -1);
+ scrollok (list, FALSE);
+ }
+ scroll--;
+ print_item (list, items[scroll * 3 + 1],
+ status[scroll], 0, TRUE);
+ wnoutrefresh (list);
+
+ print_arrows(dialog, choice, item_no, scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ wrefresh (dialog);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice - 1;
+ } else if (key == KEY_DOWN || key == '+') {
+ if (choice == max_choice - 1) {
+ if (scroll + choice >= item_no - 1)
+ continue;
+ /* Scroll list up */
+ if (list_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1],
+ max_choice - 1, FALSE);
+ scrollok (list, TRUE);
+ scroll (list);
+ scrollok (list, FALSE);
+ }
+ scroll++;
+ print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1],
+ max_choice - 1, TRUE);
+ wnoutrefresh (list);
+
+ print_arrows(dialog, choice, item_no, scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ wrefresh (dialog);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice + 1;
+ }
+ if (i != choice) {
+ /* De-highlight current item */
+ print_item (list, items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, FALSE);
+ /* Highlight new item */
+ choice = i;
+ print_item (list, items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, TRUE);
+ wnoutrefresh (list);
+ wrefresh (dialog);
+ }
+ continue; /* wait for another key press */
+ }
+ switch (key) {
+ case 'H':
+ case 'h':
+ case '?':
+ delwin (dialog);
+ free (status);
+ return 1;
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh (dialog);
+ break;
+ case 'S':
+ case 's':
+ case ' ':
+ case '\n':
+ if (!button) {
+ if (flag == FLAG_CHECK) {
+ status[scroll + choice] = !status[scroll + choice];
+ wmove (list, choice, check_x);
+ wattrset (list, check_selected_attr);
+ wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
+ } else {
+ if (!status[scroll + choice]) {
+ for (i = 0; i < item_no; i++)
+ status[i] = 0;
+ status[scroll + choice] = 1;
+ for (i = 0; i < max_choice; i++)
+ print_item (list, items[(scroll + i) * 3 + 1],
+ status[scroll + i], i, i == choice);
+ }
+ }
+ wnoutrefresh (list);
+ wrefresh (dialog);
+
+ for (i = 0; i < item_no; i++) {
+ if (status[i]) {
+ if (flag == FLAG_CHECK) {
+ fprintf (stderr, "\"%s\" ", items[i * 3]);
+ } else {
+ fprintf (stderr, "%s", items[i * 3]);
+ }
+
+ }
+ }
+ }
+ delwin (dialog);
+ free (status);
+ return button;
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ free (status);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/colors.h b/scripts/lxdialog/colors.h
new file mode 100644
index 000000000..d34dd37c6
--- /dev/null
+++ b/scripts/lxdialog/colors.h
@@ -0,0 +1,161 @@
+/*
+ * colors.h -- color attribute definitions
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * Default color definitions
+ *
+ * *_FG = foreground
+ * *_BG = background
+ * *_HL = highlight?
+ */
+#define SCREEN_FG COLOR_CYAN
+#define SCREEN_BG COLOR_BLUE
+#define SCREEN_HL TRUE
+
+#define SHADOW_FG COLOR_BLACK
+#define SHADOW_BG COLOR_BLACK
+#define SHADOW_HL TRUE
+
+#define DIALOG_FG COLOR_BLACK
+#define DIALOG_BG COLOR_WHITE
+#define DIALOG_HL FALSE
+
+#define TITLE_FG COLOR_YELLOW
+#define TITLE_BG COLOR_WHITE
+#define TITLE_HL TRUE
+
+#define BORDER_FG COLOR_WHITE
+#define BORDER_BG COLOR_WHITE
+#define BORDER_HL TRUE
+
+#define BUTTON_ACTIVE_FG COLOR_WHITE
+#define BUTTON_ACTIVE_BG COLOR_BLUE
+#define BUTTON_ACTIVE_HL TRUE
+
+#define BUTTON_INACTIVE_FG COLOR_BLACK
+#define BUTTON_INACTIVE_BG COLOR_WHITE
+#define BUTTON_INACTIVE_HL FALSE
+
+#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
+#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
+#define BUTTON_KEY_ACTIVE_HL TRUE
+
+#define BUTTON_KEY_INACTIVE_FG COLOR_RED
+#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
+#define BUTTON_KEY_INACTIVE_HL FALSE
+
+#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
+#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
+#define BUTTON_LABEL_ACTIVE_HL TRUE
+
+#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
+#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
+#define BUTTON_LABEL_INACTIVE_HL TRUE
+
+#define INPUTBOX_FG COLOR_BLACK
+#define INPUTBOX_BG COLOR_WHITE
+#define INPUTBOX_HL FALSE
+
+#define INPUTBOX_BORDER_FG COLOR_BLACK
+#define INPUTBOX_BORDER_BG COLOR_WHITE
+#define INPUTBOX_BORDER_HL FALSE
+
+#define SEARCHBOX_FG COLOR_BLACK
+#define SEARCHBOX_BG COLOR_WHITE
+#define SEARCHBOX_HL FALSE
+
+#define SEARCHBOX_TITLE_FG COLOR_YELLOW
+#define SEARCHBOX_TITLE_BG COLOR_WHITE
+#define SEARCHBOX_TITLE_HL TRUE
+
+#define SEARCHBOX_BORDER_FG COLOR_WHITE
+#define SEARCHBOX_BORDER_BG COLOR_WHITE
+#define SEARCHBOX_BORDER_HL TRUE
+
+#define POSITION_INDICATOR_FG COLOR_YELLOW
+#define POSITION_INDICATOR_BG COLOR_WHITE
+#define POSITION_INDICATOR_HL TRUE
+
+#define MENUBOX_FG COLOR_BLACK
+#define MENUBOX_BG COLOR_WHITE
+#define MENUBOX_HL FALSE
+
+#define MENUBOX_BORDER_FG COLOR_WHITE
+#define MENUBOX_BORDER_BG COLOR_WHITE
+#define MENUBOX_BORDER_HL TRUE
+
+#define ITEM_FG COLOR_BLACK
+#define ITEM_BG COLOR_WHITE
+#define ITEM_HL FALSE
+
+#define ITEM_SELECTED_FG COLOR_WHITE
+#define ITEM_SELECTED_BG COLOR_BLUE
+#define ITEM_SELECTED_HL TRUE
+
+#define TAG_FG COLOR_YELLOW
+#define TAG_BG COLOR_WHITE
+#define TAG_HL TRUE
+
+#define TAG_SELECTED_FG COLOR_YELLOW
+#define TAG_SELECTED_BG COLOR_BLUE
+#define TAG_SELECTED_HL TRUE
+
+#define TAG_KEY_FG COLOR_YELLOW
+#define TAG_KEY_BG COLOR_WHITE
+#define TAG_KEY_HL TRUE
+
+#define TAG_KEY_SELECTED_FG COLOR_YELLOW
+#define TAG_KEY_SELECTED_BG COLOR_BLUE
+#define TAG_KEY_SELECTED_HL TRUE
+
+#define CHECK_FG COLOR_BLACK
+#define CHECK_BG COLOR_WHITE
+#define CHECK_HL FALSE
+
+#define CHECK_SELECTED_FG COLOR_WHITE
+#define CHECK_SELECTED_BG COLOR_BLUE
+#define CHECK_SELECTED_HL TRUE
+
+#define UARROW_FG COLOR_GREEN
+#define UARROW_BG COLOR_WHITE
+#define UARROW_HL TRUE
+
+#define DARROW_FG COLOR_GREEN
+#define DARROW_BG COLOR_WHITE
+#define DARROW_HL TRUE
+
+/* End of default color definitions */
+
+#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
+#define COLOR_NAME_LEN 10
+#define COLOR_COUNT 8
+
+/*
+ * Global variables
+ */
+
+typedef struct {
+ char name[COLOR_NAME_LEN];
+ int value;
+} color_names_st;
+
+extern color_names_st color_names[];
+extern int color_table[][3];
diff --git a/scripts/lxdialog/dialog.h b/scripts/lxdialog/dialog.h
new file mode 100644
index 000000000..3be5feb21
--- /dev/null
+++ b/scripts/lxdialog/dialog.h
@@ -0,0 +1,166 @@
+
+/*
+ * dialog.h -- common declarations for all dialog modules
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include CURSES_LOC
+
+#define ESC 27
+#define TAB 9
+#define MAX_LEN 2048
+#define BUF_SIZE (10*1024)
+#define MIN(x,y) (x < y ? x : y)
+#define MAX(x,y) (x > y ? x : y)
+
+
+#ifndef ACS_ULCORNER
+#define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#define ACS_URCORNER '+'
+#endif
+#ifndef ACS_LRCORNER
+#define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#define ACS_VLINE '|'
+#endif
+#ifndef ACS_LTEE
+#define ACS_LTEE '+'
+#endif
+#ifndef ACS_RTEE
+#define ACS_RTEE '+'
+#endif
+#ifndef ACS_UARROW
+#define ACS_UARROW '^'
+#endif
+#ifndef ACS_DARROW
+#define ACS_DARROW 'v'
+#endif
+
+/*
+ * Attribute names
+ */
+#define screen_attr attributes[0]
+#define shadow_attr attributes[1]
+#define dialog_attr attributes[2]
+#define title_attr attributes[3]
+#define border_attr attributes[4]
+#define button_active_attr attributes[5]
+#define button_inactive_attr attributes[6]
+#define button_key_active_attr attributes[7]
+#define button_key_inactive_attr attributes[8]
+#define button_label_active_attr attributes[9]
+#define button_label_inactive_attr attributes[10]
+#define inputbox_attr attributes[11]
+#define inputbox_border_attr attributes[12]
+#define searchbox_attr attributes[13]
+#define searchbox_title_attr attributes[14]
+#define searchbox_border_attr attributes[15]
+#define position_indicator_attr attributes[16]
+#define menubox_attr attributes[17]
+#define menubox_border_attr attributes[18]
+#define item_attr attributes[19]
+#define item_selected_attr attributes[20]
+#define tag_attr attributes[21]
+#define tag_selected_attr attributes[22]
+#define tag_key_attr attributes[23]
+#define tag_key_selected_attr attributes[24]
+#define check_attr attributes[25]
+#define check_selected_attr attributes[26]
+#define uarrow_attr attributes[27]
+#define darrow_attr attributes[28]
+
+/* number of attributes */
+#define ATTRIBUTE_COUNT 29
+
+/*
+ * Global variables
+ */
+extern bool use_colors;
+extern bool use_shadow;
+
+extern chtype attributes[];
+
+extern const char *backtitle;
+
+/*
+ * Function prototypes
+ */
+extern void create_rc (const char *filename);
+extern int parse_rc (void);
+
+
+void init_dialog (void);
+void end_dialog (void);
+void attr_clear (WINDOW * win, int height, int width, chtype attr);
+void dialog_clear (void);
+void color_setup (void);
+void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
+void print_button (WINDOW * win, const char *label, int y, int x, int selected);
+void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
+ chtype border);
+void draw_shadow (WINDOW * win, int y, int x, int height, int width);
+
+int first_alpha (const char *string, const char *exempt);
+int dialog_yesno (const char *title, const char *prompt, int height, int width);
+int dialog_msgbox (const char *title, const char *prompt, int height,
+ int width, int pause);
+int dialog_textbox (const char *title, const char *file, int height, int width);
+int dialog_menu (const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *choice, int item_no,
+ const char * const * items);
+int dialog_checklist (const char *title, const char *prompt, int height,
+ int width, int list_height, int item_no,
+ const char * const * items, int flag);
+extern unsigned char dialog_input_result[];
+int dialog_inputbox (const char *title, const char *prompt, int height,
+ int width, const char *init);
+
+/*
+ * This is the base for fictitious keys, which activate
+ * the buttons.
+ *
+ * Mouse-generated keys are the following:
+ * -- the first 32 are used as numbers, in addition to '0'-'9'
+ * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
+ * -- uppercase chars are used to invoke the button (M_EVENT + 'O')
+ */
+#define M_EVENT (KEY_MAX+1)
+
+
+/*
+ * The `flag' parameter in checklist is used to select between
+ * radiolist and checklist
+ */
+#define FLAG_CHECK 1
+#define FLAG_RADIO 0
diff --git a/scripts/lxdialog/inputbox.c b/scripts/lxdialog/inputbox.c
new file mode 100644
index 000000000..1d0200fa4
--- /dev/null
+++ b/scripts/lxdialog/inputbox.c
@@ -0,0 +1,232 @@
+/*
+ * inputbox.c -- implements the input box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+unsigned char dialog_input_result[MAX_LEN + 1];
+
+/*
+ * Print the termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button (dialog, " Ok ", y, x, selected==0);
+ print_button (dialog, " Help ", y, x + 14, selected==1);
+
+ wmove(dialog, y, x+1+14*selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int
+dialog_inputbox (const char *title, const char *prompt, int height, int width,
+ const char *init)
+{
+ int i, x, y, box_y, box_x, box_width;
+ int input_x = 0, scroll = 0, key = 0, button = -1;
+ unsigned char *instr = dialog_input_result;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ /* Draw the input field box */
+ box_width = width - 6;
+ getyx (dialog, y, x);
+ box_y = y + 2;
+ box_x = (width - box_width) / 2;
+ draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
+ border_attr, dialog_attr);
+
+ print_buttons(dialog, height, width, 0);
+
+ /* Set up the initial value */
+ wmove (dialog, box_y, box_x);
+ wattrset (dialog, inputbox_attr);
+
+ if (!init)
+ instr[0] = '\0';
+ else
+ strcpy (instr, init);
+
+ input_x = strlen (instr);
+
+ if (input_x >= box_width) {
+ scroll = input_x - box_width + 1;
+ input_x = box_width - 1;
+ for (i = 0; i < box_width - 1; i++)
+ waddch (dialog, instr[scroll + i]);
+ } else
+ waddstr (dialog, instr);
+
+ wmove (dialog, box_y, box_x + input_x);
+
+ wrefresh (dialog);
+
+ while (key != ESC) {
+ key = wgetch (dialog);
+
+ if (button == -1) { /* Input box selected */
+ switch (key) {
+ case TAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ break;
+ case KEY_LEFT:
+ continue;
+ case KEY_RIGHT:
+ continue;
+ case KEY_BACKSPACE:
+ case 127:
+ if (input_x || scroll) {
+ wattrset (dialog, inputbox_attr);
+ if (!input_x) {
+ scroll = scroll < box_width - 1 ?
+ 0 : scroll - (box_width - 1);
+ wmove (dialog, box_y, box_x);
+ for (i = 0; i < box_width; i++)
+ waddch (dialog, instr[scroll + input_x + i] ?
+ instr[scroll + input_x + i] : ' ');
+ input_x = strlen (instr) - scroll;
+ } else
+ input_x--;
+ instr[scroll + input_x] = '\0';
+ mvwaddch (dialog, box_y, input_x + box_x, ' ');
+ wmove (dialog, box_y, input_x + box_x);
+ wrefresh (dialog);
+ }
+ continue;
+ default:
+ if (key < 0x100 && isprint (key)) {
+ if (scroll + input_x < MAX_LEN) {
+ wattrset (dialog, inputbox_attr);
+ instr[scroll + input_x] = key;
+ instr[scroll + input_x + 1] = '\0';
+ if (input_x == box_width - 1) {
+ scroll++;
+ wmove (dialog, box_y, box_x);
+ for (i = 0; i < box_width - 1; i++)
+ waddch (dialog, instr[scroll + i]);
+ } else {
+ wmove (dialog, box_y, input_x++ + box_x);
+ waddch (dialog, key);
+ }
+ wrefresh (dialog);
+ } else
+ flash (); /* Alarm user about overflow */
+ continue;
+ }
+ }
+ }
+ switch (key) {
+ case 'O':
+ case 'o':
+ delwin (dialog);
+ return 0;
+ case 'H':
+ case 'h':
+ delwin (dialog);
+ return 1;
+ case KEY_UP:
+ case KEY_LEFT:
+ switch (button) {
+ case -1:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 0:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove (dialog, box_y, box_x + input_x);
+ wrefresh (dialog);
+ break;
+ case 1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ }
+ break;
+ case TAB:
+ case KEY_DOWN:
+ case KEY_RIGHT:
+ switch (button) {
+ case -1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ case 0:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 1:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove (dialog, box_y, box_x + input_x);
+ wrefresh (dialog);
+ break;
+ }
+ break;
+ case ' ':
+ case '\n':
+ delwin (dialog);
+ return (button == -1 ? 0 : button);
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c
new file mode 100644
index 000000000..94d75ded6
--- /dev/null
+++ b/scripts/lxdialog/lxdialog.c
@@ -0,0 +1,223 @@
+/*
+ * dialog - Display simple dialog boxes from shell scripts
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void Usage (const char *name);
+
+typedef int (jumperFn) (const char *title, int argc, const char * const * argv);
+
+struct Mode {
+ char *name;
+ int argmin, argmax, argmod;
+ jumperFn *jumper;
+};
+
+jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox;
+jumperFn j_msgbox, j_infobox;
+
+static struct Mode modes[] =
+{
+ {"--menu", 9, 0, 3, j_menu},
+ {"--checklist", 9, 0, 3, j_checklist},
+ {"--radiolist", 9, 0, 3, j_radiolist},
+ {"--yesno", 5,5,1, j_yesno},
+ {"--textbox", 5,5,1, j_textbox},
+ {"--inputbox", 5, 6, 1, j_inputbox},
+ {"--msgbox", 5, 5, 1, j_msgbox},
+ {"--infobox", 5, 5, 1, j_infobox},
+ {NULL, 0, 0, 0, NULL}
+};
+
+static struct Mode *modePtr;
+
+#ifdef LOCALE
+#include <locale.h>
+#endif
+
+int
+main (int argc, const char * const * argv)
+{
+ int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
+ const char *title = NULL;
+
+#ifdef LOCALE
+ (void) setlocale (LC_ALL, "");
+#endif
+
+ if (argc < 2) {
+ Usage (argv[0]);
+ exit (-1);
+ }
+
+ while (offset < argc - 1 && !end_common_opts) { /* Common options */
+ if (!strcmp (argv[offset + 1], "--title")) {
+ if (argc - offset < 3 || title != NULL) {
+ Usage (argv[0]);
+ exit (-1);
+ } else {
+ title = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp (argv[offset + 1], "--backtitle")) {
+ if (backtitle != NULL) {
+ Usage (argv[0]);
+ exit (-1);
+ } else {
+ backtitle = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp (argv[offset + 1], "--clear")) {
+ if (clear_screen) { /* Hey, "--clear" can't appear twice! */
+ Usage (argv[0]);
+ exit (-1);
+ } else if (argc == 2) { /* we only want to clear the screen */
+ init_dialog ();
+ refresh (); /* init_dialog() will clear the screen for us */
+ end_dialog ();
+ return 0;
+ } else {
+ clear_screen = 1;
+ offset++;
+ }
+ } else /* no more common options */
+ end_common_opts = 1;
+ }
+
+ if (argc - 1 == offset) { /* no more options */
+ Usage (argv[0]);
+ exit (-1);
+ }
+ /* use a table to look for the requested mode, to avoid code duplication */
+
+ for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
+ if (!strcmp (argv[offset + 1], modePtr->name))
+ break;
+
+ if (!modePtr->name)
+ Usage (argv[0]);
+ if (argc - offset < modePtr->argmin)
+ Usage (argv[0]);
+ if (modePtr->argmax && argc - offset > modePtr->argmax)
+ Usage (argv[0]);
+
+
+
+ init_dialog ();
+ retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
+
+ if (clear_screen) { /* clear screen before exit */
+ attr_clear (stdscr, LINES, COLS, screen_attr);
+ refresh ();
+ }
+ end_dialog();
+
+ exit (retval);
+}
+
+/*
+ * Print program usage
+ */
+static void
+Usage (const char *name)
+{
+ fprintf (stderr, "\
+\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
+\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
+\n modified/gutted for use as a Linux kernel config tool by \
+\n William Roadcap (roadcapw@cfw.com)\
+\n\
+\n* Display dialog boxes from shell scripts *\
+\n\
+\nUsage: %s --clear\
+\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
+\n\
+\nBox options:\
+\n\
+\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
+\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --textbox <file> <height> <width>\
+\n --inputbox <text> <height> <width> [<init>]\
+\n --yesno <text> <height> <width>\
+", name, name);
+ exit (-1);
+}
+
+/*
+ * These are the program jumpers
+ */
+
+int
+j_menu (const char *t, int ac, const char * const * av)
+{
+ return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), av[6], (ac - 6) / 2, av + 7);
+}
+
+int
+j_checklist (const char *t, int ac, const char * const * av)
+{
+ return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK);
+}
+
+int
+j_radiolist (const char *t, int ac, const char * const * av)
+{
+ return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO);
+}
+
+int
+j_textbox (const char *t, int ac, const char * const * av)
+{
+ return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4]));
+}
+
+int
+j_yesno (const char *t, int ac, const char * const * av)
+{
+ return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4]));
+}
+
+int
+j_inputbox (const char *t, int ac, const char * const * av)
+{
+ int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]),
+ ac == 6 ? av[5] : (char *) NULL);
+ if (ret == 0)
+ fprintf(stderr, dialog_input_result);
+ return ret;
+}
+
+int
+j_msgbox (const char *t, int ac, const char * const * av)
+{
+ return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1);
+}
+
+int
+j_infobox (const char *t, int ac, const char * const * av)
+{
+ return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0);
+}
+
diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c
new file mode 100644
index 000000000..ad4380870
--- /dev/null
+++ b/scripts/lxdialog/menubox.c
@@ -0,0 +1,350 @@
+/*
+ * menubox.c -- implements the menu box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static int menu_width, item_x;
+
+/*
+ * Print menu item
+ */
+static void
+print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
+{
+ int i, j;
+ char menu_item[menu_width+1];
+
+ strncpy(menu_item, item, menu_width);
+ menu_item[menu_width] = 0;
+ j = first_alpha(menu_item, "YyNnMm");
+
+ /* Clear 'residue' of last item */
+ wattrset (win, menubox_attr);
+ wmove (win, choice, 0);
+ for (i = 0; i < menu_width; i++)
+ waddch (win, ' ');
+ wattrset (win, selected ? item_selected_attr : item_attr);
+ mvwaddstr (win, choice, item_x, menu_item);
+ if (hotkey) {
+ wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
+ mvwaddch(win, choice, item_x+j, menu_item[j]);
+ }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int item_no, int scroll,
+ int y, int x, int height)
+{
+ int cur_y, cur_x;
+
+ getyx(win, cur_y, cur_x);
+
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset (win, uarrow_attr);
+ waddch (win, ACS_UARROW);
+ waddstr (win, "(-)");
+ }
+ else {
+ wattrset (win, menubox_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+
+ if ((height < item_no) && (scroll + height < item_no)) {
+ wattrset (win, darrow_attr);
+ waddch (win, ACS_DARROW);
+ waddstr (win, "(+)");
+ }
+ else {
+ wattrset (win, menubox_border_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+
+ wmove(win, cur_y, cur_x);
+}
+
+/*
+ * Display the termination buttons.
+ */
+static void
+print_buttons (WINDOW *win, int height, int width, int selected)
+{
+ int x = width / 2 - 16;
+ int y = height - 2;
+
+ print_button (win, "Select", y, x, selected == 0);
+ print_button (win, " Exit ", y, x + 12, selected == 1);
+ print_button (win, " Help ", y, x + 24, selected == 2);
+
+ wmove(win, y, x+1+12*selected);
+ wrefresh (win);
+}
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int
+dialog_menu (const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *current, int item_no,
+ const char * const * items)
+
+{
+ int i, j, x, y, box_x, box_y;
+ int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
+ WINDOW *dialog, *menu;
+
+ max_choice = MIN (menu_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ menu_width = width - 6;
+ box_y = height - menu_height - 5;
+ box_x = (width - menu_width) / 2 - 1;
+
+ /* create new window for the menu */
+ menu = subwin (dialog, menu_height, menu_width,
+ y + box_y + 1, x + box_x + 1);
+ keypad (menu, TRUE);
+
+ /* draw a box around the menu items */
+ draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /*
+ * Find length of longest item in order to center menu.
+ * Set 'choice' to default item.
+ */
+ item_x = 0;
+ for (i = 0; i < item_no; i++) {
+ item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2));
+ if (strcmp(current, items[i*2]) == 0) choice = i;
+ }
+
+ item_x = (menu_width - item_x) / 2;
+
+ if (choice >= max_choice){
+ scroll = first_item = choice - max_choice + 1;
+ choice = max_choice-1;
+ }
+
+ /* Print the menu */
+ for (i=0; i < max_choice; i++) {
+ print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice,
+ (items[(first_item + i)*2][0] != ':'));
+ }
+
+ wnoutrefresh (menu);
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x+item_x+1, menu_height);
+
+ print_buttons (dialog, height, width, 0);
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+
+ if (key < 256 && isalpha(key)) key = tolower(key);
+
+ if (strchr("ynm", key))
+ i = max_choice;
+ else {
+ for (i = choice+1; i < max_choice; i++) {
+ j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
+ if (key == tolower(items[(scroll+i)*2+1][j]))
+ break;
+ }
+ if (i == max_choice)
+ for (i = 0; i < max_choice; i++) {
+ j = first_alpha(items[(scroll+i)*2+1], "YyNnMm");
+ if (key == tolower(items[(scroll+i)*2+1][j]))
+ break;
+ }
+ }
+
+ if (i < max_choice ||
+ key == KEY_UP || key == KEY_DOWN ||
+ key == '-' || key == '+' ||
+ key == KEY_PPAGE || key == KEY_NPAGE) {
+
+ print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
+ (items[(scroll+choice)*2][0] != ':'));
+
+ if (key == KEY_UP || key == '-') {
+ if (choice < 2 && scroll) {
+ /* Scroll menu down */
+ scrollok (menu, TRUE);
+ wscrl (menu, -1);
+ scrollok (menu, FALSE);
+
+ scroll--;
+
+ print_item (menu, items[scroll * 2 + 1], 0, FALSE,
+ (items[scroll*2][0] != ':'));
+ } else
+ choice = MAX(choice - 1, 0);
+
+ } else if (key == KEY_DOWN || key == '+') {
+
+ print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
+ (items[(scroll+choice)*2][0] != ':'));
+
+ if ((choice > max_choice-3) &&
+ (scroll + max_choice < item_no)
+ ) {
+ /* Scroll menu up */
+ scrollok (menu, TRUE);
+ scroll (menu);
+ scrollok (menu, FALSE);
+
+ scroll++;
+
+ print_item (menu, items[(scroll+max_choice-1)*2+1],
+ max_choice-1, FALSE,
+ (items[(scroll+max_choice-1)*2][0] != ':'));
+ } else
+ choice = MIN(choice+1, max_choice-1);
+
+ } else if (key == KEY_PPAGE) {
+ scrollok (menu, TRUE);
+ for (i=0; (i < max_choice) && (scroll > 0); i++) {
+ wscrl (menu, -1);
+ scroll--;
+ print_item (menu, items[scroll * 2 + 1], 0, FALSE,
+ (items[scroll*2][0] != ':'));
+ }
+ scrollok (menu, FALSE);
+ choice = 0;
+
+ } else if (key == KEY_NPAGE) {
+ scrollok (menu, TRUE);
+ for (i=0; (i < max_choice) && (scroll+max_choice < item_no); i++) {
+ scroll(menu);
+ scroll++;
+ print_item (menu, items[(scroll+max_choice-1)*2+1],
+ max_choice-1, FALSE,
+ (items[(scroll+max_choice-1)*2][0] != ':'));
+ }
+ scrollok (menu, FALSE);
+ choice = 0;
+
+ } else
+ choice = i;
+
+ print_item (menu, items[(scroll+choice)*2+1], choice, TRUE,
+ (items[(scroll+choice)*2][0] != ':'));
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x+item_x+1, menu_height);
+
+ wnoutrefresh (menu);
+ wrefresh (dialog);
+
+ continue; /* wait for another key press */
+ }
+
+ switch (key) {
+ case KEY_LEFT:
+ case TAB:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 2 : (button > 2 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh (dialog);
+ break;
+ case ' ':
+ case 's':
+ case 'y':
+ case 'n':
+ case 'm':
+ delwin (dialog);
+ fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+ switch (key) {
+ case 's': return 3;
+ case 'y': return 3;
+ case 'n': return 4;
+ case 'm': return 5;
+ case ' ': return 6;
+ }
+ return 0;
+ case 'h':
+ case '?':
+ button = 2;
+ case '\n':
+ delwin (dialog);
+ if (button == 2)
+ fprintf(stderr, "%s \"%s\"\n",
+ items[(scroll + choice) * 2],
+ items[(scroll + choice) * 2 + 1] +
+ first_alpha(items[(scroll + choice) * 2 + 1],""));
+ else
+ fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+
+ return button;
+ case 'e':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/msgbox.c b/scripts/lxdialog/msgbox.c
new file mode 100644
index 000000000..19ae28c52
--- /dev/null
+++ b/scripts/lxdialog/msgbox.c
@@ -0,0 +1,77 @@
+/*
+ * msgbox.c -- implements the message box and info box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display a message box. Program will pause and display an "OK" button
+ * if the parameter 'pause' is non-zero.
+ */
+int
+dialog_msgbox (const char *title, const char *prompt, int height, int width,
+ int pause)
+{
+ int i, x, y, key = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 2);
+
+ if (pause) {
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ print_button (dialog, " Ok ",
+ height - 2, width / 2 - 4, TRUE);
+
+ wrefresh (dialog);
+ while (key != ESC && key != '\n' && key != ' ' &&
+ key != 'O' && key != 'o' && key != 'X' && key != 'x')
+ key = wgetch (dialog);
+ } else {
+ key = '\n';
+ wrefresh (dialog);
+ }
+
+ delwin (dialog);
+ return key == ESC ? -1 : 0;
+}
diff --git a/scripts/lxdialog/textbox.c b/scripts/lxdialog/textbox.c
new file mode 100644
index 000000000..df50f2c54
--- /dev/null
+++ b/scripts/lxdialog/textbox.c
@@ -0,0 +1,537 @@
+/*
+ * textbox.c -- implements the text box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void back_lines (int n);
+static void print_page (WINDOW * win, int height, int width);
+static void print_line (WINDOW * win, int row, int width);
+static char *get_line (void);
+static void print_position (WINDOW * win, int height, int width);
+
+static int hscroll = 0, fd, file_size, bytes_read;
+static int begin_reached = 1, end_reached = 0, page_length;
+static char *buf, *page;
+
+/*
+ * Display text from a file in a dialog box.
+ */
+int
+dialog_textbox (const char *title, const char *file, int height, int width)
+{
+ int i, x, y, cur_x, cur_y, fpos, key = 0;
+ int passed_end;
+ char search_term[MAX_LEN + 1];
+ WINDOW *dialog, *text;
+
+ search_term[0] = '\0'; /* no search term entered yet */
+
+ /* Open input file for reading */
+ if ((fd = open (file, O_RDONLY)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nCan't open input file in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Get file size. Actually, 'file_size' is the real file size - 1,
+ since it's only the last byte offset from the beginning */
+ if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Restore file pointer to beginning of file after getting file size */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Allocate space for read buffer */
+ if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
+ endwin ();
+ fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0'; /* mark end of valid data */
+ page = buf; /* page is pointer to start of page to be displayed */
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ /* Create window for text region, used for scrolling text */
+ text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
+
+ keypad (text, TRUE);
+
+ /* register the new window, along with its borders */
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+ print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
+ wnoutrefresh (dialog);
+ getyx (dialog, cur_y, cur_x); /* Save cursor position */
+
+ /* Print first page of text */
+ attr_clear (text, height - 4, width - 2, dialog_attr);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+
+ while ((key != ESC) && (key != '\n')) {
+ key = wgetch (dialog);
+ switch (key) {
+ case 'E': /* Exit */
+ case 'e':
+ case 'X':
+ case 'x':
+ delwin (dialog);
+ free (buf);
+ close (fd);
+ return 0;
+ case 'g': /* First page */
+ case KEY_HOME:
+ if (!begin_reached) {
+ begin_reached = 1;
+ /* First page not in buffer? */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) { /* Yes, we have to read it in */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf;
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case 'G': /* Last page */
+ case KEY_END:
+
+ end_reached = 1;
+ /* Last page not in buffer? */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if (fpos < file_size) { /* Yes, we have to read it in */
+ if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf + bytes_read;
+ back_lines (height - 4);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ break;
+ case 'K': /* Previous line */
+ case 'k':
+ case KEY_UP:
+ if (!begin_reached) {
+ back_lines (page_length + 1);
+
+ /* We don't call print_page() here but use scrolling to ensure
+ faster screen update. However, 'end_reached' and
+ 'page_length' should still be updated, and 'page' should
+ point to start of next page. This is done by calling
+ get_line() in the following 'for' loop. */
+ scrollok (text, TRUE);
+ wscrl (text, -1); /* Scroll text region down one line */
+ scrollok (text, FALSE);
+ page_length = 0;
+ passed_end = 0;
+ for (i = 0; i < height - 4; i++) {
+ if (!i) {
+ /* print first line of page */
+ print_line (text, 0, width - 2);
+ wnoutrefresh (text);
+ } else
+ /* Called to update 'end_reached' and 'page' */
+ get_line ();
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case 'B': /* Previous page */
+ case 'b':
+ case KEY_PPAGE:
+ if (begin_reached)
+ break;
+ back_lines (page_length + height - 4);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case 'J': /* Next line */
+ case 'j':
+ case KEY_DOWN:
+ if (!end_reached) {
+ begin_reached = 0;
+ scrollok (text, TRUE);
+ scroll (text); /* Scroll text region up one line */
+ scrollok (text, FALSE);
+ print_line (text, height - 5, width - 2);
+ wnoutrefresh (text);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case KEY_NPAGE: /* Next page */
+ case ' ':
+ if (end_reached)
+ break;
+
+ begin_reached = 0;
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case '0': /* Beginning of line */
+ case 'H': /* Scroll left */
+ case 'h':
+ case KEY_LEFT:
+ if (hscroll <= 0)
+ break;
+
+ if (key == '0')
+ hscroll = 0;
+ else
+ hscroll--;
+ /* Reprint current page to scroll horizontally */
+ back_lines (page_length);
+ print_page (text, height - 4, width - 2);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case 'L': /* Scroll right */
+ case 'l':
+ case KEY_RIGHT:
+ if (hscroll >= MAX_LEN)
+ break;
+ hscroll++;
+ /* Reprint current page to scroll horizontally */
+ back_lines (page_length);
+ print_page (text, height - 4, width - 2);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ free (buf);
+ close (fd);
+ return -1; /* ESC pressed */
+}
+
+/*
+ * Go back 'n' lines in text file. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void
+back_lines (int n)
+{
+ int i, fpos;
+
+ begin_reached = 0;
+ /* We have to distinguish between end_reached and !end_reached
+ since at end of file, the line is not ended by a '\n'.
+ The code inside 'if' basically does a '--page' to move one
+ character backward so as to skip '\n' of the previous line */
+ if (!end_reached) {
+ /* Either beginning of buffer or beginning of file reached? */
+ if (page == buf) {
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) { /* Not beginning of file yet */
+ /* We've reached beginning of buffer, but not beginning of
+ file yet, so read previous part of file into buffer.
+ Note that we only move backward for BUF_SIZE/2 bytes,
+ but not BUF_SIZE bytes to avoid re-reading again in
+ print_page() later */
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
+ == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in back_lines().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ if (*(--page) != '\n') { /* '--page' here */
+ /* Something's wrong... */
+ endwin ();
+ fprintf (stderr, "\nInternal error in back_lines().\n");
+ exit (-1);
+ }
+ }
+ /* Go back 'n' lines */
+ for (i = 0; i < n; i++)
+ do {
+ if (page == buf) {
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in back_lines().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) {
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
+ SEEK_CUR) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer"
+ " in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ } while (*(--page) != '\n');
+ page++;
+}
+
+/*
+ * Print a new page of text. Called by dialog_textbox().
+ */
+static void
+print_page (WINDOW * win, int height, int width)
+{
+ int i, passed_end = 0;
+
+ page_length = 0;
+ for (i = 0; i < height; i++) {
+ print_line (win, i, width);
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+ wnoutrefresh (win);
+}
+
+/*
+ * Print a new line of text. Called by dialog_textbox() and print_page().
+ */
+static void
+print_line (WINDOW * win, int row, int width)
+{
+ int i, y, x;
+ char *line;
+
+ line = get_line ();
+ line += MIN (strlen (line), hscroll); /* Scroll horizontally */
+ wmove (win, row, 0); /* move cursor to correct line */
+ waddch (win, ' ');
+ waddnstr (win, line, MIN (strlen (line), width - 2));
+
+ getyx (win, y, x);
+ /* Clear 'residue' of previous line */
+ for (i = 0; i < width - x; i++)
+ waddch (win, ' ');
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *
+get_line (void)
+{
+ int i = 0, fpos;
+ static char line[MAX_LEN + 1];
+
+ end_reached = 0;
+ while (*page != '\n') {
+ if (*page == '\0') {
+ /* Either end of file or end of buffer reached */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "get_line().\n");
+ exit (-1);
+ }
+ if (fpos < file_size) { /* Not end of file yet */
+ /* We've reached end of buffer, but not end of file yet,
+ so read next part of file into buffer */
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in get_line().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ page = buf;
+ } else {
+ if (!end_reached)
+ end_reached = 1;
+ break;
+ }
+ } else if (i < MAX_LEN)
+ line[i++] = *(page++);
+ else {
+ /* Truncate lines longer than MAX_LEN characters */
+ if (i == MAX_LEN)
+ line[i++] = '\0';
+ page++;
+ }
+ }
+ if (i <= MAX_LEN)
+ line[i] = '\0';
+ if (!end_reached)
+ page++; /* move pass '\n' */
+
+ return line;
+}
+
+/*
+ * Print current position
+ */
+static void
+print_position (WINDOW * win, int height, int width)
+{
+ int fpos, percent;
+
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in print_position().\n");
+ exit (-1);
+ }
+ wattrset (win, position_indicator_attr);
+ percent = !file_size ?
+ 100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
+ wmove (win, height - 3, width - 9);
+ wprintw (win, "(%3d%%)", percent);
+}
diff --git a/scripts/lxdialog/util.c b/scripts/lxdialog/util.c
new file mode 100644
index 000000000..b3a7af9d2
--- /dev/null
+++ b/scripts/lxdialog/util.c
@@ -0,0 +1,359 @@
+/*
+ * util.c
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+
+/* use colors by default? */
+bool use_colors = 1;
+
+const char *backtitle = NULL;
+
+const char *dialog_result;
+
+/*
+ * Attribute values, default is for mono display
+ */
+chtype attributes[] =
+{
+ A_NORMAL, /* screen_attr */
+ A_NORMAL, /* shadow_attr */
+ A_NORMAL, /* dialog_attr */
+ A_BOLD, /* title_attr */
+ A_NORMAL, /* border_attr */
+ A_REVERSE, /* button_active_attr */
+ A_DIM, /* button_inactive_attr */
+ A_REVERSE, /* button_key_active_attr */
+ A_BOLD, /* button_key_inactive_attr */
+ A_REVERSE, /* button_label_active_attr */
+ A_NORMAL, /* button_label_inactive_attr */
+ A_NORMAL, /* inputbox_attr */
+ A_NORMAL, /* inputbox_border_attr */
+ A_NORMAL, /* searchbox_attr */
+ A_BOLD, /* searchbox_title_attr */
+ A_NORMAL, /* searchbox_border_attr */
+ A_BOLD, /* position_indicator_attr */
+ A_NORMAL, /* menubox_attr */
+ A_NORMAL, /* menubox_border_attr */
+ A_NORMAL, /* item_attr */
+ A_REVERSE, /* item_selected_attr */
+ A_BOLD, /* tag_attr */
+ A_REVERSE, /* tag_selected_attr */
+ A_BOLD, /* tag_key_attr */
+ A_REVERSE, /* tag_key_selected_attr */
+ A_BOLD, /* check_attr */
+ A_REVERSE, /* check_selected_attr */
+ A_BOLD, /* uarrow_attr */
+ A_BOLD /* darrow_attr */
+};
+
+
+#include "colors.h"
+
+/*
+ * Table of color values
+ */
+int color_table[][3] =
+{
+ {SCREEN_FG, SCREEN_BG, SCREEN_HL},
+ {SHADOW_FG, SHADOW_BG, SHADOW_HL},
+ {DIALOG_FG, DIALOG_BG, DIALOG_HL},
+ {TITLE_FG, TITLE_BG, TITLE_HL},
+ {BORDER_FG, BORDER_BG, BORDER_HL},
+ {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
+ {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
+ {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
+ {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
+ {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
+ {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
+ BUTTON_LABEL_INACTIVE_HL},
+ {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
+ {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
+ {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
+ {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
+ {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
+ {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
+ {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
+ {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
+ {ITEM_FG, ITEM_BG, ITEM_HL},
+ {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
+ {TAG_FG, TAG_BG, TAG_HL},
+ {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
+ {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
+ {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
+ {CHECK_FG, CHECK_BG, CHECK_HL},
+ {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
+ {UARROW_FG, UARROW_BG, UARROW_HL},
+ {DARROW_FG, DARROW_BG, DARROW_HL},
+}; /* color_table */
+
+/*
+ * Set window to attribute 'attr'
+ */
+void
+attr_clear (WINDOW * win, int height, int width, chtype attr)
+{
+ int i, j;
+
+ wattrset (win, attr);
+ for (i = 0; i < height; i++) {
+ wmove (win, i, 0);
+ for (j = 0; j < width; j++)
+ waddch (win, ' ');
+ }
+ touchwin (win);
+}
+
+void dialog_clear (void)
+{
+ attr_clear (stdscr, LINES, COLS, screen_attr);
+ /* Display background title if it exists ... - SLH */
+ if (backtitle != NULL) {
+ int i;
+
+ wattrset (stdscr, screen_attr);
+ mvwaddstr (stdscr, 0, 1, (char *)backtitle);
+ wmove (stdscr, 1, 1);
+ for (i = 1; i < COLS - 1; i++)
+ waddch (stdscr, ACS_HLINE);
+ }
+ wnoutrefresh (stdscr);
+}
+
+/*
+ * Do some initialization for dialog
+ */
+void
+init_dialog (void)
+{
+ initscr (); /* Init curses */
+ keypad (stdscr, TRUE);
+ cbreak ();
+ noecho ();
+
+
+ if (use_colors) /* Set up colors */
+ color_setup ();
+
+
+ dialog_clear ();
+}
+
+/*
+ * Setup for color display
+ */
+void
+color_setup (void)
+{
+ int i;
+
+ if (has_colors ()) { /* Terminal supports color? */
+ start_color ();
+
+ /* Initialize color pairs */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ init_pair (i + 1, color_table[i][0], color_table[i][1]);
+
+ /* Setup color attributes */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ attributes[i] = C_ATTR (color_table[i][2], i + 1);
+ }
+}
+
+/*
+ * End using dialog functions.
+ */
+void
+end_dialog (void)
+{
+ endwin ();
+}
+
+
+/*
+ * Print a string of text in a window, automatically wrap around to the
+ * next line if the string is too long to fit on one line. Newline
+ * characters '\n' are replaced by spaces. We start on a new line
+ * if there is no room for at least 4 nonblanks following a double-space.
+ */
+void
+print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
+{
+ int newl, cur_x, cur_y;
+ int i, prompt_len, room, wlen;
+ char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
+
+ strcpy (tempstr, prompt);
+
+ prompt_len = strlen(tempstr);
+
+ /*
+ * Remove newlines
+ */
+ for(i=0; i<prompt_len; i++) {
+ if(tempstr[i] == '\n') tempstr[i] = ' ';
+ }
+
+ if (prompt_len <= width - x * 2) { /* If prompt is short */
+ wmove (win, y, (width - prompt_len) / 2);
+ waddstr (win, tempstr);
+ } else {
+ cur_x = x;
+ cur_y = y;
+ newl = 1;
+ word = tempstr;
+ while (word && *word) {
+ sp = index(word, ' ');
+ if (sp)
+ *sp++ = 0;
+
+ /* Wrap to next line if either the word does not fit,
+ or it is the first word of a new sentence, and it is
+ short, and the next word does not fit. */
+ room = width - cur_x;
+ wlen = strlen(word);
+ if (wlen > room ||
+ (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
+ && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
+ cur_y++;
+ cur_x = x;
+ }
+ wmove (win, cur_y, cur_x);
+ waddstr (win, word);
+ getyx (win, cur_y, cur_x);
+ cur_x++;
+ if (sp && *sp == ' ') {
+ cur_x++; /* double space */
+ while (*++sp == ' ');
+ newl = 1;
+ } else
+ newl = 0;
+ word = sp;
+ }
+ }
+}
+
+/*
+ * Print a button
+ */
+void
+print_button (WINDOW * win, const char *label, int y, int x, int selected)
+{
+ int i, temp;
+
+ wmove (win, y, x);
+ wattrset (win, selected ? button_active_attr : button_inactive_attr);
+ waddstr (win, "<");
+ temp = strspn (label, " ");
+ label += temp;
+ wattrset (win, selected ? button_label_active_attr
+ : button_label_inactive_attr);
+ for (i = 0; i < temp; i++)
+ waddch (win, ' ');
+ wattrset (win, selected ? button_key_active_attr
+ : button_key_inactive_attr);
+ waddch (win, label[0]);
+ wattrset (win, selected ? button_label_active_attr
+ : button_label_inactive_attr);
+ waddstr (win, (char *)label + 1);
+ wattrset (win, selected ? button_active_attr : button_inactive_attr);
+ waddstr (win, ">");
+ wmove (win, y, x + temp + 1);
+}
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void
+draw_box (WINDOW * win, int y, int x, int height, int width,
+ chtype box, chtype border)
+{
+ int i, j;
+
+ wattrset (win, 0);
+ for (i = 0; i < height; i++) {
+ wmove (win, y + i, x);
+ for (j = 0; j < width; j++)
+ if (!i && !j)
+ waddch (win, border | ACS_ULCORNER);
+ else if (i == height - 1 && !j)
+ waddch (win, border | ACS_LLCORNER);
+ else if (!i && j == width - 1)
+ waddch (win, box | ACS_URCORNER);
+ else if (i == height - 1 && j == width - 1)
+ waddch (win, box | ACS_LRCORNER);
+ else if (!i)
+ waddch (win, border | ACS_HLINE);
+ else if (i == height - 1)
+ waddch (win, box | ACS_HLINE);
+ else if (!j)
+ waddch (win, border | ACS_VLINE);
+ else if (j == width - 1)
+ waddch (win, box | ACS_VLINE);
+ else
+ waddch (win, box | ' ');
+ }
+}
+
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void
+draw_shadow (WINDOW * win, int y, int x, int height, int width)
+{
+ int i;
+
+ if (has_colors ()) { /* Whether terminal supports color? */
+ wattrset (win, shadow_attr);
+ wmove (win, y + height, x + 2);
+ for (i = 0; i < width; i++)
+ waddch (win, winch (win) & A_CHARTEXT);
+ for (i = y + 1; i < y + height + 1; i++) {
+ wmove (win, i, x + width);
+ waddch (win, winch (win) & A_CHARTEXT);
+ waddch (win, winch (win) & A_CHARTEXT);
+ }
+ wnoutrefresh (win);
+ }
+}
+
+/*
+ * Return the position of the first alphabetic character in a string.
+ */
+int
+first_alpha(const char *string, const char *exempt)
+{
+ int i, in_paren=0, c;
+
+ for (i = 0; i < strlen(string); i++) {
+ c = tolower(string[i]);
+
+ if (strchr("<[(", c)) ++in_paren;
+ if (strchr(">])", c)) --in_paren;
+
+ if ((! in_paren) && isalpha(c) &&
+ strchr(exempt, c) == 0)
+ return i;
+ }
+
+ return 0;
+}
diff --git a/scripts/lxdialog/yesno.c b/scripts/lxdialog/yesno.c
new file mode 100644
index 000000000..6f40af645
--- /dev/null
+++ b/scripts/lxdialog/yesno.c
@@ -0,0 +1,110 @@
+/*
+ * yesno.c -- implements the yes/no box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 10;
+ int y = height - 2;
+
+ print_button (dialog, " Yes ", y, x, selected == 0);
+ print_button (dialog, " No ", y, x + 13, selected == 1);
+
+ wmove(dialog, y, x+1 + 13*selected );
+ wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int
+dialog_yesno (const char *title, const char *prompt, int height, int width)
+{
+ int i, x, y, key = 0, button = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ print_buttons(dialog, height, width, 0);
+
+ while (key != ESC) {
+ key = wgetch (dialog);
+ switch (key) {
+ case 'Y':
+ case 'y':
+ delwin (dialog);
+ return 0;
+ case 'N':
+ case 'n':
+ delwin (dialog);
+ return 1;
+
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh (dialog);
+ break;
+ case ' ':
+ case '\n':
+ delwin (dialog);
+ return button;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/mkdep.c b/scripts/mkdep.c
new file mode 100644
index 000000000..43140b0a7
--- /dev/null
+++ b/scripts/mkdep.c
@@ -0,0 +1,297 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+
+char *filename, *command, __depname[256] = "\n\t@touch ";
+int needsconfig, hasconfig, hasdep;
+
+#define depname (__depname+9)
+
+struct path_struct {
+ int len;
+ char buffer[256-sizeof(int)];
+} path_array[2] = {
+ { 23, "/usr/src/linux/include/" },
+ { 0, "" }
+};
+
+static void handle_include(int type, char *name, int len)
+{
+ int plen;
+ struct path_struct *path = path_array+type;
+
+ if (!type) {
+ if (memcmp(name, "linux/", 6) &&
+ memcmp(name, "asm/", 4) &&
+ memcmp(name, "net/", 4) &&
+ memcmp(name, "scsi/", 5))
+ return;
+ if (len == 14 && !memcmp(name, "linux/config.h", len))
+ hasconfig = 1;
+ }
+
+ plen = path->len;
+ memcpy(path->buffer+plen, name, len);
+ len += plen;
+ path->buffer[len] = '\0';
+
+ if (!hasdep) {
+ hasdep = 1;
+ printf("%s:", depname);
+ }
+ printf(" \\\n %s", path->buffer);
+}
+
+static void handle_config(void)
+{
+ needsconfig = 1;
+ if (!hasconfig)
+ fprintf(stderr,
+ "%s needs config but has not included config file\n",
+ filename);
+}
+
+#if defined(__alpha__) || defined(__i386__)
+#define LE_MACHINE
+#endif
+
+#ifdef LE_MACHINE
+#define next_byte(x) (x >>= 8)
+#define current ((unsigned char) __buf)
+#else
+#define next_byte(x) (x <<= 8)
+#define current (__buf >> 8*(sizeof(unsigned long)-1))
+#endif
+
+#define GETNEXT { \
+next_byte(__buf); \
+if (!__nrbuf) { \
+ __buf = *(unsigned long *) next; \
+ __nrbuf = sizeof(unsigned long); \
+ if (!__buf) \
+ break; \
+} next++; __nrbuf--; }
+#define CASE(c,label) if (current == c) goto label
+#define NOTCASE(c,label) if (current != c) goto label
+
+static void state_machine(register char *next)
+{
+ for(;;) {
+ register unsigned long __buf = 0;
+ register unsigned long __nrbuf = 0;
+
+normal:
+ GETNEXT
+__normal:
+ CASE('/',slash);
+ CASE('"',string);
+ CASE('\'',char_const);
+ CASE('#',preproc);
+ goto normal;
+
+slash:
+ GETNEXT
+ CASE('*',comment);
+ goto __normal;
+
+string:
+ GETNEXT
+ CASE('"',normal);
+ NOTCASE('\\',string);
+ GETNEXT
+ goto string;
+
+char_const:
+ GETNEXT
+ CASE('\'',normal);
+ NOTCASE('\\',char_const);
+ GETNEXT
+ goto char_const;
+
+comment:
+ GETNEXT
+__comment:
+ NOTCASE('*',comment);
+ GETNEXT
+ CASE('/',normal);
+ goto __comment;
+
+preproc:
+ GETNEXT
+ CASE('\n',normal);
+ CASE(' ',preproc);
+ CASE('\t',preproc);
+ CASE('i',i_preproc);
+ GETNEXT
+
+skippreproc:
+ CASE('\n',normal);
+ CASE('\\',skippreprocslash);
+ GETNEXT
+ goto skippreproc;
+
+skippreprocslash:
+ GETNEXT;
+ GETNEXT;
+ goto skippreproc;
+
+i_preproc:
+ GETNEXT
+ CASE('f',if_line);
+ NOTCASE('n',skippreproc);
+ GETNEXT
+ NOTCASE('c',skippreproc);
+ GETNEXT
+ NOTCASE('l',skippreproc);
+ GETNEXT
+ NOTCASE('u',skippreproc);
+ GETNEXT
+ NOTCASE('d',skippreproc);
+ GETNEXT
+ NOTCASE('e',skippreproc);
+
+/* "# include" found */
+include_line:
+ GETNEXT
+ CASE('\n',normal);
+ CASE('<', std_include_file);
+ NOTCASE('"', include_line);
+
+/* "local" include file */
+{
+ char *incname = next;
+local_include_name:
+ GETNEXT
+ CASE('\n',normal);
+ NOTCASE('"', local_include_name);
+ handle_include(1, incname, next-incname-1);
+ goto skippreproc;
+}
+
+/* <std> include file */
+std_include_file:
+{
+ char *incname = next;
+std_include_name:
+ GETNEXT
+ CASE('\n',normal);
+ NOTCASE('>', std_include_name);
+ handle_include(0, incname, next-incname-1);
+ goto skippreproc;
+}
+
+if_line:
+ if (needsconfig)
+ goto skippreproc;
+if_start:
+ GETNEXT
+ CASE('C', config);
+ CASE('\n', normal);
+ CASE('_', if_middle);
+ if (current >= 'a' && current <= 'z')
+ goto if_middle;
+ if (current < 'A' || current > 'Z')
+ goto if_start;
+config:
+ GETNEXT
+ NOTCASE('O', __if_middle);
+ GETNEXT
+ NOTCASE('N', __if_middle);
+ GETNEXT
+ NOTCASE('F', __if_middle);
+ GETNEXT
+ NOTCASE('I', __if_middle);
+ GETNEXT
+ NOTCASE('G', __if_middle);
+ GETNEXT
+ NOTCASE('_', __if_middle);
+ handle_config();
+ goto skippreproc;
+
+if_middle:
+ GETNEXT
+__if_middle:
+ CASE('\n', normal);
+ CASE('_', if_middle);
+ if (current >= 'a' && current <= 'z')
+ goto if_middle;
+ if (current < 'A' || current > 'Z')
+ goto if_start;
+ goto if_middle;
+ }
+}
+
+static void do_depend(void)
+{
+ char *map;
+ int mapsize;
+ int pagesizem1 = getpagesize()-1;
+ int fd = open(filename, O_RDONLY);
+ struct stat st;
+
+ if (fd < 0) {
+ perror("mkdep: open");
+ return;
+ }
+ fstat(fd, &st);
+ mapsize = st.st_size + 2*sizeof(unsigned long);
+ mapsize = (mapsize+pagesizem1) & ~pagesizem1;
+ map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (-1 == (long)map) {
+ perror("mkdep: mmap");
+ close(fd);
+ return;
+ }
+ close(fd);
+ state_machine(map);
+ munmap(map, mapsize);
+ if (hasdep)
+ puts(command);
+}
+
+int main(int argc, char **argv)
+{
+ int len;
+ char * hpath;
+
+ hpath = getenv("HPATH");
+ if (!hpath)
+ hpath = "/usr/src/linux/include";
+ len = strlen(hpath);
+ memcpy(path_array[0].buffer, hpath, len);
+ if (len && hpath[len-1] != '/') {
+ path_array[0].buffer[len] = '/';
+ len++;
+ }
+ path_array[0].buffer[len] = '\0';
+ path_array[0].len = len;
+
+ while (--argc > 0) {
+ int len;
+ char *name = *++argv;
+
+ filename = name;
+ len = strlen(name);
+ memcpy(depname, name, len+1);
+ command = __depname;
+ if (len > 2 && name[len-2] == '.') {
+ switch (name[len-1]) {
+ case 'c':
+ case 'S':
+ depname[len-1] = 'o';
+ command = "";
+ }
+ }
+ needsconfig = hasconfig = hasdep = 0;
+ do_depend();
+ if (hasconfig && !needsconfig)
+ fprintf(stderr, "%s doesn't need config\n", filename);
+ }
+ return 0;
+}
diff --git a/scripts/patch-kernel b/scripts/patch-kernel
new file mode 100644
index 000000000..2028efcbc
--- /dev/null
+++ b/scripts/patch-kernel
@@ -0,0 +1,53 @@
+#! /bin/sh
+# Script to apply kernel patches.
+# usage: patch-kernel [ sourcedir [ patchdir ] ]
+# The source directory defaults to /usr/src/linux, and the patch
+# directory defaults to the current directory.
+#
+# It determines the current kernel version from the top-level Makefile.
+# It then looks for patches for the next sublevel in the patch directory.
+# This is applied using "patch -p1 -s" from within the kernel directory.
+# A check is then made for "*.rej" files to see if the patch was
+# successful. If it is, then all of the "*.orig" files are removed.
+#
+# Nick Holloway <Nick.Holloway@alfie.demon.co.uk>, 2nd January 1995.
+
+# Set directories from arguments, or use defaults.
+sourcedir=${1-/usr/src/linux}
+patchdir=${2-.}
+
+# set current VERSION, PATCHLEVEL, SUBLEVEL
+eval `sed -n 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' $sourcedir/Makefile`
+if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
+then
+ echo "unable to determine current kernel version" >&2
+ exit 1
+fi
+
+echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL"
+
+while :
+do
+ SUBLEVEL=`expr $SUBLEVEL + 1`
+ patch=patch-$VERSION.$PATCHLEVEL.$SUBLEVEL.gz
+ if [ ! -r $patchdir/$patch ]
+ then
+ break
+ fi
+
+ echo -n "Applying $patch... "
+ if gunzip -dc $patchdir/$patch | patch -p1 -s -N -E -d $sourcedir
+ then
+ echo "done."
+ else
+ echo "failed. Clean up yourself."
+ break
+ fi
+ if [ "`find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
+ then
+ echo "Aborting. Reject files found."
+ break
+ fi
+ # Remove backup files
+ find $sourcedir/ '(' -name '*.orig' -o -name '.*.orig' ')' -exec rm -f {} \;
+done
diff --git a/scripts/pathdown.sh b/scripts/pathdown.sh
new file mode 100644
index 000000000..16c17b2a8
--- /dev/null
+++ b/scripts/pathdown.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+UP=
+DN=${PWD:?}
+TP=${TOPDIR:?}
+
+while [ ! $TP/$UP/. -ef $DN ] ;do
+ UP=`basename $PWD`/$UP
+ cd ..
+ if [ "$PWD" = "/" ]; then echo "Lost"; exit 1; fi
+done
+
+echo $UP
+exit 0
diff --git a/scripts/tail.tk b/scripts/tail.tk
new file mode 100644
index 000000000..ee2edae7e
--- /dev/null
+++ b/scripts/tail.tk
@@ -0,0 +1,78 @@
+
+pack .header -side top -padx 10 -pady 10 -expand on
+pack .f0 -side top -padx 15 -pady 10 -fill y -expand on
+
+#
+# Misc buttons to save/restore state and so forth.
+#
+frame .f0_bot
+frame .f0_bot.r
+frame .f0_bot.l
+
+#
+# Read the user's settings from .config. These will override whatever is
+# in config.in. Don't do this if the user specified a -D to force
+# the defaults.
+#
+if { [file readable .config] == 1} then {
+ if { $argc > 0 } then {
+ if { [lindex $argv 0] != "-D" } then {
+ read_config .config
+ }
+ else
+ {
+ read_config $defaults
+ }
+ } else {
+ read_config .config
+ }
+} else {
+ read_config $defaults
+}
+
+update_mainmenu .f0
+
+button .f0_bot.r.save -text "Save and Exit" -width 25 -command {
+ writeconfig .config include/linux/autoconf.h; wrapup .wrap }
+
+button .f0_bot.r.quit -text "Quit Without Saving" -width 25 \
+ -command { maybe_exit .maybe }
+
+button .f0_bot.l.store -text "Store Configuration to File" -width 25 -command {
+ load_configfile .load "Save Configuration in file" write_config_file
+}
+
+button .f0_bot.l.load -text "Load Configuration from File" -width 25 -command {
+ load_configfile .load "Load Configuration from file" read_config_file
+}
+
+pack .f0_bot.r.save .f0_bot.r.quit -padx 25 -ipadx 10 -ipady 2 -expand on
+pack .f0_bot.l.load .f0_bot.l.store -padx 25 -ipadx 10 -ipady 2 -expand on
+
+pack .f0_bot.r -side left -padx 15 -pady 10 -expand on -fill y
+pack .f0_bot.l -side right -padx 15 -pady 10 -expand on -fill y
+
+pack .f0_bot -fill both -expand on
+
+#
+# If we cannot write our config files, disable the write button.
+#
+if { [file exists .config] == 1 } then {
+ if { [file writable .config] == 0 } then {
+ .f0_bot.r.save configure -state disabled
+ }
+ } else {
+ if { [file writable .] == 0 } then {
+ .f0_bot.r.save configure -state disabled
+ }
+ }
+
+if { [file exists include/linux/autoconf.h] == 1 } then {
+ if { [file writable include/linux/autoconf.h] == 0 } then {
+ .f0_bot.r.save configure -state disabled
+ }
+ } else {
+ if { [file writable include/linux/] == 0 } then {
+ .f0_bot.r.save configure -state disabled
+ }
+ }
diff --git a/scripts/tkcond.c b/scripts/tkcond.c
new file mode 100644
index 000000000..9cc10fa4f
--- /dev/null
+++ b/scripts/tkcond.c
@@ -0,0 +1,542 @@
+/* parser config.in
+ *
+ * Version 1.0
+ * Eric Youngdale
+ * 10/95
+ *
+ * The general idea here is that we want to parse a config.in file and
+ * from this, we generate a wish script which gives us effectively the
+ * same functionality that the original config.in script provided.
+ *
+ * This task is split roughly into 3 parts. The first parse is the parse
+ * of the input file itself. The second part is where we analyze the
+ * #ifdef clauses, and attach a linked list of tokens to each of the
+ * menu items. In this way, each menu item has a complete list of
+ * dependencies that are used to enable/disable the options.
+ * The third part is to take the configuration database we have build,
+ * and build the actual wish script.
+ *
+ * This file contains the code to further process the conditions from
+ * the "ifdef" clauses.
+ *
+ * The conditions are assumed to be one of the following formats
+ *
+ * simple_condition:= "$VARIABLE" == y/n/m
+ * simple_condition:= "$VARIABLE != y/n/m
+ *
+ * simple_condition -a simple_condition
+ *
+ * If the input condition contains '(' or ')' it would screw us up, but for now
+ * this is not a problem.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "tkparse.h"
+
+
+/*
+ * Walk a condition chain and invert it so that the logical result is
+ * inverted.
+ */
+static void invert_condition(struct condition * cnd)
+{
+ /*
+ * This is simple. Just walk through the list, and invert
+ * all of the operators.
+ */
+ for(;cnd; cnd = cnd->next)
+ {
+ switch(cnd->op)
+ {
+ case op_and:
+ cnd->op = op_or;
+ break;
+ case op_or:
+ /*
+ * This is not turned into op_and - we need to keep track
+ * of what operators were used here since we have an optimization
+ * later on to remove duplicate conditions, and having
+ * inverted ors in there would make it harder if we did not
+ * distinguish an inverted or from an and we inserted because
+ * of nested ifs.
+ */
+ cnd->op = op_and1;
+ break;
+ case op_neq:
+ cnd->op = op_eq;
+ break;
+ case op_eq:
+ cnd->op = op_neq;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * Walk a condition chain, and free the memory associated with it.
+ */
+static void free_condition(struct condition * cnd)
+{
+ struct condition * next;
+ for(;cnd; cnd = next)
+ {
+ next = cnd->next;
+
+ if( cnd->variable.str != NULL )
+ free(cnd->variable.str);
+
+ free(cnd);
+ }
+}
+
+/*
+ * Walk all of the conditions, and look for choice values. Convert
+ * the tokens into something more digestible.
+ */
+void fix_choice_cond()
+{
+ struct condition * cond;
+ struct condition * cond2;
+ struct kconfig * cfg;
+ char tmpbuf[10];
+
+ for(cfg = config;cfg != NULL; cfg = cfg->next)
+ {
+ if( cfg->cond == NULL )
+ {
+ continue;
+ }
+
+ for(cond = cfg->cond; cond != NULL; cond = cond->next)
+ {
+ if( cond->op != op_kvariable )
+ continue;
+
+ if( cond->variable.cfg->tok != tok_choice )
+ continue;
+
+ /*
+ * Look ahead for what we are comparing this to. There should
+ * be one operator in between.
+ */
+ cond2 = cond->next->next;
+ strcpy(tmpbuf, cond->variable.cfg->label);
+
+ if( strcmp(cond2->variable.str, "y") == 0 )
+ {
+ cond->variable.cfg = cond->variable.cfg->choice_label;
+ cond2->variable.str = strdup(tmpbuf);
+ }
+ else
+ {
+ fprintf(stderr,"Ooops\n");
+ exit(0);
+ }
+ }
+
+ }
+}
+
+/*
+ * Walk the stack of conditions, and clone all of them with "&&" operators
+ * gluing them together. The conditions from each level of the stack
+ * are wrapped in parenthesis so as to guarantee that the results
+ * are logically correct.
+ */
+struct condition * get_token_cond(struct condition ** cond, int depth)
+{
+ int i;
+ struct condition * newcond;
+ struct condition * tail;
+ struct condition * new;
+ struct condition * ocond;
+ struct kconfig * cfg;
+
+ newcond = tail = NULL;
+ for(i=0; i<depth; i++, cond++)
+ {
+ /*
+ * First insert the left parenthesis
+ */
+ new = (struct condition *) malloc(sizeof(struct condition));
+ memset(new, 0, sizeof(*new));
+ new->op = op_lparen;
+ if( tail == NULL )
+ {
+ newcond = tail = new;
+ }
+ else
+ {
+ tail->next = new;
+ tail = new;
+ }
+
+ /*
+ * Now duplicate the chain.
+ */
+ ocond = *cond;
+ for(;ocond != NULL; ocond = ocond->next)
+ {
+ new = (struct condition *) malloc(sizeof(struct condition));
+ memset(new, 0, sizeof(*new));
+ new->op = ocond->op;
+ if( ocond->variable.str != NULL )
+ {
+ if( ocond->op == op_variable )
+ {
+ /*
+ * Search for structure to insert here.
+ */
+ for(cfg = config;cfg != NULL; cfg = cfg->next)
+ {
+ if( cfg->tok != tok_bool
+ && cfg->tok != tok_int
+ && cfg->tok != tok_hex
+ && cfg->tok != tok_tristate
+ && cfg->tok != tok_choice
+ && cfg->tok != tok_dep_tristate)
+ {
+ continue;
+ }
+ if( strcmp(cfg->optionname, ocond->variable.str) == 0)
+ {
+ new->variable.cfg = cfg;
+ new->op = op_kvariable;
+ break;
+ }
+ }
+ if( cfg == NULL )
+ {
+ new->variable.str = strdup(ocond->variable.str);
+ }
+ }
+ else
+ {
+ new->variable.str = strdup(ocond->variable.str);
+ }
+ }
+ tail->next = new;
+ tail = new;
+ }
+
+ /*
+ * Next insert the left parenthesis
+ */
+ new = (struct condition *) malloc(sizeof(struct condition));
+ memset(new, 0, sizeof(*new));
+ new->op = op_rparen;
+ tail->next = new;
+ tail = new;
+
+ /*
+ * Insert an and operator, if we have another condition.
+ */
+ if( i < depth - 1 )
+ {
+ new = (struct condition *) malloc(sizeof(struct condition));
+ memset(new, 0, sizeof(*new));
+ new->op = op_and;
+ tail->next = new;
+ tail = new;
+ }
+
+ }
+
+ return newcond;
+}
+
+/*
+ * Walk a single chain of conditions and clone it. These are assumed
+ * to be created/processed by get_token_cond in a previous pass.
+ */
+struct condition * get_token_cond_frag(struct condition * cond,
+ struct condition ** last)
+{
+ struct condition * newcond;
+ struct condition * tail;
+ struct condition * new;
+ struct condition * ocond;
+
+ newcond = tail = NULL;
+
+ /*
+ * Now duplicate the chain.
+ */
+ for(ocond = cond;ocond != NULL; ocond = ocond->next)
+ {
+ new = (struct condition *) malloc(sizeof(struct condition));
+ memset(new, 0, sizeof(*new));
+ new->op = ocond->op;
+ new->variable.cfg = ocond->variable.cfg;
+ if( tail == NULL )
+ {
+ newcond = tail = new;
+ }
+ else
+ {
+ tail->next = new;
+ tail = new;
+ }
+ }
+
+ new = (struct condition *) malloc(sizeof(struct condition));
+ memset(new, 0, sizeof(*new));
+ new->op = op_and;
+ tail->next = new;
+ tail = new;
+
+ *last = tail;
+ return newcond;
+}
+
+/*
+ * Walk through the if conditionals and maintain a chain.
+ */
+void fix_conditionals(struct kconfig * scfg)
+{
+ int depth = 0;
+ int i;
+ struct kconfig * cfg;
+ struct kconfig * cfg1;
+ struct condition * conditions[25];
+ struct condition * cnd;
+ struct condition * cnd1;
+ struct condition * cnd2;
+ struct condition * cnd3;
+ struct condition * newcond;
+ struct condition * last;
+
+ /*
+ * Start by walking the chain. Every time we see an ifdef, push
+ * the condition chain on the stack. When we see an "else", we invert
+ * the condition at the top of the stack, and when we see an "endif"
+ * we free all of the memory for the condition at the top of the stack
+ * and remove the condition from the top of the stack.
+ *
+ * For any other type of token (i.e. a bool), we clone a new condition chain
+ * by anding together all of the conditions that are currently stored on
+ * the stack. In this way, we have a correct representation of whatever
+ * conditions govern the usage of each option.
+ */
+ memset(conditions, 0, sizeof(conditions));
+ for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+ {
+ switch(cfg->tok)
+ {
+ case tok_if:
+ /*
+ * Push this condition on the stack, and nuke the token
+ * representing the ifdef, since we no longer need it.
+ */
+ conditions[depth] = cfg->cond;
+ depth++;
+ cfg->tok = tok_nop;
+ cfg->cond = NULL;
+ break;
+ case tok_else:
+ /*
+ * For an else, we just invert the condition at the top of
+ * the stack. This is done in place with no reallocation
+ * of memory taking place.
+ */
+ invert_condition(conditions[depth-1]);
+ cfg->tok = tok_nop;
+ break;
+ case tok_fi:
+ depth--;
+ free_condition(conditions[depth]);
+ conditions[depth] = NULL;
+ cfg->tok = tok_nop;
+ break;
+ case tok_comment:
+ case tok_define:
+ case tok_menuoption:
+ case tok_bool:
+ case tok_tristate:
+ case tok_int:
+ case tok_hex:
+ case tok_choice:
+ case tok_make:
+ /*
+ * We need to duplicate the chain of conditions and attach them to
+ * this token.
+ */
+ cfg->cond = get_token_cond(&conditions[0], depth);
+ break;
+ case tok_dep_tristate:
+ /*
+ * Same as tok_tristate et al except we have a temporary
+ * conditional. (Sort of a hybrid tok_if, tok_tristate, tok_fi
+ * option)
+ */
+ conditions[depth] = cfg->cond;
+ depth++;
+ cfg->cond = get_token_cond(&conditions[0], depth);
+ depth--;
+ free_condition(conditions[depth]);
+ conditions[depth] = NULL;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Fix any conditions involving the "choice" operator.
+ */
+ fix_choice_cond();
+
+ /*
+ * Walk through and see if there are multiple options that control the
+ * same kvariable. If there are we need to treat them a little bit
+ * special.
+ */
+ for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+ {
+ switch(cfg->tok)
+ {
+ case tok_bool:
+ case tok_tristate:
+ case tok_dep_tristate:
+ case tok_int:
+ case tok_hex:
+ for(cfg1=cfg;cfg1 != NULL; cfg1 = cfg1->next)
+ {
+ switch(cfg1->tok)
+ {
+ case tok_define:
+ case tok_bool:
+ case tok_tristate:
+ case tok_dep_tristate:
+ case tok_int:
+ case tok_hex:
+ if( strcmp(cfg->optionname, cfg1->optionname) == 0)
+ {
+ cfg->flags |= CFG_DUP;
+ cfg1->flags |= CFG_DUP;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Now go through the list, and every time we see a kvariable, check
+ * to see whether it also has some dependencies. If so, then
+ * append it to our list. The reason we do this is that we might have
+ * option CONFIG_FOO which is only used if CONFIG_BAR is set. It may
+ * turn out that in config.in that the default value for CONFIG_BAR is
+ * set to "y", but that CONFIG_BAR is not enabled because CONFIG_XYZZY
+ * is not set. The current condition chain does not reflect this, but
+ * we can fix this by searching for the tokens that this option depends
+ * upon and cloning the conditions and merging them with the list.
+ */
+ for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+ {
+ /*
+ * Search for a token that has a condition list.
+ */
+ if(cfg->cond == NULL) continue;
+ for(cnd = cfg->cond; cnd; cnd=cnd->next)
+ {
+ /*
+ * Now search the condition list for a known configuration variable
+ * that has conditions of its own.
+ */
+ if(cnd->op != op_kvariable) continue;
+ if(cnd->variable.cfg->cond == NULL) continue;
+
+ if(cnd->variable.cfg->flags & CFG_DUP) continue;
+ /*
+ * OK, we have some conditions to append to cfg. Make a clone
+ * of the conditions,
+ */
+ newcond = get_token_cond_frag(cnd->variable.cfg->cond, &last);
+
+ /*
+ * Finally, we splice it into our list.
+ */
+ last->next = cfg->cond;
+ cfg->cond = newcond;
+
+ }
+ }
+
+ /*
+ * There is a strong possibility that we have duplicate conditions
+ * in here. It would make the script more efficient and readable to
+ * remove these. Here is where we assume here that there are no
+ * parenthesis in the input script.
+ */
+ for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+ {
+ /*
+ * Search for configuration options that have conditions.
+ */
+ if(cfg->cond == NULL) continue;
+ for(cnd = cfg->cond; cnd; cnd=cnd->next)
+ {
+ /*
+ * Search for a left parenthesis.
+ */
+ if(cnd->op != op_lparen) continue;
+ for(cnd1 = cnd->next; cnd1; cnd1=cnd1->next)
+ {
+ /*
+ * Search after the previous left parenthesis, and try
+ * and find a second left parenthesis.
+ */
+ if(cnd1->op != op_lparen) continue;
+
+ /*
+ * Now compare the next 5 tokens to see if they are
+ * identical. We are looking for two chains that
+ * are like: '(' $VARIABLE operator constant ')'.
+ */
+ cnd2 = cnd;
+ cnd3 = cnd1;
+ for(i=0; i<5; i++, cnd2=cnd2->next, cnd3=cnd3->next)
+ {
+ if(!cnd2 || !cnd3) break;
+ if(cnd2->op != cnd3->op) break;
+ if(i == 1 && (cnd2->op != op_kvariable
+ || cnd2->variable.cfg != cnd3->variable.cfg) ) break;
+ if(i==2 && cnd2->op != op_eq && cnd2->op != op_neq) break;
+ if(i == 3 && cnd2->op != op_constant &&
+ strcmp(cnd2->variable.str, cnd3->variable.str) != 0)
+ break;
+ if(i==4 && cnd2->op != op_rparen) break;
+ }
+ /*
+ * If these match, and there is an and gluing these together,
+ * then we can nuke the second one.
+ */
+ if(i==5 && ((cnd3 && cnd3->op == op_and)
+ ||(cnd2 && cnd2->op == op_and)))
+ {
+ /*
+ * We have a duplicate. Nuke 5 ops.
+ */
+ cnd3 = cnd1;
+ for(i=0; i<5; i++, cnd3=cnd3->next)
+ {
+ cnd3->op = op_nuked;
+ }
+ /*
+ * Nuke the and that glues the conditions together.
+ */
+ if(cnd3 && cnd3->op == op_and) cnd3->op = op_nuked;
+ else if(cnd2 && cnd2->op == op_and) cnd2->op = op_nuked;
+ }
+ }
+ }
+ }
+}
diff --git a/scripts/tkgen.c b/scripts/tkgen.c
new file mode 100644
index 000000000..fc9338db3
--- /dev/null
+++ b/scripts/tkgen.c
@@ -0,0 +1,1132 @@
+/* Generate tk script based upon config.in
+ *
+ * Version 1.0
+ * Eric Youngdale
+ * 10/95
+ *
+ * 1996 01 04
+ * Avery Pennarun - Aesthetic improvements.
+ *
+ * 1996 01 24
+ * Avery Pennarun - Bugfixes and more aesthetics.
+ *
+ * 1996 03 08
+ * Avery Pennarun - The int and hex config.in commands work right.
+ * - Choice buttons are more user-friendly.
+ * - Disabling a text entry line greys it out properly.
+ * - dep_tristate now works like in Configure. (not pretty)
+ * - No warnings in gcc -Wall. (Fixed some "interesting" bugs.)
+ * - Faster/prettier "Help" lookups.
+ *
+ * 1996 03 15
+ * Avery Pennarun - Added new sed script from Axel Boldt to make help even
+ * faster. (Actually awk is downright slow on some machines.)
+ * - Fixed a bug I introduced into Choice dependencies. Thanks
+ * to Robert Krawitz for pointing this out.
+ *
+ * 1996 03 16
+ * Avery Pennarun - basic "do_make" support added to let sound config work.
+ *
+ * 1996 03 25
+ * Axel Boldt - Help now works on "choice" buttons.
+ *
+ * 1996 04 06
+ * Avery Pennarun - Improved sound config stuff. (I think it actually works
+ * now!)
+ * - Window-resize-limits don't use ugly /usr/lib/tk4.0 hack.
+ * - int/hex work with tk3 again. (The "cget" error.)
+ * - Next/Prev buttons switch between menus. I can't take
+ * much credit for this; the code was already there, but
+ * ifdef'd out for some reason. It flickers a lot, but
+ * I suspect there's no "easy" fix for that.
+ * - Labels no longer highlight as you move the mouse over
+ * them (although you can still press them... oh well.)
+ * - Got rid of the last of the literal color settings, to
+ * help out people with mono X-Windows systems.
+ * (Apparently there still are some out there!)
+ * - Tabstops seem sensible now.
+ *
+ * 1996 04 14
+ * Avery Pennarun - Reduced flicker when creating windows, even with "update
+ * idletasks" hack.
+ *
+ * TO DO:
+ * - clean up - there are useless ifdef's everywhere.
+ * - better comments throughout - C code generating tcl is really cryptic.
+ * - eliminate silly "update idletasks" hack to improve display speed and
+ * reduce flicker. But how?
+ * - make canvas contents resize with the window (good luck).
+ * - some way to make submenus inside of submenus (ie. Main->Networking->IP)
+ * (perhaps a button where the description would be)
+ * - make the main menu use the same tcl code as the submenus.
+ * - make choice and int/hex input types line up vertically with
+ * bool/tristate.
+ * - general speedups - how? The canvas seems to slow it down a lot.
+ * - choice buttons should default to the first menu option, rather than a
+ * blank. Also look up the right variable when the help button
+ * is pressed.
+ * - clean up +/- 16 confusion for enabling/disabling variables; causes
+ * (theoretical, at the moment) problems with dependencies.
+ *
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include "tkparse.h"
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+/*
+ * This is the total number of submenus that we have.
+ */
+static int tot_menu_num =0;
+
+/*
+ * 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)
+{
+ if( flag )
+ 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("\ttoplevel $w -class Dialog\n");
+ printf("\twm withdraw $w\n");
+ 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");
+ printf("\twm title $w \"%s\" \n\n", label);
+
+ /*
+ * 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"
+ "\t\t-width 15 -command \"destroy $w; focus $oldFocus; update_mainmenu $w\"\n");
+ printf("\tbutton $w.f.next -text \"Next\" \\\n"
+ "\t\t-width 15 -command \" destroy $w; focus $oldFocus; 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"
+ "\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n",
+ menu_num-1, menu_num-1);
+ if (1 == menu_num)
+ 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");
+ printf("\tpack $w.f -pady 10 -side bottom -anchor w -fill x\n");
+
+ /*
+ * Lines between canvas and other areas of the window.
+ */
+ printf("\tframe $w.topline -relief ridge -borderwidth 2 -height 2\n");
+ printf("\tpack $w.topline -side top -fill x\n\n");
+ printf("\tframe $w.botline -relief ridge -borderwidth 2 -height 2\n");
+ printf("\tpack $w.botline -side bottom -fill x\n\n");
+
+ /*
+ * The "config" frame contains the canvas and a scrollbar.
+ */
+ printf("\tframe $w.config\n");
+ printf("\tpack $w.config -fill y -expand on\n\n");
+ printf("\tscrollbar $w.config.vscroll -command \"$w.config.canvas yview\"\n");
+ printf("\tpack $w.config.vscroll -side right -fill y\n\n");
+
+ /*
+ * The scrollable canvas itself, where the real work (and mess) gets done.
+ */
+ printf("\tcanvas $w.config.canvas -height 1\\\n"
+ "\t\t-relief flat -borderwidth 0 -yscrollcommand \"$w.config.vscroll set\" \\\n"
+ "\t\t-width [expr [winfo screenwidth .] * 1 / 2] \n");
+ printf("\tframe $w.config.f\n");
+ printf("\tpack $w.config.canvas -side right -fill y\n");
+
+ printf("\n\n");
+}
+
+/*
+ * Each proc we create needs a global declaration for any global variables we
+ * use. To minimize the size of the file, we set a flag each time we output
+ * a global declaration so we know whether we need to insert one for a
+ * given function or not.
+ */
+void clear_globalflags(struct kconfig * cfg)
+{
+ for(; cfg != NULL; cfg = cfg->next)
+ {
+ cfg->flags &= ~GLOBAL_WRITTEN;
+ }
+}
+
+/*
+ * Output a "global" line for a given variable. Also include the
+ * call to "vfix". (If vfix is not needed, then it's fine to just printf
+ * a "global" line).
+ */
+void inline global(char *var)
+{
+ printf("\tglobal %s; vfix %s\n", var, var);
+}
+
+/*
+ * This function walks the chain of conditions that we got from cond.c,
+ * and creates a wish conditional to enable/disable a given widget.
+ */
+void generate_if(struct kconfig * item,
+ struct condition * cond,
+ int menu_num,
+ int line_num)
+{
+ struct condition * ocond;
+
+ ocond = cond;
+
+ /*
+ * First write any global declarations we need for this conditional.
+ */
+ while(cond != NULL )
+ {
+ switch(cond->op){
+ case op_variable:
+ global(cond->variable.str);
+ break;
+ case op_kvariable:
+ if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
+ cond->variable.cfg->flags |= GLOBAL_WRITTEN;
+ global(cond->variable.cfg->optionname);
+ break;
+ default:
+ break;
+ }
+ cond = cond->next;
+ }
+
+ /*
+ * Now write this option.
+ */
+ if( (item->flags & GLOBAL_WRITTEN) == 0
+ && (item->optionname != NULL) )
+ {
+ global(item->optionname);
+ item->flags |= GLOBAL_WRITTEN;
+ }
+ /*
+ * Now generate the body of the conditional.
+ */
+ printf("\tif {");
+ cond = ocond;
+ while(cond != NULL )
+ {
+ switch(cond->op){
+ case op_bang:
+ printf(" ! ");
+ break;
+ case op_eq:
+ printf(" == ");
+ break;
+ case op_neq:
+ printf(" != ");
+ break;
+ case op_and:
+ case op_and1:
+ printf(" && ");
+ break;
+ case op_or:
+ printf(" || ");
+ break;
+ case op_lparen:
+ printf("(");
+ break;
+ case op_rparen:
+ printf(")");
+ break;
+ case op_variable:
+ printf("$%s", cond->variable.str);
+ break;
+ case op_kvariable:
+ printf("$%s", cond->variable.cfg->optionname);
+ break;
+ case op_shellcmd:
+ printf("[exec %s]", cond->variable.str);
+ break;
+ case op_constant:
+ if( strcmp(cond->variable.str, "y") == 0 )
+ printf("1");
+ else if( strcmp(cond->variable.str, "n") == 0 )
+ printf("0");
+ else if( strcmp(cond->variable.str, "m") == 0 )
+ printf("2");
+ else
+ printf("\"%s\"", cond->variable.str);
+ break;
+ default:
+ break;
+ }
+ cond = cond->next;
+ }
+
+ /*
+ * Now we generate what we do depending upon the value of the conditional.
+ * Depending upon what the token type is, there are different things
+ * we must do to enable/disable the given widget - this code needs to
+ * be closely coordinated with the widget creation procedures in header.tk.
+ */
+ switch(item->tok)
+ {
+ case tok_define:
+ printf("} then { set %s %s } \n", item->optionname, item->value);
+ break;
+ case tok_menuoption:
+ printf("} then { .f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
+ menu_num, menu_num);
+ break;
+ case tok_int:
+ case tok_hex:
+ printf("} then { ");
+ printf(".menu%d.config.f.x%d.x configure -state normal -fore [ 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 -fore [ cget .ref -disabledforeground ];", menu_num, line_num );
+ printf(".menu%d.config.f.x%d.l configure -state disabled;", menu_num, line_num );
+ printf("}\n");
+ break;
+ case tok_bool:
+#ifdef BOOL_IS_BUTTON
+ /*
+ * If a bool is just a button, then use this definition.
+ */
+ printf("} then { .menu%d.config.f.x%d configure -state normal } else { .menu%d.config.f.x%d configure -state disabled }\n",
+ menu_num, line_num,
+ menu_num, line_num );
+#else
+ /*
+ * If a bool is a radiobutton, then use this instead.
+ */
+ printf("} then { ");
+ 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];", item->optionname, item->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];", item->optionname, item->optionname);
+ printf("}\n");
+#endif
+ break;
+ case tok_tristate:
+ case tok_dep_tristate:
+ printf("} then { ");
+ if( item->tok == tok_dep_tristate )
+ {
+ global(item->depend.str);
+ printf("if { $%s != 1 && $%s != 0 } then {",
+ item->depend.str,item->depend.str);
+ printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
+ printf("} else {");
+ printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
+ printf("}; ");
+ }
+ else
+ {
+ 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.m configure -state normal;",menu_num, line_num);
+ printf(".menu%d.config.f.x%d.l configure -state normal;",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("set %s [expr $%s&15];", item->optionname, item->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);
+ /*
+ * Clear the disable bit - this causes the correct radiobutton
+ * to appear selected (i.e. turn red).
+ */
+ printf("set %s [expr $%s|16];", item->optionname, item->optionname);
+ printf("}\n");
+ break;
+ case tok_choose:
+ case tok_choice:
+ fprintf(stderr,"Fixme\n");
+ exit(0);
+ default:
+ break;
+ }
+}
+
+/*
+ * Similar to generate_if, except we come here when generating an
+ * output file. Thus instead of enabling/disabling a widget, we
+ * need to decide whether to write out a given configuration variable
+ * to the output file.
+ */
+void generate_if_for_outfile(struct kconfig * item,
+ struct condition * cond)
+{
+ struct condition * ocond;
+
+ /*
+ * First write any global declarations we need for this conditional.
+ */
+ ocond = cond;
+ for(; cond != NULL; cond = cond->next )
+ {
+ switch(cond->op){
+ case op_variable:
+ global(cond->variable.str);
+ break;
+ case op_kvariable:
+ if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
+ cond->variable.cfg->flags |= GLOBAL_WRITTEN;
+ global(cond->variable.cfg->optionname);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Now generate the body of the conditional.
+ */
+ printf("\tif {");
+ cond = ocond;
+ while(cond != NULL )
+ {
+ switch(cond->op){
+ case op_bang:
+ printf(" ! ");
+ break;
+ case op_eq:
+ printf(" == ");
+ break;
+ case op_neq:
+ printf(" != ");
+ break;
+ case op_and:
+ case op_and1:
+ printf(" && ");
+ break;
+ case op_or:
+ printf(" || ");
+ break;
+ case op_lparen:
+ printf("(");
+ break;
+ case op_rparen:
+ printf(")");
+ break;
+ case op_variable:
+ printf("$%s", cond->variable.str);
+ break;
+ case op_shellcmd:
+ printf("[exec %s]", cond->variable.str);
+ break;
+ case op_kvariable:
+ printf("$%s", cond->variable.cfg->optionname);
+ break;
+ case op_constant:
+ if( strcmp(cond->variable.str, "y") == 0 )
+ printf("1");
+ else if( strcmp(cond->variable.str, "n") == 0 )
+ printf("0");
+ else if( strcmp(cond->variable.str, "m") == 0 )
+ printf("2");
+ else
+ printf("\"%s\"", cond->variable.str);
+ break;
+ default:
+ break;
+ }
+ cond = cond->next;
+ }
+
+ /*
+ * Now we generate what we do depending upon the value of the
+ * conditional. Depending upon what the token type is, there are
+ * different things we must do write the value the given widget -
+ * this code needs to be closely coordinated with the widget
+ * creation procedures in header.tk.
+ */
+ switch(item->tok)
+ {
+ case tok_define:
+ printf("} then {write_tristate $cfg $autocfg %s %s $notmod }\n", item->optionname, item->value);
+ break;
+ case tok_comment:
+ printf("} then {write_comment $cfg $autocfg \"%s\"}\n", item->label);
+ break;
+ case tok_dep_tristate:
+ printf("} then { write_tristate $cfg $autocfg %s $%s $%s } \n",
+ item->optionname, item->optionname, item->depend.str);
+ break;
+ case tok_tristate:
+ case tok_bool:
+ printf("} then { write_tristate $cfg $autocfg %s $%s $notmod }\n",
+ item->optionname, item->optionname);
+ break;
+ case tok_int:
+ printf("} then { write_int $cfg $autocfg %s $%s $notmod }\n",
+ item->optionname, item->optionname);
+ break;
+ case tok_hex:
+ printf("} then { write_hex $cfg $autocfg %s $%s $notmod }\n",
+ item->optionname, item->optionname);
+ break;
+ case tok_make:
+ printf("} then { do_make {%s} }\n",item->value);
+ break;
+ case tok_choose:
+ case tok_choice:
+ fprintf(stderr,"Fixme\n");
+ exit(0);
+ default:
+ break;
+ }
+}
+
+/*
+ * Generates a fragment of wish script that closes out a submenu procedure.
+ */
+static void end_proc(int menu_num)
+{
+ struct kconfig * cfg;
+
+ printf("\n\n\n");
+ printf("\tfocus $w\n");
+ printf("\tupdate_menu%d $w.config.f\n", menu_num);
+ printf("\tglobal winx; global winy\n");
+ printf("\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n");
+ printf("\twm geometry $w +$winx+$winy\n");
+
+ /*
+ * Now that the whole window is in place, we need to wait for an "update"
+ * so we can tell the canvas what its virtual size should be.
+ *
+ * Unfortunately, this causes some ugly screen-flashing because the whole
+ * window is drawn, and then it is immediately resized. It seems
+ * unavoidable, though, since "frame" objects won't tell us their size
+ * until after an update, and "canvas" objects can't automatically pack
+ * around frames. Sigh.
+ */
+ printf("\tupdate idletasks\n");
+ printf("\t$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n");
+ printf("\t$w.config.canvas configure \\\n"
+ "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n"
+ "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n"
+ "\t\t\t [expr [winfo reqheight $w.config.f] + 1]\"\n\n");
+
+ /*
+ * If the whole canvas will fit in 3/4 of the screen height, do it;
+ * otherwise, resize to around 1/2 the screen and let us scroll.
+ */
+ printf("\tset winy [expr [winfo reqh $w] - [winfo reqh $w.config.canvas]]\n");
+ printf("\tset scry [expr [winfo screenh $w] / 2]\n");
+ printf("\tset maxy [expr [winfo screenh $w] * 3 / 4]\n");
+ printf("\tset canvtotal [expr [winfo reqh $w.config.f] + 2]\n");
+ printf("\tif [expr $winy + $canvtotal < $maxy] {\n"
+ "\t\t$w.config.canvas configure -height $canvtotal\n"
+ "\t} else {\n"
+ "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n"
+ "\t}\n");
+
+ /*
+ * Limit the min/max window size. Height can vary, but not width,
+ * because of the limitations of canvas and our laziness.
+ */
+ printf("\tupdate idletasks\n");
+ printf("\twm maxsize $w [winfo width $w] [winfo screenheight $w]\n");
+ printf("\twm minsize $w [winfo width $w] 100\n\n");
+ printf("\twm deiconify $w\n");
+
+ printf("}\n\n\n");
+
+ /*
+ * Now we generate the companion procedure for the menu we just
+ * generated. This procedure contains all of the code to
+ * disable/enable widgets based upon the settings of the other
+ * 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");
+ clear_globalflags(config);
+ for(cfg = config;cfg != NULL; cfg = cfg->next)
+ {
+ /*
+ * Skip items not for this menu, or ones having no conditions.
+ */
+ if (cfg->menu_number != menu_num ) continue;
+ if (cfg->tok != tok_define) continue;
+ /*
+ * Clear all of the booleans that are defined in this menu.
+ */
+ if( (cfg->flags & GLOBAL_WRITTEN) == 0
+ && (cfg->optionname != NULL) )
+ {
+ printf("\tglobal %s\n", cfg->optionname);
+ cfg->flags |= GLOBAL_WRITTEN;
+ printf("\tset %s 0\n", cfg->optionname);
+ }
+
+ }
+ for(cfg = config;cfg != NULL; cfg = cfg->next)
+ {
+ /*
+ * Skip items not for this menu, or ones having no conditions.
+ */
+ if (cfg->menu_number != menu_num ) continue;
+ if (cfg->tok == tok_menuoption) continue;
+ if (cfg->cond != NULL )
+ generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
+ else
+ {
+ /*
+ * If this token has no conditionals, check to see whether
+ * it is a tristate - if so, then generate the conditional
+ * to enable/disable the "y" button based upon the setting
+ * of the option it depends upon.
+ */
+ if(cfg->tok == tok_dep_tristate)
+ {
+ global(cfg->depend.str);
+ 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.str,cfg->depend.str,
+ menu_num, cfg->menu_line,
+ menu_num, cfg->menu_line);
+ }
+ }
+
+ }
+
+
+ printf("}\n\n\n");
+}
+
+/*
+ * This function goes through and counts up the number of items in
+ * each submenu. If there are too many options, we need to split it
+ * into submenus. This function just calculates how many submenus,
+ * and how many items go in each submenu.
+ */
+static void find_menu_size(struct kconfig *cfg,
+ int *menu_max,
+ int *menu_maxlines)
+
+{
+ struct kconfig * pnt;
+ int tot;
+
+ /*
+ * First count up the number of options in this menu.
+ */
+ tot = 0;
+ for(pnt = cfg->next; pnt; pnt = pnt->next)
+ {
+ if( pnt->tok == tok_menuoption) break;
+ switch (pnt->tok)
+ {
+ case tok_bool:
+ case tok_tristate:
+ case tok_dep_tristate:
+ case tok_int:
+ case tok_hex:
+ case tok_choose:
+ tot++;
+ break;
+ case tok_choice:
+ default:
+ break;
+ }
+ }
+
+ *menu_max = cfg->menu_number;
+ *menu_maxlines = tot;
+}
+
+/*
+ * This is the top level function for generating the tk script.
+ */
+void dump_tk_script(struct kconfig *scfg)
+{
+ int menu_num =0;
+ int menu_max =0;
+ int menu_min =0;
+ int menu_line = 0;
+ int menu_maxlines = 0;
+ struct kconfig * cfg;
+ struct kconfig * cfg1 = NULL;
+ char * menulabel;
+
+ /*
+ * Start by assigning menu numbers, and submenu numbers.
+ */
+ for(cfg = scfg;cfg != NULL; cfg = cfg->next)
+ {
+ switch (cfg->tok)
+ {
+ case tok_menuname:
+ break;
+ case tok_menuoption:
+ /*
+ * At the start of a new menu, calculate the number of items
+ * we will put into each submenu so we know when to bump the
+ * menu number. The submenus are really no different from a
+ * normal menu, but the top level buttons only access the first
+ * of the chain of menus, and the prev/next buttons are used
+ * access the submenus.
+ */
+ cfg->menu_number = ++menu_num;
+ find_menu_size(cfg, &menu_max, &menu_maxlines);
+ cfg->submenu_start = menu_num;
+ cfg->submenu_end = menu_max;
+ menu_line = 0;
+ break;
+ case tok_bool:
+ case tok_tristate:
+ case tok_dep_tristate:
+ case tok_int:
+ case tok_hex:
+ case tok_choose:
+ /*
+ * If we have overfilled the menu, then go to the next one.
+ */
+ if( menu_line == menu_maxlines )
+ {
+ menu_line = 0;
+ menu_num++;
+ }
+ cfg->menu_number = menu_num;
+ cfg->submenu_start = menu_min;
+ cfg->submenu_end = menu_max;
+ cfg->menu_line = menu_line++;
+ break;
+ case tok_define:
+ cfg->menu_number = -1;
+ case tok_choice:
+ default:
+ break;
+ };
+ }
+
+ /*
+ * Record this so we can set up the prev/next buttons correctly.
+ */
+ tot_menu_num = menu_num;
+
+ /*
+ * Now start generating the actual wish script that we will use.
+ * We need to keep track of the menu numbers of the min/max menu
+ * for a range of submenus so that we can correctly limit the
+ * prev and next buttons so that they don't go over into some other
+ * category.
+ */
+ for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+ {
+ switch (cfg->tok)
+ {
+ case tok_menuname:
+ printf("mainmenu_name \"%s\"\n", cfg->label);
+ break;
+ case tok_menuoption:
+ /*
+ * We are at the start of a new menu. If we had one that
+ * we were working on before, close it out, and then generate
+ * the script to start the new one.
+ */
+ if( cfg->menu_number > 1 )
+ {
+ end_proc(menu_num);
+ }
+ menulabel = cfg->label;
+ start_proc(cfg->label, cfg->menu_number, TRUE);
+ menu_num = cfg->menu_number;
+ menu_max = cfg->submenu_end;
+ menu_min = cfg->submenu_start;
+ break;
+ case tok_bool:
+ /*
+ * If we reached the point where we need to switch over
+ * to the next submenu, then bump the menu number and generate
+ * the code to close out the old menu and start the new one.
+ */
+ if( cfg->menu_number != menu_num )
+ {
+ end_proc(menu_num);
+ start_proc(menulabel, cfg->menu_number, FALSE);
+ menu_num = cfg->menu_number;
+ }
+ printf("\tbool $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number,
+ cfg->menu_line,
+ cfg->label,
+ cfg->optionname);
+ break;
+
+ case tok_choice:
+ 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);
+ break;
+ case tok_choose:
+ if( cfg->menu_number != menu_num )
+ {
+ end_proc(menu_num);
+ start_proc(menulabel, cfg->menu_number, FALSE);
+ menu_num = cfg->menu_number;
+ }
+ printf("\tglobal %s\n",cfg->optionname);
+ printf("\tminimenu $w.config.f %d %d \"%s\" %s %s\n",
+ cfg->menu_number,
+ cfg->menu_line,
+ cfg->label,
+ cfg->optionname,
+ /*
+ * We rely on the fact that the first tok_choice corresponding
+ * to the current tok_choose is cfg->next (compare parse() in
+ * tkparse.c). We need its name to pick out the right help
+ * text from Configure.help.
+ */
+ cfg->next->optionname);
+ printf("\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line);
+ cfg1 = cfg;
+ break;
+ case tok_tristate:
+ if( cfg->menu_number != menu_num )
+ {
+ end_proc(menu_num);
+ start_proc(menulabel, cfg->menu_number, FALSE);
+ menu_num = cfg->menu_number;
+ }
+ printf("\ttristate $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number,
+ cfg->menu_line,
+ cfg->label,
+ cfg->optionname);
+ break;
+ case tok_dep_tristate:
+ if( cfg->menu_number != menu_num )
+ {
+ end_proc(menu_num);
+ start_proc(menulabel, cfg->menu_number, FALSE);
+ menu_num = cfg->menu_number;
+ }
+ printf("\tdep_tristate $w.config.f %d %d \"%s\" %s %s\n",
+ cfg->menu_number,
+ cfg->menu_line,
+ cfg->label,
+ cfg->optionname,
+ cfg->depend.str);
+ break;
+ case tok_int:
+ if( cfg->menu_number != menu_num )
+ {
+ end_proc(menu_num);
+ start_proc(menulabel, cfg->menu_number, FALSE);
+ menu_num = cfg->menu_number;
+ }
+ printf("\tint $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number,
+ cfg->menu_line,
+ cfg->label,
+ cfg->optionname);
+ break;
+ case tok_hex:
+ if( cfg->menu_number != menu_num )
+ {
+ end_proc(menu_num);
+ start_proc(menulabel, cfg->menu_number, FALSE);
+ menu_num = cfg->menu_number;
+ }
+ printf("\thex $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number,
+ cfg->menu_line,
+ cfg->label,
+ cfg->optionname);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ /*
+ * Generate the code to close out the last menu.
+ */
+ end_proc(menu_num);
+
+#ifdef ERIC_DONT_DEF
+ /*
+ * Generate the code for configuring the sound driver. Right now this
+ * cannot be done from the X script, but we insert the menu anyways.
+ */
+ start_proc("Configure sound driver", ++menu_num, TRUE);
+#if 0
+ printf("\tdo_make -C drivers/sound config\n");
+ printf("\techo check_sound_config %d\n",menu_num);
+#endif
+ printf("\tlabel $w.config.f.m0 -bitmap error\n");
+ printf("\tmessage $w.config.f.m1 -width 400 -aspect 300 -text \"The sound drivers cannot as of yet be configured via the X-based interface\" -relief raised\n");
+ printf("\tpack $w.config.f.m0 $w.config.f.m1 -side top -pady 10 -expand on\n");
+ /*
+ * Close out the last menu.
+ */
+ end_proc(menu_num);
+#endif
+
+ /*
+ * The top level menu also needs an update function. When we exit 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.
+ */
+ printf("proc update_mainmenu {w} {\n");
+ for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+ {
+ switch (cfg->tok)
+ {
+ case tok_menuoption:
+ if (cfg->cond != NULL )
+ generate_if(cfg, cfg->cond, cfg->menu_number, cfg->menu_line);
+ break;
+ default:
+ break;
+ }
+ }
+
+ printf("}\n\n\n");
+
+#if 0
+ /*
+ * Generate some code to set the variables that are "defined".
+ */
+ for(cfg = config;cfg != NULL; cfg = cfg->next)
+ {
+ /*
+ * Skip items not for this menu, or ones having no conditions.
+ */
+ if( cfg->tok != tok_define) continue;
+ 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
+
+ /*
+ * Now generate code to load the default settings into the variables.
+ * Note that the script in tail.tk will attempt to load .config,
+ * which may override these settings, but that's OK.
+ */
+ for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+ {
+ switch (cfg->tok)
+ {
+ case tok_bool:
+ case tok_tristate:
+ case tok_dep_tristate:
+ case tok_choice:
+ printf("set %s 0\n", cfg->optionname);
+ break;
+ case tok_int:
+ case tok_hex:
+ printf("set %s %s\n", cfg->optionname, cfg->value);
+ break;
+ case tok_choose:
+ printf("set %s \"(not set)\"\n",cfg->optionname);
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Next generate a function that can be called from the main menu that will
+ * write all of the variables out. This also serves double duty - we can
+ * save configuration to a file using this.
+ */
+ printf("proc writeconfig {file1 file2} {\n");
+ printf("\tset cfg [open $file1 w]\n");
+ printf("\tset autocfg [open $file2 w]\n");
+ printf("\tset notmod 1\n");
+ printf("\tset notset 0\n");
+ clear_globalflags(config);
+ printf("\tputs $cfg \"#\"\n");
+ printf("\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
+ printf("\tputs $cfg \"#\"\n");
+
+ printf("\tputs $autocfg \"/*\"\n");
+ printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
+ printf("\tputs $autocfg \" */\"\n");
+ for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+ {
+ switch (cfg->tok)
+ {
+ case tok_int:
+ case tok_hex:
+ case tok_bool:
+ case tok_tristate:
+ case tok_dep_tristate:
+ case tok_define:
+ case tok_choose:
+ if(!(cfg->flags & GLOBAL_WRITTEN))
+ {
+ cfg->flags |= GLOBAL_WRITTEN;
+ printf("\tglobal %s\n", cfg->optionname);
+ }
+ /* fall through */
+ case tok_make:
+ case tok_comment:
+ if (cfg->cond != NULL )
+ generate_if_for_outfile(cfg, cfg->cond);
+ else
+ {
+ if(cfg->tok == tok_dep_tristate)
+ {
+ printf("\tif {$%s == 0 } then {\n"
+ "\t\twrite_tristate $cfg $autocfg %s $notset $notmod\n"
+ "\t} else {\n"
+ "\t\twrite_tristate $cfg $autocfg %s $%s $%s\n"
+ "\t}\n",
+ cfg->depend.str,
+ cfg->optionname,
+ cfg->optionname,
+ cfg->optionname,
+ cfg->depend.str);
+ }
+ else if(cfg->tok == tok_comment)
+ {
+ printf("\twrite_comment $cfg $autocfg \"%s\"\n", cfg->label);
+ }
+#if 0
+ else if(cfg->tok == tok_define)
+ {
+ printf("\twrite_define %s %s\n", cfg->optionname,
+ cfg->value);
+ }
+#endif
+ else if (cfg->tok == tok_choose )
+ {
+ for(cfg1 = cfg->next;
+ cfg1 != NULL && cfg1->tok == tok_choice;
+ cfg1 = cfg1->next)
+ {
+ printf("\tif { $%s == \"%s\" } then { write_tristate $cfg $autocfg %s 1 $notmod }\n",
+ cfg->optionname,
+ cfg1->label,
+ cfg1->optionname);
+ }
+ }
+ else if (cfg->tok == tok_int )
+ {
+ printf("\twrite_int $cfg $autocfg %s $%s $notmod\n",
+ cfg->optionname,
+ cfg->optionname);
+ }
+ else if (cfg->tok == tok_hex )
+ {
+ printf("\twrite_hex $cfg $autocfg %s $%s $notmod\n",
+ cfg->optionname,
+ cfg->optionname);
+ }
+ else if (cfg->tok == tok_make )
+ {
+ printf("\tdo_make {%s}\n",cfg->value);
+ }
+ else
+ {
+ printf("\twrite_tristate $cfg $autocfg %s $%s $notmod\n",
+ cfg->optionname,
+ cfg->optionname);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ printf("\tclose $cfg\n");
+ printf("\tclose $autocfg\n");
+ printf("}\n\n\n");
+
+ /*
+ * Finally write a simple function that updates the master choice
+ * variable depending upon what values were loaded from a .config
+ * file.
+ */
+ printf("proc clear_choices { } {\n");
+ for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+ {
+ if( cfg->tok != tok_choose ) continue;
+ for(cfg1 = cfg->next;
+ cfg1 != NULL && cfg1->tok == tok_choice;
+ cfg1 = cfg1->next)
+ {
+ printf("\tglobal %s; set %s 0\n",cfg1->optionname,cfg1->optionname);
+ }
+ }
+ printf("}\n\n\n");
+
+ printf("proc update_choices { } {\n");
+ for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+ {
+ if( cfg->tok != tok_choose ) continue;
+ printf("\tglobal %s\n", cfg->optionname);
+ for(cfg1 = cfg->next;
+ cfg1 != NULL && cfg1->tok == tok_choice;
+ 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("}\n\n\n");
+
+ printf("proc update_define { } {\n");
+ clear_globalflags(config);
+ for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+ {
+ if( cfg->tok != tok_define ) continue;
+ printf("\tglobal %s; set %s 0\n", cfg->optionname, cfg->optionname);
+ cfg->flags |= GLOBAL_WRITTEN;
+ }
+ for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+ {
+ if( cfg->tok != tok_define ) continue;
+ if (cfg->cond != NULL )
+ generate_if(cfg, cfg->cond, -1, 0);
+ else
+ {
+ printf("\tset %s %s\n",
+ cfg->optionname, cfg->value);
+ }
+ }
+ printf("}\n\n\n");
+ /*
+ * That's it. We are done. The output of this file will have header.tk
+ * prepended and tail.tk appended to create an executable wish script.
+ */
+}
diff --git a/scripts/tkparse.c b/scripts/tkparse.c
new file mode 100644
index 000000000..2a000217c
--- /dev/null
+++ b/scripts/tkparse.c
@@ -0,0 +1,751 @@
+/* parser config.in
+ *
+ * Version 1.0
+ * Eric Youngdale
+ * 10/95
+ *
+ * The general idea here is that we want to parse a config.in file and
+ * from this, we generate a wish script which gives us effectively the
+ * same functionality that the original config.in script provided.
+ *
+ * This task is split roughly into 3 parts. The first parse is the parse
+ * of the input file itself. The second part is where we analyze the
+ * #ifdef clauses, and attach a linked list of tokens to each of the
+ * menu items. In this way, each menu item has a complete list of
+ * dependencies that are used to enable/disable the options.
+ * The third part is to take the configuration database we have build,
+ * and build the actual wish script.
+ *
+ * This file contains the code to do the first parse of config.in.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "tkparse.h"
+
+struct kconfig * config = NULL;
+struct kconfig * clast = NULL;
+struct kconfig * koption = NULL;
+static int lineno = 0;
+static int menus_seen = 0;
+static char * current_file = NULL;
+static int do_source(char * filename);
+static char * get_string(char *pnt, char ** labl);
+static int choose_number = 0;
+
+
+/*
+ * Simple function just to skip over spaces and tabs in config.in.
+ */
+static char * skip_whitespace(char * pnt)
+{
+ while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
+ return pnt;
+}
+
+/*
+ * This function parses a conditional from a config.in (i.e. from an ifdef)
+ * and generates a linked list of tokens that describes the conditional.
+ */
+static struct condition * parse_if(char * pnt)
+{
+ char * opnt;
+ struct condition *list;
+ struct condition *last;
+ struct condition *cpnt;
+ char varname[64];
+ char * pnt1;
+
+ opnt = pnt;
+
+ /*
+ * We need to find the various tokens, and build the linked list.
+ */
+ pnt = skip_whitespace(pnt);
+ if( *pnt != '[' ) return NULL;
+ pnt++;
+ pnt = skip_whitespace(pnt);
+
+ list = last = NULL;
+ while(*pnt && *pnt != ']') {
+
+ pnt = skip_whitespace(pnt);
+ if(*pnt== '\0' || *pnt == ']') break;
+
+ /*
+ * Allocate memory for the token we are about to parse, and insert
+ * it in the linked list.
+ */
+ cpnt = (struct condition *) malloc(sizeof(struct condition));
+ memset(cpnt, 0, sizeof(struct condition));
+ if( last == NULL )
+ {
+ list = last = cpnt;
+ }
+ else
+ {
+ last->next = cpnt;
+ last = cpnt;
+ }
+
+ /*
+ * Determine what type of operation this token represents.
+ */
+ if( *pnt == '-' && pnt[1] == 'a' )
+ {
+ cpnt->op = op_and;
+ pnt += 2;
+ continue;
+ }
+
+ if( *pnt == '-' && pnt[1] == 'o' )
+ {
+ cpnt->op = op_or;
+ pnt += 2;
+ continue;
+ }
+
+ if( *pnt == '!' && pnt[1] == '=' )
+ {
+ cpnt->op = op_neq;
+ pnt += 2;
+ continue;
+ }
+
+ if( *pnt == '=')
+ {
+ cpnt->op = op_eq;
+ pnt += 1;
+ continue;
+ }
+
+ if( *pnt == '!')
+ {
+ cpnt->op = op_bang;
+ pnt += 1;
+ continue;
+ }
+
+ if( *pnt != '"' ) goto error; /* This cannot be right. */
+ pnt++;
+ if( *pnt == '`' )
+ {
+ cpnt->op = op_shellcmd;
+ pnt1 = varname;
+ pnt++;
+ while(*pnt && *pnt != '`') *pnt1++ = *pnt++;
+ *pnt1++ = '\0';
+ cpnt->variable.str = strdup(varname);
+ if( *pnt == '`' ) pnt++;
+ if( *pnt == '"' ) pnt++;
+ continue;
+ }
+ if( *pnt == '$' )
+ {
+ cpnt->op = op_variable;
+ pnt1 = varname;
+ pnt++;
+ while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
+ *pnt1++ = '\0';
+ cpnt->variable.str = strdup(varname);
+ if( *pnt == '"' ) pnt++;
+ continue;
+ }
+
+ cpnt->op = op_constant;
+ pnt1 = varname;
+ while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
+ *pnt1++ = '\0';
+ cpnt->variable.str = strdup(varname);
+ if( *pnt == '"' ) pnt++;
+ continue;
+ }
+
+ return list;
+
+ error:
+ if(current_file != NULL)
+ fprintf(stderr,
+ "Bad if clause at line %d(%s):%s\n", lineno, current_file, opnt);
+ else
+ fprintf(stderr,
+ "Bad if clause at line %d:%s\n", lineno, opnt);
+ return NULL;
+}
+
+/*
+ * This function looks for a quoted string, from the input buffer, and
+ * returns a pointer to a copy of this string. Any characters in
+ * the string that need to be "quoted" have a '\' character inserted
+ * in front - this way we can directly write these strings into
+ * wish scripts.
+ */
+static char * get_qstring(char *pnt, char ** labl)
+{
+ char quotechar;
+ char newlabel[1024];
+ char * pnt1;
+ char * pnt2;
+
+ while( *pnt && *pnt != '"' && *pnt != '\'') pnt++;
+ if (*pnt == '\0') return pnt;
+
+ quotechar = *pnt++;
+ pnt1 = newlabel;
+ while(*pnt && *pnt != quotechar && pnt[-1] != '\\')
+ {
+ /*
+ * Quote the character if we need to.
+ */
+ if( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']')
+ *pnt1++ = '\\';
+
+ *pnt1++ = *pnt++;
+ }
+ *pnt1++ = '\0';
+
+ pnt2 = (char *) malloc(strlen(newlabel) + 1);
+ strcpy(pnt2, newlabel);
+ *labl = pnt2;
+
+ /*
+ * Skip over last quote, and whitespace.
+ */
+ pnt++;
+ pnt = skip_whitespace(pnt);
+ return pnt;
+}
+
+static char * parse_choices(struct kconfig * choice_kcfg, char * pnt)
+{
+ struct kconfig * kcfg;
+ int index = 1;
+
+ /*
+ * Choices appear in pairs of strings. The parse is fairly trivial.
+ */
+ while(1)
+ {
+ pnt = skip_whitespace(pnt);
+ if(*pnt == '\0') break;
+
+ kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
+ memset(kcfg, 0, sizeof(struct kconfig));
+ kcfg->tok = tok_choice;
+ if( clast != NULL )
+ {
+ clast->next = kcfg;
+ clast = kcfg;
+ }
+ else
+ {
+ clast = config = kcfg;
+ }
+
+ pnt = get_string(pnt, &kcfg->label);
+ pnt = skip_whitespace(pnt);
+ pnt = get_string(pnt, &kcfg->optionname);
+ kcfg->choice_label = choice_kcfg;
+ kcfg->choice_value = index++;
+ if( strcmp(kcfg->label, choice_kcfg->value) == 0 )
+ choice_kcfg->choice_value = kcfg->choice_value;
+ }
+
+ return pnt;
+}
+
+
+/*
+ * This function grabs one text token from the input buffer
+ * and returns a pointer to a copy of just the identifier.
+ * This can be either a variable name (i.e. CONFIG_NET),
+ * or it could be the default value for the option.
+ */
+static char * get_string(char *pnt, char ** labl)
+{
+ char newlabel[1024];
+ char * pnt1;
+ char * pnt2;
+
+ if (*pnt == '\0') return pnt;
+
+ pnt1 = newlabel;
+ while(*pnt && *pnt != ' ' && *pnt != '\t')
+ {
+ *pnt1++ = *pnt++;
+ }
+ *pnt1++ = '\0';
+
+ pnt2 = (char *) malloc(strlen(newlabel) + 1);
+ strcpy(pnt2, newlabel);
+ *labl = pnt2;
+
+ if( *pnt ) pnt++;
+ return pnt;
+}
+
+
+/*
+ * Top level parse function. Input pointer is one complete line from config.in
+ * and the result is that we create a token that describes this line
+ * and insert it into our linked list.
+ */
+void parse(char * pnt) {
+ enum token tok;
+ struct kconfig * kcfg;
+ char tmpbuf[24],fake_if[1024];
+
+ /*
+ * Ignore comments and leading whitespace.
+ */
+
+ pnt = skip_whitespace(pnt);
+ while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
+ if(! *pnt ) return;
+ if( *pnt == '#' ) return;
+
+ /*
+ * Now categorize the next token.
+ */
+ tok = tok_unknown;
+ if (strncmp(pnt, "mainmenu_name", 13) == 0)
+ {
+ tok = tok_menuname;
+ pnt += 13;
+ }
+ else if (strncmp(pnt, "source", 6) == 0)
+ {
+ pnt += 7;
+ pnt = skip_whitespace(pnt);
+ do_source(pnt);
+ return;
+ }
+ else if (strncmp(pnt, "mainmenu_option", 15) == 0)
+ {
+ menus_seen++;
+ tok = tok_menuoption;
+ pnt += 15;
+ }
+ else if (strncmp(pnt, "$MAKE ", 6) == 0)
+ {
+ tok = tok_make;
+ }
+ else if (strncmp(pnt, "comment", 7) == 0)
+ {
+ tok = tok_comment;
+ pnt += 7;
+ }
+ else if (strncmp(pnt, "choice", 6) == 0)
+ {
+ tok = tok_choose;
+ pnt += 6;
+ }
+ else if (strncmp(pnt, "define_bool", 11) == 0)
+ {
+ tok = tok_define;
+ pnt += 11;
+ }
+ else if (strncmp(pnt, "bool", 4) == 0)
+ {
+ tok = tok_bool;
+ pnt += 4;
+ }
+ else if (strncmp(pnt, "tristate", 8) == 0)
+ {
+ tok = tok_tristate;
+ pnt += 8;
+ }
+ else if (strncmp(pnt, "dep_tristate", 12) == 0)
+ {
+ tok = tok_dep_tristate;
+ pnt += 12;
+ }
+ else if (strncmp(pnt, "int", 3) == 0)
+ {
+ tok = tok_int;
+ pnt += 3;
+ }
+ else if (strncmp(pnt, "hex", 3) == 0)
+ {
+ tok = tok_hex;
+ pnt += 3;
+ }
+ else if (strncmp(pnt, "if", 2) == 0)
+ {
+ tok = tok_if;
+ pnt += 2;
+ }
+ else if (strncmp(pnt, "else", 4) == 0)
+ {
+ tok = tok_else;
+ pnt += 4;
+ }
+ else if (strncmp(pnt, "fi", 2) == 0)
+ {
+ tok = tok_fi;
+ pnt += 2;
+ }
+ else if (strncmp(pnt, "endmenu", 7) == 0)
+ {
+ tok = tok_endmenu;
+ pnt += 7;
+ }
+
+ if( tok == tok_unknown)
+ {
+ if( clast != NULL && clast->tok == tok_if
+ && strcmp(pnt,"then") == 0) return;
+ if( current_file != NULL )
+ fprintf(stderr, "unknown command=%s(%s %d)\n", pnt,
+ current_file, lineno);
+ else
+ fprintf(stderr, "unknown command=%s(%d)\n", pnt,lineno);
+ return;
+ }
+
+ /*
+ * Allocate memory for this item, and attach it to the end of the linked
+ * list.
+ */
+ kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
+ memset(kcfg, 0, sizeof(struct kconfig));
+ kcfg->tok = tok;
+ if( clast != NULL )
+ {
+ clast->next = kcfg;
+ clast = kcfg;
+ }
+ else
+ {
+ clast = config = kcfg;
+ }
+
+ pnt = skip_whitespace(pnt);
+
+ /*
+ * Now parse the remaining parts of the option, and attach the results
+ * to the structure.
+ */
+ switch (tok)
+ {
+ case tok_choose:
+ pnt = get_qstring(pnt, &kcfg->label);
+ pnt = get_qstring(pnt, &kcfg->optionname);
+ pnt = get_string(pnt, &kcfg->value);
+ /*
+ * Now we need to break apart the individual options into their
+ * own configuration structures.
+ */
+ parse_choices(kcfg, kcfg->optionname);
+ free(kcfg->optionname);
+ sprintf(tmpbuf, "tmpvar_%d", choose_number++);
+ kcfg->optionname = strdup(tmpbuf);
+ break;
+ case tok_define:
+ pnt = get_string(pnt, &kcfg->optionname);
+ if(*pnt == 'y' || *pnt == 'Y' ) kcfg->value = "1";
+ if(*pnt == 'n' || *pnt == 'N' ) kcfg->value = "0";
+ if(*pnt == 'm' || *pnt == 'M' ) kcfg->value = "2";
+ break;
+ case tok_menuname:
+ pnt = get_qstring(pnt, &kcfg->label);
+ break;
+ case tok_bool:
+ case tok_tristate:
+ pnt = get_qstring(pnt, &kcfg->label);
+ pnt = get_string(pnt, &kcfg->optionname);
+ break;
+ case tok_int:
+ case tok_hex:
+ pnt = get_qstring(pnt, &kcfg->label);
+ pnt = get_string(pnt, &kcfg->optionname);
+ pnt = get_string(pnt, &kcfg->value);
+ break;
+ case tok_dep_tristate:
+ pnt = get_qstring(pnt, &kcfg->label);
+ pnt = get_string(pnt, &kcfg->optionname);
+ pnt = skip_whitespace(pnt);
+ if( *pnt == '$') pnt++;
+ pnt = get_string(pnt, &kcfg->depend.str);
+
+ /*
+ * Create a conditional for this object's dependency.
+ *
+ * We can't use "!= n" because this is internally converted to "!= 0"
+ * and if UMSDOS depends on MSDOS which depends on FAT, then when FAT
+ * is disabled MSDOS has 16 added to its value, making UMSDOS fully
+ * available. Whew.
+ *
+ * This is more of a hack than a fix. Nested "if" conditionals are
+ * probably affected too - that +/- 16 affects things in too many
+ * places. But this should do for now.
+ */
+ sprintf(fake_if,"[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then",
+ kcfg->depend.str,kcfg->depend.str);
+ kcfg->cond = parse_if(fake_if);
+ if(kcfg->cond == NULL )
+ {
+ exit(1);
+ }
+ break;
+ case tok_comment:
+ pnt = get_qstring(pnt, &kcfg->label);
+ if( koption != NULL )
+ {
+ pnt = get_qstring(pnt, &kcfg->label);
+ koption->label = kcfg->label;
+ koption = NULL;
+ }
+ break;
+ case tok_menuoption:
+ if( strncmp(pnt, "next_comment", 12) == 0)
+ {
+ koption = kcfg;
+ }
+ else
+ {
+ pnt = get_qstring(pnt, &kcfg->label);
+ }
+ break;
+ case tok_make:
+ kcfg->value=strdup(pnt);
+ break;
+ case tok_else:
+ case tok_fi:
+ case tok_endmenu:
+ break;
+ case tok_if:
+ /*
+ * Conditionals are different. For the first level parse, only
+ * tok_if and tok_dep_tristate items have a ->cond chain attached.
+ */
+ kcfg->cond = parse_if(pnt);
+ if(kcfg->cond == NULL )
+ {
+ exit(1);
+ }
+ break;
+ default:
+ exit(0);
+ }
+
+ return;
+}
+
+/*
+ * Simple function to dump to the screen what the condition chain looks like.
+ */
+void dump_if(struct condition * cond)
+{
+ printf(" ");
+ while(cond != NULL )
+ {
+ switch(cond->op){
+ case op_eq:
+ printf(" = ");
+ break;
+ case op_bang:
+ printf(" ! ");
+ break;
+ case op_neq:
+ printf(" != ");
+ break;
+ case op_and:
+ printf(" -a ");
+ break;
+ case op_lparen:
+ printf("(");
+ break;
+ case op_rparen:
+ printf(")");
+ break;
+ case op_variable:
+ printf("$%s", cond->variable.str);
+ break;
+ case op_constant:
+ printf("'%s'", cond->variable.str);
+ break;
+ default:
+ break;
+ }
+ cond = cond->next;
+ }
+
+ printf("\n");
+}
+
+static int do_source(char * filename)
+{
+ char buffer[1024];
+ int offset;
+ int old_lineno;
+ char * old_file;
+ char * pnt;
+ FILE * infile;
+
+ if( strcmp(filename, "-") == 0 )
+ infile = stdin;
+ else
+ infile = fopen(filename,"r");
+
+ /*
+ * If our cwd was in the scripts directory, we might have to go up one
+ * to find the sourced file.
+ */
+ if(!infile) {
+ strcpy (buffer, "../");
+ strcat (buffer, filename);
+ infile = fopen(buffer,"r");
+ }
+
+ if(!infile) {
+ fprintf(stderr,"Unable to open file %s\n", filename);
+ return 1;
+ }
+ old_lineno = lineno;
+ lineno = 0;
+ if( infile != stdin ) {
+ old_file = current_file;
+ current_file = filename;
+ }
+ offset = 0;
+ while(1)
+ {
+ fgets(&buffer[offset], sizeof(buffer) - offset, infile);
+ if(feof(infile)) break;
+
+ /*
+ * Strip the trailing return character.
+ */
+ pnt = buffer + strlen(buffer) - 1;
+ if( *pnt == '\n') *pnt-- = 0;
+ lineno++;
+ if( *pnt == '\\' )
+ {
+ offset = pnt - buffer;
+ }
+ else
+ {
+ parse(buffer);
+ offset = 0;
+ }
+ }
+ fclose(infile);
+ if( infile != stdin ) {
+ current_file = old_file;
+ }
+ lineno = old_lineno;
+ return 0;
+}
+
+int main(int argc, char * argv[])
+{
+#if 0
+ char buffer[1024];
+ char * pnt;
+ struct kconfig * cfg;
+ int i;
+#endif
+
+ /*
+ * Read stdin to get the top level script.
+ */
+ do_source("-");
+
+ if( menus_seen == 0 )
+ {
+ fprintf(stderr,"The config.in file for this platform does not support\n");
+ fprintf(stderr,"menus.\n");
+ exit(1);
+ }
+ /*
+ * Input file is now parsed. Next we need to go through and attach
+ * the correct conditions to each of the actual menu items and kill
+ * the if/else/endif tokens from the list. We also flag the menu items
+ * that have other things that depend upon its setting.
+ */
+ fix_conditionals(config);
+
+ /*
+ * Finally, we generate the wish script.
+ */
+ dump_tk_script(config);
+
+#if 0
+ /*
+ * Now dump what we have so far. This is only for debugging so that
+ * we can display what we think we have in the list.
+ */
+ for(cfg = config; cfg; cfg = cfg->next)
+ {
+
+ if(cfg->cond != NULL && cfg->tok != tok_if)
+ dump_if(cfg->cond);
+
+ switch(cfg->tok)
+ {
+ case tok_menuname:
+ printf("main_menuname ");
+ break;
+ case tok_bool:
+ printf("bool ");
+ break;
+ case tok_tristate:
+ printf("tristate ");
+ break;
+ case tok_dep_tristate:
+ printf("dep_tristate ");
+ break;
+ case tok_int:
+ printf("int ");
+ break;
+ case tok_hex:
+ printf("hex ");
+ break;
+ case tok_comment:
+ printf("comment ");
+ break;
+ case tok_menuoption:
+ printf("menuoption ");
+ break;
+ case tok_else:
+ printf("else");
+ break;
+ case tok_fi:
+ printf("fi");
+ break;
+ case tok_if:
+ printf("if");
+ break;
+ default:
+ }
+
+ switch(cfg->tok)
+ {
+ case tok_menuoption:
+ case tok_comment:
+ case tok_menuname:
+ printf("%s\n", cfg->label);
+ break;
+ case tok_bool:
+ case tok_tristate:
+ case tok_dep_tristate:
+ case tok_int:
+ case tok_hex:
+ printf("%s %s\n", cfg->label, cfg->optionname);
+ break;
+ case tok_if:
+ dump_if(cfg->cond);
+ break;
+ case tok_nop:
+ case tok_endmenu:
+ break;
+ default:
+ printf("\n");
+ }
+ }
+#endif
+
+ return 0;
+
+}
diff --git a/scripts/tkparse.h b/scripts/tkparse.h
new file mode 100644
index 000000000..911abdfbe
--- /dev/null
+++ b/scripts/tkparse.h
@@ -0,0 +1,82 @@
+
+enum token {
+ tok_menuname,
+ tok_menuoption,
+ tok_comment,
+ tok_bool,
+ tok_tristate,
+ tok_dep_tristate,
+ tok_nop,
+ tok_if,
+ tok_else,
+ tok_fi,
+ tok_int,
+ tok_hex,
+ tok_make,
+ tok_define,
+ tok_choose,
+ tok_choice,
+ tok_endmenu,
+ tok_unknown
+};
+
+enum operator {
+ op_eq,
+ op_neq,
+ op_and,
+ op_and1,
+ op_or,
+ op_bang,
+ op_lparen,
+ op_rparen,
+ op_variable,
+ op_kvariable,
+ op_shellcmd,
+ op_constant,
+ op_nuked
+};
+
+union var
+{
+ char * str;
+ struct kconfig * cfg;
+};
+
+struct condition
+{
+ struct condition * next;
+ enum operator op;
+ union var variable;
+};
+
+#define GLOBAL_WRITTEN 1
+#define CFG_DUP 2
+#define UNSAFE 4
+
+struct kconfig
+{
+ struct kconfig * next;
+ int flags;
+ enum token tok;
+ char menu_number;
+ char menu_line;
+ char submenu_start;
+ char submenu_end;
+ char * optionname;
+ char * label;
+ char * value;
+ int choice_value;
+ struct kconfig * choice_label;
+ union var depend;
+ struct condition * cond;
+};
+
+extern struct kconfig * config;
+extern struct kconfig * clast;
+extern struct kconfig * koption;
+
+/*
+ * Prototypes
+ */
+void fix_conditionals(struct kconfig * scfg); /* tkcond.c */
+void dump_tk_script(struct kconfig *scfg); /* tkgen.c */