summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 17:40:40 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 17:40:40 -0800
commit7a2deb32924142696b8174cdf9b38cd72a11fc96 (patch)
tree8ecc18f81fdb849254f39dc2e9fd77253319e1ec /scripts
Import changeset
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Configure584
-rw-r--r--scripts/MAKEDEV.ide49
-rw-r--r--scripts/Makefile45
-rw-r--r--scripts/Menuconfig1469
-rw-r--r--scripts/README.Menuconfig194
-rw-r--r--scripts/checkconfig.pl53
-rw-r--r--scripts/checkhelp.pl30
-rw-r--r--scripts/checkincludes.pl24
-rw-r--r--scripts/cramfs/GNUmakefile11
-rw-r--r--scripts/cramfs/mkcramfs.c624
-rw-r--r--scripts/docgen3
-rw-r--r--scripts/docproc.c103
-rw-r--r--scripts/gen-all-syms7
-rw-r--r--scripts/header.tk636
-rw-r--r--scripts/kernel-doc998
-rw-r--r--scripts/ksymoops/README8
-rw-r--r--scripts/lxdialog/BIG.FAT.WARNING4
-rw-r--r--scripts/lxdialog/Makefile46
-rw-r--r--scripts/lxdialog/checklist.c359
-rw-r--r--scripts/lxdialog/colors.h161
-rw-r--r--scripts/lxdialog/dialog.h184
-rw-r--r--scripts/lxdialog/inputbox.c240
-rw-r--r--scripts/lxdialog/lxdialog.c226
-rw-r--r--scripts/lxdialog/menubox.c437
-rw-r--r--scripts/lxdialog/msgbox.c85
-rw-r--r--scripts/lxdialog/textbox.c556
-rw-r--r--scripts/lxdialog/util.c359
-rw-r--r--scripts/lxdialog/yesno.c118
-rw-r--r--scripts/makelst21
-rw-r--r--scripts/mkdep.c562
-rwxr-xr-xscripts/patch-kernel94
-rw-r--r--scripts/pathdown.sh13
-rw-r--r--scripts/split-include.c226
-rw-r--r--scripts/tail.tk89
-rw-r--r--scripts/tkcond.c602
-rw-r--r--scripts/tkgen.c1521
-rw-r--r--scripts/tkparse.c822
-rw-r--r--scripts/tkparse.h127
-rw-r--r--scripts/ver_linux34
39 files changed, 11724 insertions, 0 deletions
diff --git a/scripts/Configure b/scripts/Configure
new file mode 100644
index 000000000000..f931c4cbfd04
--- /dev/null
+++ b/scripts/Configure
@@ -0,0 +1,584 @@
+#! /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.
+#
+# Raymond Chen was the original author of Configure.
+# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
+#
+# 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
+#
+# 090397 Axel Boldt (boldt@math.ucsb.edu) - avoid ? and + in regular
+# expressions for GNU expr since version 1.15 and up use \? and \+.
+#
+# 300397 Phil Blundell (pjb27@cam.ac.uk) - added support for min/max
+# arguments to "int", allow dep_tristate to take a list of dependencies
+# rather than just one.
+#
+# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help
+# texts.
+#
+# 102598 Michael Chastain (mec@shout.net) - put temporary files in
+# current directory, not in /tmp.
+#
+# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Improve the exit message (Jeff Ronne).
+
+#
+# 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[ ]*\$/c\\
+${var}:\\
+
+ /^#/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") | ${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 || 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 () {
+ define_tristate $1 $2
+}
+
+function define_tristate () {
+ 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_tristate "$2" "y"
+ break ;;
+ [nN] | [nN]o ) define_tristate "$2" "n"
+ break ;;
+ [mM] ) define_tristate "$2" "m"
+ break ;;
+ * ) help "$2"
+ ;;
+ esac
+ done
+ fi
+}
+
+#
+# dep_tristate processes a tristate argument that depends upon
+# another option or options. If any of the options we depend upon is a
+# module, then the only allowable options are M or N. If all are 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.
+#
+# dep_tristate question define default ...
+#
+function dep_tristate () {
+ old=$(eval echo "\${$2}")
+ def=${old:-'n'}
+ ques=$1
+ var=$2
+ need_module=0
+ shift 2
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ n)
+ define_tristate "$var" "n"
+ return
+ ;;
+ m)
+ need_module=1
+ ;;
+ esac
+ shift
+ done
+
+ if [ $need_module = 1 ]; then
+ if [ "$CONFIG_MODULES" = "y" ]; then
+ case "$def" in
+ "y" | "m") defprompt="M/n/?"
+ def="m"
+ ;;
+ "n") defprompt="N/m/?"
+ ;;
+ esac
+ while :; do
+ readln "$ques ($var) [$defprompt] " "$def" "$old"
+ case "$ans" in
+ [nN] | [nN]o ) define_tristate "$var" "n"
+ break ;;
+ [mM] ) define_tristate "$var" "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 "$var"
+ ;;
+ esac
+ done
+ fi
+ else
+ tristate "$ques" "$var"
+ fi
+}
+
+function dep_bool () {
+ ques=$1
+ var=$2
+ shift 2
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ m | n)
+ define_bool "$var" "n"
+ return
+ ;;
+ esac
+ shift
+ done
+
+ bool "$ques" "$var"
+}
+
+function dep_mbool () {
+ ques=$1
+ var=$2
+ shift 2
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ n)
+ define_bool "$var" "n"
+ return
+ ;;
+ esac
+ shift
+ done
+
+ bool "$ques" "$var"
+}
+
+#
+# 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 with optional limits
+#
+# int question define default [min max]
+#
+function int () {
+ old=$(eval echo "\${$2}")
+ def=${old:-$3}
+ if [ $# -gt 3 ]; then
+ min=$4
+ else
+ min=-10000000 # !!
+ fi
+ if [ $# -gt 4 ]; then
+ max=$5
+ else
+ max=10000000 # !!
+ fi
+ while :; do
+ readln "$1 ($2) [$def] " "$def" "$old"
+ if expr \( \( $ans + 0 \) \>= $min \) \& \( $ans \<= $max \) >/dev/null 2>&1 ; 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][0-9a-fA-F]*$' > /dev/null; then
+ define_hex "$2" "$ans"
+ break
+ else
+ help "$2"
+ fi
+ done
+}
+
+#
+# define_string sets the value of a string argument
+#
+# define_string define value
+#
+function define_string () {
+ echo "$1=\"$2\"" >>$CONFIG
+ echo "#define $1 \"$2\"" >>$CONFIG_H
+ eval "$1=\"$2\""
+}
+
+#
+# string processes a string argument
+#
+# string question define default
+#
+function string () {
+ old=$(eval echo "\${$2}")
+ def=${old:-$3}
+ while :; do
+ if [ "$old" = "?" ]; then
+ readln "$1 ($2) [$def] " "$def" ""
+ else
+ readln "$1 ($2) [$def] " "$def" "$old"
+ fi
+ if [ "$ans" = "?" ]; then
+ help "$2"
+ else
+ break
+ fi
+ done
+ define_string "$2" "$ans"
+}
+#
+# 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"* | */"$ans"* )
+ case "$name" in
+ "$ans" | */"$ans"/* | \
+ "$ans"/* | */"$ans" )
+ val="$2"
+ break # exact match
+ ;;
+ esac
+ 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
+echo "#define AUTOCONF_INCLUDED" >> $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/# \(CONFIG_[^ ]*\) is not.*/\1=n/' <$DEFAULTS >.config-is-not.$$
+ . .config-is-not.$$
+ rm .config-is-not.$$
+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 "*** End of Linux kernel configuration."
+echo "*** Check the top-level Makefile for additional configuration."
+if [ ! -f .hdepend -o "$CONFIG_MODVERSIONS" = "y" ] ; then
+ echo "*** Next, you must run 'make dep'."
+else
+ echo "*** Next, you may run 'make bzImage', 'make bzdisk', or 'make install'."
+fi
+echo
+
+exit 0
diff --git a/scripts/MAKEDEV.ide b/scripts/MAKEDEV.ide
new file mode 100644
index 000000000000..feecb99bb865
--- /dev/null
+++ b/scripts/MAKEDEV.ide
@@ -0,0 +1,49 @@
+#!/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
+makedevs hdi 56 0
+makedevs hdj 56 64
+makedevs hdk 57 0
+makedevs hdl 57 64
+makedevs hdm 88 0
+makedevs hdn 88 64
+makedevs hdo 89 0
+makedevs hdp 89 64
+makedevs hdq 90 0
+makedevs hdr 90 64
+makedevs hds 91 0
+makedevs hdt 91 64
+
+for tape in 0 1 2 3 4 5 6 7
+do
+ 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 000000000000..d6d231d73fa6
--- /dev/null
+++ b/scripts/Makefile
@@ -0,0 +1,45 @@
+HEADER=header.tk
+TAIL=tail.tk
+
+# Previous versions always remade kconfig.tk because they always depended
+# on soundscript. This runs fairly fast, and I can't find all the
+# Config.in files to depend on anyways. So I'll force it to remake.
+
+kconfig.tk: dummy
+
+kconfig.tk: ${TOPDIR}/Makefile ${TOPDIR}/arch/${ARCH}/config.in \
+ tkparse ${HEADER} ${TAIL}
+ @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
+ ./tkparse < ../arch/${ARCH}/config.in >> kconfig.tk
+ echo "set defaults \"arch/${ARCH}/defconfig\"" >> kconfig.tk
+ echo "set ARCH \"${ARCH}\"" >> 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
+
+tkcond.o: tkcond.c tkparse.h
+
+tkgen.o: tkgen.c tkparse.h
+
+tkparse.o tkcond.o tkgen.o:
+ $(HOSTCC) $(HOSTCFLAGS) -c -o $@ $(@:.o=.c)
+
+docproc.o: docproc.c
+ $(HOSTCC) $(HOSTCFLAGS) -c -o $@ $(@:.o=.c)
+
+docproc: docproc.o
+ ${HOSTCC} -o docproc docproc.o
+
+clean:
+ rm -f *~ kconfig.tk *.o tkparse mkdep split-include docproc
+
+include $(TOPDIR)/Rules.make
diff --git a/scripts/Menuconfig b/scripts/Menuconfig
new file mode 100644
index 000000000000..5a76152e734c
--- /dev/null
+++ b/scripts/Menuconfig
@@ -0,0 +1,1469 @@
+#! /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.
+#
+# William Roadcap was the original author of Menuconfig.
+# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
+#
+# 070497 Bernhard Kaindl (bkaindl@netway.at) - get default values for
+# new bool, tristate and dep_tristate parameters from the defconfig file.
+# new configuration parameters are marked with '(NEW)' as in make config.
+#
+# 180697 Bernhard Kaindl (bkaindl@netway.at) - added the needed support
+# for string options. They are handled like the int and hex options.
+#
+# 081297 Pavel Machek (pavel@atrey.karlin.mff.cuni.cz) - better error
+# handling
+#
+# 131197 Michael Chastain (mec@shout.net) - output all lines for a
+# choice list, not just the selected one. This makes the output
+# the same as Configure output, which is important for smart config
+# dependencies.
+#
+# 101297 Michael Chastain (mec@shout.net) - remove sound driver cruft.
+#
+# 221297 Michael Chastain (mec@shout.net) - make define_bool actually
+# define its arguments so that later tests on them work right.
+#
+# 160198 Michael Chastain (mec@shout.net) - fix bug with 'c' command
+# (complement existing value) when used on virgin uninitialized variables.
+#
+# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help
+# texts.
+#
+# 12 Dec 1998, Michael Elizabeth Chastain (mec@shout.net)
+# Remove a /tmp security hole in get_def (also makes it faster).
+# Give uninitialized variables canonical values rather than null value.
+# Change a lot of places to call set_x_info uniformly.
+# Take out message about preparing version (old sound driver cruft).
+#
+# 13 Dec 1998, Riley H Williams <rhw@memalpha.cx>
+# When an error occurs, actually display the error message as well as
+# our comments thereon.
+#
+# 31 Dec 1998, Michael Elizabeth Chastain (mec@shout.net)
+# Fix mod_bool to honor $CONFIG_MODULES.
+# Fix dep_tristate to call define_bool when dependency is "n".
+#
+# 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
+# Blow away lxdialog.scrltmp on entry to activate_menu. This protects
+# against people who use commands like ' ' to select menus.
+#
+# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Improve the exit message (Jeff Ronne).
+#
+# 06 July 1999, Andrzej M. Krzysztofowicz, <ankry@mif.pg.gda.pl>
+# - Support for multiple conditions in dep_tristate().
+# - Implemented new functions: define_tristate(), define_int(), define_hex(),
+# define_string(), dep_bool().
+#
+
+
+#
+# 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
+
+
+
+# Given a configuration variable, set the global variable $x to its value,
+# and the global variable $info to the string " (NEW)" if this is a new
+# variable.
+#
+# This function looks for: (1) the current value, or (2) the default value
+# from the arch-dependent defconfig file, or (3) a default passed by the caller.
+
+function set_x_info () {
+ eval x=\$$1
+ if [ -z "$x" ]; then
+ eval `sed -n -e 's/# \(.*\) is not set.*/\1=n/' -e "/^$1=/p" arch/$ARCH/defconfig`
+ eval x=\${$1:-"$2"}
+ eval $1=$x
+ eval INFO_$1="' (NEW)'"
+ fi
+ eval info="\$INFO_$1"
+}
+
+#
+# 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
+}
+
+#
+# Define a boolean to a specific value.
+#
+function define_bool () {
+ eval $1=$2
+}
+
+function define_tristate () {
+ eval $1=$2
+}
+
+function define_hex () {
+ eval $1=$2
+}
+
+function define_int () {
+ eval $1=$2
+}
+
+function define_string () {
+ eval $1="$2"
+}
+
+#
+# Create a boolean (Yes/No) function for our current menu
+# which calls our local bool function.
+#
+function bool () {
+ set_x_info "$2" "n"
+
+ case $x in
+ y|m) flag="*" ;;
+ n) flag=" " ;;
+ esac
+
+ echo -ne "'$2' '[$flag] $1$info' " >>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
+ set_x_info "$2" "n"
+
+ case $x in
+ y) flag="*" ;;
+ m) flag="M" ;;
+ *) flag=" " ;;
+ esac
+
+ echo -ne "'$2' '<$flag> $1$info' " >>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 () {
+ ques="$1"
+ var="$2"
+ dep=y
+ shift 2
+ while [ $# -gt 0 ]; do
+ if [ "$1" = y ]; then
+ shift
+ elif [ "$1" = m ]; then
+ dep=m
+ shift
+ else
+ dep=n
+ shift $#
+ fi
+ done
+ if [ "$dep" = y ]; then
+ tristate "$ques" "$var"
+ elif [ "$dep" = m ]; then
+ mod_bool "$ques" "$var"
+ else
+ define_tristate "$var" n
+ fi
+}
+
+#
+# Same as above, but now only Y and N are allowed as dependency
+# (i.e. third and next arguments).
+#
+function dep_bool () {
+ ques="$1"
+ var="$2"
+ dep=y
+ shift 2
+ while [ $# -gt 0 ]; do
+ if [ "$1" = y ]; then
+ shift
+ else
+ dep=n
+ shift $#
+ fi
+ done
+ if [ "$dep" = y ]; then
+ bool "$ques" "$var"
+ else
+ define_bool "$var" n
+ fi
+}
+
+function dep_mbool () {
+ ques="$1"
+ var="$2"
+ dep=y
+ shift 2
+ while [ $# -gt 0 ]; do
+ if [ "$1" = y -o "$1" = m ]; then
+ shift
+ else
+ dep=n
+ shift $#
+ fi
+ done
+ if [ "$dep" = y ]; then
+ bool "$ques" "$var"
+ else
+ define_bool "$var" n
+ fi
+}
+
+#
+# Add a menu item which will call our local int function.
+#
+function int () {
+ set_x_info "$2" "$3"
+
+ echo -ne "'$2' '($x) $1$info' " >>MCmenu
+
+ echo -e "function $2 () { l_int '$1' '$2' '$3' '$x' ;}" >>MCradiolists
+}
+
+#
+# Add a menu item which will call our local hex function.
+#
+function hex () {
+ set_x_info "$2" "$3"
+ x=${x##*[x,X]}
+
+ echo -ne "'$2' '($x) $1$info' " >>MCmenu
+
+ echo -e "function $2 () { l_hex '$1' '$2' '$3' '$x' ;}" >>MCradiolists
+}
+
+#
+# Add a menu item which will call our local string function.
+#
+function string () {
+ set_x_info "$2" "$3"
+
+ echo -ne "'$2' ' $1: \"$x\"$info' " >>MCmenu
+
+ echo -e "function $2 () { l_string '$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[ ]*\$/c\\
+${var}:\\
+
+ /^#/b
+ /^[^ ]/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 -f 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
+}
+
+#
+# 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 ;;
+ *) eval $1=y ;;
+ esac ;;
+ *) eval $1=n ;;
+ esac
+ else
+ echo -ne "\007"
+ fi
+}
+
+#
+# Same as bool() except options are (Module/No)
+#
+function mod_bool () {
+ if [ "$CONFIG_MODULES" != "y" ]; then
+ define_bool "$2" "n"
+ else
+ set_x_info "$2" "n"
+
+ case $x in
+ y|m) flag='M' ;;
+ *) flag=' ' ;;
+ esac
+
+ echo -ne "'$2' '<$flag> $1$info' " >>MCmenu
+
+ echo -e "function $2 () { l_mod_bool '$2' \"\$1\" ;}" >>MCradiolists
+ fi
+}
+
+#
+# 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 ;;
+ *) 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 ;;
+ *) 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}"
+
+ # Semantics of + and ? in GNU expr changed, so
+ # we avoid them:
+ if expr "$answer" : '0$' '|' "$answer" : '[1-9][0-9]*$' '|' "$answer" : '-[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][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
+}
+
+#
+# Create a dialog for entering a string into a kernel option.
+#
+function l_string () {
+ while true
+ do
+ if $DIALOG --title "$1" \
+ --backtitle "$backtitle" \
+ --inputbox "$inputbox_instructions_string" \
+ 10 75 "$4" 2>MCdialog.out
+ then
+ answer="`cat MCdialog.out`"
+ answer="${answer:-$3}"
+
+ #
+ # Someone may add a nice check for the entered
+ # string here...
+ #
+ eval $2=\"$answer\"
+
+ break
+ fi
+
+ help "$2" "$1"
+ done
+}
+
+
+#
+# Handle a one-of-many choice list.
+#
+function l_choice () {
+ #
+ # Need to remember params cause they're gonna get reset.
+ #
+ title="$1"
+ choices="$2"
+ current="$3"
+ chosen=
+
+ #
+ # Scan current value of choices and set radiolist switches.
+ #
+ list=
+ set -- $choices
+ firstchoice=$2
+ while [ -n "$2" ]
+ do
+ case "$1" in
+ "$current"*) if [ -z "$chosen" ]; then
+ list="$list $2 $1 ON "
+ chosen=1
+ else
+ list="$list $2 $1 OFF "
+ fi ;;
+ *) 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 based 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
+}
+
+#
+# Call awk, and watch for error codes, etc.
+#
+function callawk () {
+awk "$1" || echo "Awk died with error code $?. Giving up." || exit 1
+}
+
+#
+# A faster awk based recursive parser. (I hope)
+#
+function parser1 () {
+callawk '
+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
+
+ newmenu = sprintf("MCmenu%d", menu_no);
+ printf( "function MCmenu%s () {\n"\
+ "default=$1\n"\
+ "menu_name %s\n",\
+ menu_no, $0) >newmenu
+
+ parser(ifile, newmenu)
+ }
+ else if ($0 ~ /^#|\$MAKE|mainmenu_name/) {
+ printf("") >>menu
+ }
+ else if ($1 ~ "endmenu") {
+ printf("}\n") >>menu
+ return
+ }
+ else if ($1 == "source") {
+ parser($2,menu)
+ }
+ else {
+ print >>menu
+ }
+ }
+}'
+}
+
+#
+# Secondary parser for single menu mode.
+#
+function parser2 () {
+callawk '
+BEGIN {
+ parser("'$CONFIG_IN'","MCmenu0")
+}
+
+function parser(ifile,menu) {
+
+ while (getline <ifile) {
+ if ($0 ~ /^#|$MAKE|mainmenu_name/) {
+ printf("") >>menu
+ }
+ else if ($1 ~ /mainmenu_option|endmenu/) {
+ printf("") >>menu
+ }
+ else if ($1 == "source") {
+ 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
+ echo -n "."
+ 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 () {
+ rm -f lxdialog.scrltmp
+ while true
+ do
+ comment_ctr=0 #So comment lines get unique tags
+
+ $1 "$default" 2> MCerror #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. Here is the error
+report:
+
+EOM
+ sed 's/^/ Q> /' MCerror
+ cat <<EOM
+
+Please report this to the maintainer <mec@shout.net>. You may also
+send a problem report to <linux-kernel@vger.kernel.org>.
+
+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
+ rm -f MCerror
+
+ . ./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 maintainer <mec@shout.net> or post a message to
+<linux-kernel@vger.kernel.org> 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 () {
+ echo
+ echo -n "Saving your kernel configuration."
+
+ #
+ # Now, let's redefine the configuration functions for final
+ # output to the config files.
+ #
+ # Nested function definitions, YIPEE!
+ #
+ function bool () {
+ set_x_info "$2" "n"
+ eval define_bool "$2" "$x"
+ }
+
+ function tristate () {
+ set_x_info "$2" "n"
+ eval define_tristate "$2" "$x"
+ }
+
+ function dep_tristate () {
+ set_x_info "$2" "n"
+ var="$2"
+ shift 2
+ while [ $# -gt 0 ]; do
+ if [ "$1" = y ]; then
+ shift
+ elif [ "$1" = m -a "$x" != n ]; then
+ x=m; shift
+ else
+ x=n; shift $#
+ fi
+ done
+ define_tristate "$var" "$x"
+ }
+
+ function dep_bool () {
+ set_x_info "$2" "n"
+ var="$2"
+ shift 2
+ while [ $# -gt 0 ]; do
+ if [ "$1" = y ]; then
+ shift
+ else
+ x=n; shift $#
+ fi
+ done
+ define_bool "$var" "$x"
+ }
+
+ function dep_mbool () {
+ set_x_info "$2" "n"
+ var="$2"
+ shift 2
+ while [ $# -gt 0 ]; do
+ if [ "$1" = y -o "$1" = m ]; then
+ shift
+ else
+ x=n; shift $#
+ fi
+ done
+ define_bool "$var" "$x"
+ }
+
+ function int () {
+ set_x_info "$2" "$3"
+ echo "$2=$x" >>$CONFIG
+ echo "#define $2 ($x)" >>$CONFIG_H
+ }
+
+ function hex () {
+ set_x_info "$2" "$3"
+ echo "$2=$x" >>$CONFIG
+ echo "#define $2 0x${x##*[x,X]}" >>$CONFIG_H
+ }
+
+ function string () {
+ set_x_info "$2" "$3"
+ echo "$2=\"$x\"" >>$CONFIG
+ echo "#define $2 \"$x\"" >>$CONFIG_H
+ }
+
+ function define_hex () {
+ eval $1="$2"
+ echo "$1=$2" >>$CONFIG
+ echo "#define $1 0x${2##*[x,X]}" >>$CONFIG_H
+ }
+
+ function define_int () {
+ eval $1="$2"
+ echo "$1=$2" >>$CONFIG
+ echo "#define $1 ($2)" >>$CONFIG_H
+ }
+
+ function define_string () {
+ eval $1="$2"
+ echo "$1=\"$2\"" >>$CONFIG
+ echo "#define $1 \"$2\"" >>$CONFIG_H
+ }
+
+ function define_bool () {
+ define_tristate "$1" "$2"
+ }
+
+ function define_tristate () {
+ eval $1="$2"
+
+ case "$2" in
+ 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=
+ chosen=
+
+ 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}
+
+ #
+ # Output all choices (to be compatible with other configs).
+ #
+ set -- $choices
+ while [ -n "$2" ]
+ do
+ case "$1" in
+ "$current"*) if [ -z "$chosen" ]; then
+ define_bool "$2" "y"
+ chosen=1
+ else
+ define_bool "$2" "n"
+ fi ;;
+ *) define_bool "$2" "n" ;;
+ esac
+ shift ; shift
+ done
+ }
+
+ 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
+ }
+
+ echo -n "."
+
+ 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
+ echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H
+
+ echo -n "."
+ if . $CONFIG_IN >>.menuconfig.log 2>&1
+ then
+ if [ "$DEF_CONFIG" = ".config" ]
+ then
+ 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. \
+Fractions will not be accepted. \
+Use the <TAB> key to move from the input field to the buttons below it."
+
+inputbox_instructions_hex="\
+Please enter a hexadecimal value. \
+Use the <TAB> key to move from the input field to the buttons below it."
+
+inputbox_instructions_string="\
+Please enter a string value. \
+Use the <TAB> key to move from the input field to the buttons below it."
+
+DIALOG="./scripts/lxdialog/lxdialog"
+
+kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
+
+backtitle="Linux Kernel v$kernel_version Configuration"
+
+trap "cleanup ; 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 "Using defaults found in" $DEFAULTS
+ load_config_file $DEFAULTS
+else
+ echo "No defaults found"
+fi
+
+
+# Fresh new log.
+>.menuconfig.log
+
+# Load the functions used by the config.in files.
+echo -n "Preparing scripts: functions"
+load_functions
+
+if [ ! -e $CONFIG_IN ]
+then
+ echo "Your main config.in file ($CONFIG_IN) does not exist"
+ exit 1
+fi
+
+if [ ! -x $DIALOG ]
+then
+ echo "Your lxdialog utility does not exist"
+ exit 1
+fi
+
+#
+# Read config.in files and parse them into one shell function per menu.
+#
+echo -n ", parsing"
+parse_config_files $CONFIG_IN
+
+echo "done."
+#
+# 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
+ echo
+ echo
+ echo "*** End of Linux kernel configuration."
+ echo "*** Check the top-level Makefile for additional configuration."
+ if [ ! -f .hdepend -o "$CONFIG_MODVERSIONS" = "y" ] ; then
+ echo "*** Next, you must run 'make dep'."
+ else
+ echo "*** Next, you may run 'make bzImage', 'make bzdisk', or 'make install'."
+ fi
+ echo
+else
+ echo
+ echo
+ echo Your kernel configuration changes were NOT saved.
+ echo
+fi
+
+# Remove log if empty.
+if [ ! -s .menuconfig.log ] ; then
+ rm -f .menuconfig.log
+fi
+
+exit 0
diff --git a/scripts/README.Menuconfig b/scripts/README.Menuconfig
new file mode 100644
index 000000000000..5c28589964e1
--- /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.
+
+William Roadcap was the original author of Menuconfig.
+Michael Elizabeth Chastain <mec@shout.net> is the current maintainer.
+
+<END OF FILE>
diff --git a/scripts/checkconfig.pl b/scripts/checkconfig.pl
new file mode 100644
index 000000000000..fc352e436372
--- /dev/null
+++ b/scripts/checkconfig.pl
@@ -0,0 +1,53 @@
+#! /usr/bin/perl
+#
+# checkconfig: find uses of CONFIG_* names without matching definitions.
+# Copyright abandoned, 1998, Michael Elizabeth Chastain <mailto:mec@shout.net>.
+
+use integer;
+
+$| = 1;
+
+foreach $file (@ARGV)
+{
+ # Open this file.
+ open(FILE, $file) || die "Can't open $file: $!\n";
+
+ # Initialize variables.
+ my $fInComment = 0;
+ my $fUseConfig = 0;
+ my $iLinuxConfig = 0;
+ my %configList = ();
+
+ LINE: while ( <FILE> )
+ {
+ # Strip comments.
+ $fInComment && (s+^.*?\*/+ +o ? ($fInComment = 0) : next);
+ m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1)));
+
+ # Pick up definitions.
+ if ( m/^\s*#/o )
+ {
+ $iLinuxConfig = $. if m/^\s*#\s*include\s*<linux\/config\.h>/o;
+ $configList{uc $1} = 1 if m/^\s*#\s*include\s*<config\/(\S*)\.h>/o;
+ $configList{$1} = 1 if m/^\s*#\s*define\s+CONFIG_(\w*)/o;
+ $configList{$1} = 1 if m/^\s*#\s*undef\s+CONFIG_(\w*)/o;
+ }
+
+ # Look for usages.
+ next unless m/CONFIG_/o;
+ WORD: while ( m/\bCONFIG_(\w+)/og )
+ {
+ $fUseConfig = 1;
+ last LINE if $iLinuxConfig;
+ next WORD if exists $configList{$1};
+ print "$file: $.: need CONFIG_$1.\n";
+ $configList{$1} = 0;
+ }
+ }
+
+ # Report superfluous includes.
+ if ( $iLinuxConfig && ! $fUseConfig )
+ { print "$file: $iLinuxConfig: <linux/config.h> not needed.\n"; }
+
+ close(FILE);
+}
diff --git a/scripts/checkhelp.pl b/scripts/checkhelp.pl
new file mode 100644
index 000000000000..e765233259e2
--- /dev/null
+++ b/scripts/checkhelp.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+# checkhelp.pl - finds configuration options that have no
+# corresponding section in the help file
+#
+# made by Meelis Roos (mroos@tartu.cyber.ee)
+
+# read the help file
+@options=split /\n/, `grep '^CONFIG' Documentation/Configure.help`;
+die "Can't read Documentation/Configure.help\n" if $#options == -1;
+
+#read all the files
+foreach $file (@ARGV)
+{
+ open (FILE, $file) || die "Can't open $file: $!\n";
+ while (<FILE>) {
+ # repeat until no CONFIG_* are left
+ while (/^\s*(bool|tristate|dep_tristate|string|int|hex).*' *(.*)'.*(CONFIG_\w*)/) {
+ $what=$3;
+ $name=$2;
+ s/$3//;
+ @found = grep (/$what$/, @options);
+ if ($#found == -1) {
+ next if $nohelp{$what};
+ print "$name\n$what\n No help for $what\n\n";
+ $nohelp{$what}=1;
+ }
+ }
+ }
+ close (FILE);
+}
diff --git a/scripts/checkincludes.pl b/scripts/checkincludes.pl
new file mode 100644
index 000000000000..8e6b716c191c
--- /dev/null
+++ b/scripts/checkincludes.pl
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+#
+# checkincludes: Find files included more than once in (other) files.
+# Copyright abandoned, 2000, Niels Kristian Bech Jensen <nkbj@image.dk>.
+
+foreach $file (@ARGV) {
+ open(FILE, $file) or die "Cannot open $file: $!.\n";
+
+ my %includedfiles = ();
+
+ while (<FILE>) {
+ if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) {
+ ++$includedfiles{$1};
+ }
+ }
+
+ foreach $filename (keys %includedfiles) {
+ if ($includedfiles{$filename} > 1) {
+ print "$file: $filename is included more than once.\n";
+ }
+ }
+
+ close(FILE);
+}
diff --git a/scripts/cramfs/GNUmakefile b/scripts/cramfs/GNUmakefile
new file mode 100644
index 000000000000..ea972e38fa47
--- /dev/null
+++ b/scripts/cramfs/GNUmakefile
@@ -0,0 +1,11 @@
+CFLAGS = -Wall -O2
+CPPFLAGS = -I../../fs/cramfs
+LDLIBS = -lz
+PROGS = mkcramfs
+
+all: $(PROGS)
+
+distclean clean:
+ rm -f $(PROGS)
+
+.PHONY: all clean
diff --git a/scripts/cramfs/mkcramfs.c b/scripts/cramfs/mkcramfs.c
new file mode 100644
index 000000000000..878e12b32427
--- /dev/null
+++ b/scripts/cramfs/mkcramfs.c
@@ -0,0 +1,624 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+/* zlib required.. */
+#include <zlib.h>
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#include "cramfs.h"
+
+static const char *progname = "mkcramfs";
+
+/* N.B. If you change the disk format of cramfs, please update fs/cramfs/README. */
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: '%s dirname outfile'\n"
+ " where <dirname> is the root of the\n"
+ " filesystem to be compressed.\n", progname);
+ exit(1);
+}
+
+/*
+ * If DO_HOLES is defined, then mkcramfs can create explicit holes in the
+ * data, which saves 26 bytes per hole (which is a lot smaller a saving than
+ * most filesystems).
+ *
+ * Note that kernels up to at least 2.3.39 don't support cramfs holes, which
+ * is why this defaults to undefined at the moment.
+ */
+/* #define DO_HOLES 1 */
+
+#define PAGE_CACHE_SIZE (4096)
+/* The kernel assumes PAGE_CACHE_SIZE as block size. */
+static unsigned int blksize = PAGE_CACHE_SIZE;
+
+static int warn_dev, warn_gid, warn_namelen, warn_size, warn_uid;
+
+#ifndef MIN
+# define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+/* In-core version of inode / directory entry. */
+struct entry {
+ /* stats */
+ char *name;
+ unsigned int mode, size, uid, gid;
+
+ /* FS data */
+ void *uncompressed;
+ /* points to other identical file */
+ struct entry *same;
+ unsigned int offset; /* pointer to compressed data in archive */
+ unsigned int dir_offset; /* Where in the archive is the directory entry? */
+
+ /* organization */
+ struct entry *child; /* null for non-directories and empty directories */
+ struct entry *next;
+};
+
+/*
+ * Width of various bitfields in struct cramfs_inode.
+ * Used only to generate warnings.
+ */
+#define SIZE_WIDTH 24
+#define UID_WIDTH 16
+#define GID_WIDTH 8
+#define OFFSET_WIDTH 26
+
+/*
+ * The longest file name component to allow for in the input directory tree.
+ * Ext2fs (and many others) allow up to 255 bytes. A couple of filesystems
+ * allow longer (e.g. smbfs 1024), but there isn't much use in supporting
+ * >255-byte names in the input directory tree given that such names get
+ * truncated to 255 bytes when written to cramfs.
+ */
+#define MAX_INPUT_NAMELEN 255
+
+static int find_identical_file(struct entry *orig,struct entry *newfile)
+{
+ if(orig==newfile) return 1;
+ if(!orig) return 0;
+ if(orig->size==newfile->size && orig->uncompressed && !memcmp(orig->uncompressed,newfile->uncompressed,orig->size)) {
+ newfile->same=orig;
+ return 1;
+ }
+ return find_identical_file(orig->child,newfile) ||
+ find_identical_file(orig->next,newfile);
+}
+
+static void eliminate_doubles(struct entry *root,struct entry *orig) {
+ if(orig) {
+ if(orig->size && orig->uncompressed)
+ find_identical_file(root,orig);
+ eliminate_doubles(root,orig->child);
+ eliminate_doubles(root,orig->next);
+ }
+}
+
+static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub)
+{
+ DIR *dir;
+ int count = 0, totalsize = 0;
+ struct dirent *dirent;
+ char *path, *endpath;
+ size_t len = strlen(name);
+
+ dir = opendir(name);
+ if (!dir) {
+ perror(name);
+ exit(2);
+ }
+
+ /* Set up the path. */
+ /* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */
+ path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1);
+ if (!path) {
+ perror(NULL);
+ exit(1);
+ }
+ memcpy(path, name, len);
+ endpath = path + len;
+ *endpath = '/';
+ endpath++;
+
+ while ((dirent = readdir(dir)) != NULL) {
+ struct entry *entry;
+ struct stat st;
+ int size;
+ size_t namelen;
+
+ /* Ignore "." and ".." - we won't be adding them to the archive */
+ if (dirent->d_name[0] == '.') {
+ if (dirent->d_name[1] == '\0')
+ continue;
+ if (dirent->d_name[1] == '.') {
+ if (dirent->d_name[2] == '\0')
+ continue;
+ }
+ }
+ namelen = strlen(dirent->d_name);
+ if (namelen > MAX_INPUT_NAMELEN) {
+ fprintf(stderr,
+ "Very long (%u bytes) filename `%s' found.\n"
+ " Please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile. Exiting.\n",
+ namelen, dirent->d_name);
+ exit(1);
+ }
+ memcpy(endpath, dirent->d_name, namelen + 1);
+
+ if (lstat(path, &st) < 0) {
+ perror(endpath);
+ continue;
+ }
+ entry = calloc(1, sizeof(struct entry));
+ if (!entry) {
+ perror(NULL);
+ exit(5);
+ }
+ entry->name = strdup(dirent->d_name);
+ if (!entry->name) {
+ perror(NULL);
+ exit(1);
+ }
+ if (namelen > 255) {
+ /* Can't happen when reading from ext2fs. */
+
+ /* TODO: we ought to avoid chopping in half
+ multi-byte UTF8 characters. */
+ entry->name[namelen = 255] = '\0';
+ warn_namelen = 1;
+ }
+ entry->mode = st.st_mode;
+ entry->size = st.st_size;
+ entry->uid = st.st_uid;
+ if (entry->uid >= 1 << UID_WIDTH)
+ warn_uid = 1;
+ entry->gid = st.st_gid;
+ if (entry->gid >= 1 << GID_WIDTH)
+ /* TODO: We ought to replace with a default
+ gid instead of truncating; otherwise there
+ are security problems. Maybe mode should
+ be &= ~070. Same goes for uid once Linux
+ supports >16-bit uids. */
+ warn_gid = 1;
+ size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3);
+ *fslen_ub += size;
+ if (S_ISDIR(st.st_mode)) {
+ entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub);
+ } else if (S_ISREG(st.st_mode)) {
+ /* TODO: We ought to open files in do_compress, one
+ at a time, instead of amassing all these memory
+ maps during parse_directory (which don't get used
+ until do_compress anyway). As it is, we tend to
+ get EMFILE errors (especially if mkcramfs is run
+ by non-root).
+
+ While we're at it, do analagously for symlinks
+ (which would just save a little memory). */
+ int fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ perror(path);
+ continue;
+ }
+ if (entry->size) {
+ if ((entry->size >= 1 << SIZE_WIDTH)) {
+ warn_size = 1;
+ entry->size = (1 << SIZE_WIDTH) - 1;
+ }
+
+ entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (-1 == (int) (long) entry->uncompressed) {
+ perror("mmap");
+ exit(5);
+ }
+ }
+ close(fd);
+ } else if (S_ISLNK(st.st_mode)) {
+ entry->uncompressed = malloc(entry->size);
+ if (!entry->uncompressed) {
+ perror(NULL);
+ exit(5);
+ }
+ if (readlink(path, entry->uncompressed, entry->size) < 0) {
+ perror(path);
+ continue;
+ }
+ } else {
+ entry->size = st.st_rdev;
+ if (entry->size & -(1<<SIZE_WIDTH))
+ warn_dev = 1;
+ }
+
+ if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
+ /* block pointers & data expansion allowance + data */
+ if(entry->size)
+ *fslen_ub += ((4+26)*((entry->size - 1) / blksize + 1)
+ + MIN(entry->size + 3, st.st_blocks << 9));
+ else
+ *fslen_ub += MIN(entry->size + 3, st.st_blocks << 9);
+ }
+
+ /* Link it into the list */
+ *prev = entry;
+ prev = &entry->next;
+ count++;
+ totalsize += size;
+ }
+ closedir(dir);
+ free(path);
+ return totalsize;
+}
+
+static void set_random(void *area, size_t size)
+{
+ int fd = open("/dev/random", O_RDONLY);
+
+ if (fd >= 0) {
+ if (read(fd, area, size) == size)
+ return;
+ }
+ memset(area, 0x00, size);
+}
+
+/* Returns sizeof(struct cramfs_super), which includes the root inode. */
+static unsigned int write_superblock(struct entry *root, char *base)
+{
+ struct cramfs_super *super = (struct cramfs_super *) base;
+ unsigned int offset = sizeof(struct cramfs_super);
+
+ super->magic = CRAMFS_MAGIC;
+ super->flags = 0;
+ /* Note: 0x10000 is meaningless, which is a bug; but
+ super->size is never used anyway. */
+ super->size = 0x10000;
+ memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
+ set_random(super->fsid, sizeof(super->fsid));
+ strncpy(super->name, "Compressed", sizeof(super->name));
+
+ super->root.mode = root->mode;
+ super->root.uid = root->uid;
+ super->root.gid = root->gid;
+ super->root.size = root->size;
+ super->root.offset = offset >> 2;
+
+ return offset;
+}
+
+static void set_data_offset(struct entry *entry, char *base, unsigned long offset)
+{
+ struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset);
+ assert ((offset & 3) == 0);
+ if (offset >= (1 << (2 + OFFSET_WIDTH))) {
+ fprintf(stderr, "filesystem too big. Exiting.\n");
+ exit(1);
+ }
+ inode->offset = (offset >> 2);
+}
+
+
+/*
+ * We do a width-first printout of the directory
+ * entries, using a stack to remember the directories
+ * we've seen.
+ */
+#define MAXENTRIES (100)
+static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset)
+{
+ int stack_entries = 0;
+ struct entry *entry_stack[MAXENTRIES];
+
+ for (;;) {
+ int dir_start = stack_entries;
+ while (entry) {
+ struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset);
+ size_t len = strlen(entry->name);
+
+ entry->dir_offset = offset;
+
+ inode->mode = entry->mode;
+ inode->uid = entry->uid;
+ inode->gid = entry->gid;
+ inode->size = entry->size;
+ inode->offset = 0;
+ /* Non-empty directories, regfiles and symlinks will
+ write over inode->offset later. */
+
+ offset += sizeof(struct cramfs_inode);
+ memcpy(base + offset, entry->name, len);
+ /* Pad up the name to a 4-byte boundary */
+ while (len & 3) {
+ *(base + offset + len) = '\0';
+ len++;
+ }
+ inode->namelen = len >> 2;
+ offset += len;
+
+ /* TODO: this may get it wrong for chars >= 0x80.
+ Most filesystems use UTF8 encoding for filenames,
+ whereas the console is a single-byte character
+ set like iso-latin-1. */
+ printf(" %s\n", entry->name);
+ if (entry->child) {
+ if (stack_entries >= MAXENTRIES) {
+ fprintf(stderr, "Exceeded MAXENTRIES. Raise this value in mkcramfs.c and recompile. Exiting.\n");
+ exit(1);
+ }
+ entry_stack[stack_entries] = entry;
+ stack_entries++;
+ }
+ entry = entry->next;
+ }
+
+ /*
+ * Reverse the order the stack entries pushed during
+ * this directory, for a small optimization of disk
+ * access in the created fs. This change makes things
+ * `ls -UR' order.
+ */
+ {
+ struct entry **lo = entry_stack + dir_start;
+ struct entry **hi = entry_stack + stack_entries;
+ struct entry *tmp;
+
+ while (lo < --hi) {
+ tmp = *lo;
+ *lo++ = *hi;
+ *hi = tmp;
+ }
+ }
+
+ /* Pop a subdirectory entry from the stack, and recurse. */
+ if (!stack_entries)
+ break;
+ stack_entries--;
+ entry = entry_stack[stack_entries];
+
+ set_data_offset(entry, base, offset);
+ printf("'%s':\n", entry->name);
+ entry = entry->child;
+ }
+ return offset;
+}
+
+#ifdef DO_HOLES
+/*
+ * Returns non-zero iff the first LEN bytes from BEGIN are all NULs.
+ */
+static int
+is_zero(char const *begin, unsigned len)
+{
+ return (len-- == 0 ||
+ (begin[0] == '\0' &&
+ (len-- == 0 ||
+ (begin[1] == '\0' &&
+ (len-- == 0 ||
+ (begin[2] == '\0' &&
+ (len-- == 0 ||
+ (begin[3] == '\0' &&
+ memcmp(begin, begin + 4, len) == 0))))))));
+}
+#else /* !DO_HOLES */
+# define is_zero(_begin,_len) (0) /* Never create holes. */
+#endif /* !DO_HOLES */
+
+/*
+ * One 4-byte pointer per block and then the actual blocked
+ * output. The first block does not need an offset pointer,
+ * as it will start immediately after the pointer block;
+ * so the i'th pointer points to the end of the i'th block
+ * (i.e. the start of the (i+1)'th block or past EOF).
+ *
+ * Note that size > 0, as a zero-sized file wouldn't ever
+ * have gotten here in the first place.
+ */
+static unsigned int do_compress(char *base, unsigned int offset, char const *name, char *uncompressed, unsigned int size)
+{
+ unsigned long original_size = size;
+ unsigned long original_offset = offset;
+ unsigned long new_size;
+ unsigned long blocks = (size - 1) / blksize + 1;
+ unsigned long curr = offset + 4 * blocks;
+ int change;
+
+ do {
+ unsigned long len = 2 * blksize;
+ unsigned int input = size;
+ if (input > blksize)
+ input = blksize;
+ size -= input;
+ if (!is_zero (uncompressed, input)) {
+ compress(base + curr, &len, uncompressed, input);
+ curr += len;
+ }
+ uncompressed += input;
+
+ if (len > blksize*2) {
+ /* (I don't think this can happen with zlib.) */
+ printf("AIEEE: block \"compressed\" to > 2*blocklength (%ld)\n", len);
+ exit(1);
+ }
+
+ *(u32 *) (base + offset) = curr;
+ offset += 4;
+ } while (size);
+
+ curr = (curr + 3) & ~3;
+ new_size = curr - original_offset;
+ /* TODO: Arguably, original_size in these 2 lines should be
+ st_blocks * 512. But if you say that then perhaps
+ administrative data should also be included in both. */
+ change = new_size - original_size;
+ printf("%6.2f%% (%+d bytes)\t%s\n",
+ (change * 100) / (double) original_size, change, name);
+
+ return curr;
+}
+
+
+/*
+ * Traverse the entry tree, writing data for every item that has
+ * non-null entry->compressed (i.e. every symlink and non-empty
+ * regfile).
+ */
+static unsigned int write_data(struct entry *entry, char *base, unsigned int offset)
+{
+ do {
+ if (entry->uncompressed) {
+ if(entry->same) {
+ set_data_offset(entry, base, entry->same->offset);
+ entry->offset=entry->same->offset;
+ } else {
+ set_data_offset(entry, base, offset);
+ entry->offset=offset;
+ offset = do_compress(base, offset, entry->name, entry->uncompressed, entry->size);
+ }
+ }
+ else if (entry->child)
+ offset = write_data(entry->child, base, offset);
+ entry=entry->next;
+ } while (entry);
+ return offset;
+}
+
+
+/*
+ * Maximum size fs you can create is roughly 256MB. (The last file's
+ * data must begin within 256MB boundary but can extend beyond that.)
+ *
+ * Note that if you want it to fit in a ROM then you're limited to what the
+ * hardware and kernel can support (64MB?).
+ */
+#define MAXFSLEN ((((1 << OFFSET_WIDTH) - 1) << 2) /* offset */ \
+ + (1 << SIZE_WIDTH) - 1 /* filesize */ \
+ + (1 << SIZE_WIDTH) * 4 / PAGE_CACHE_SIZE /* block pointers */ )
+
+
+/*
+ * Usage:
+ *
+ * mkcramfs directory-name outfile
+ *
+ * where "directory-name" is simply the root of the directory
+ * tree that we want to generate a compressed filesystem out
+ * of.
+ */
+int main(int argc, char **argv)
+{
+ struct stat st;
+ struct entry *root_entry;
+ char *rom_image;
+ unsigned int offset;
+ ssize_t written;
+ int fd;
+ loff_t fslen_ub = 0; /* initial guess (upper-bound) of
+ required filesystem size */
+ char const *dirname;
+
+ if (argc)
+ progname = argv[0];
+ if (argc != 3)
+ usage();
+
+ if (stat(dirname = argv[1], &st) < 0) {
+ perror(argv[1]);
+ exit(1);
+ }
+ fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+ root_entry = calloc(1, sizeof(struct entry));
+ if (!root_entry) {
+ perror(NULL);
+ exit(5);
+ }
+ root_entry->mode = st.st_mode;
+ root_entry->uid = st.st_uid;
+ root_entry->gid = st.st_gid;
+
+ root_entry->size = parse_directory(root_entry, argv[1], &root_entry->child, &fslen_ub);
+ if (fslen_ub > MAXFSLEN) {
+ fprintf(stderr,
+ "warning: guestimate of required size (upper bound) is %luMB, but maximum image size is %uMB. We might die prematurely.\n",
+ (unsigned long) (fslen_ub >> 20),
+ MAXFSLEN >> 20);
+ fslen_ub = MAXFSLEN;
+ }
+
+ /* find duplicate files. TODO: uses the most inefficient algorithm
+ possible. */
+ eliminate_doubles(root_entry,root_entry);
+
+
+ /* TODO: Why do we use a private/anonymous mapping here
+ followed by a write below, instead of just a shared mapping
+ and a couple of ftruncate calls? Is it just to save us
+ having to deal with removing the file afterwards? If we
+ really need this huge anonymous mapping, we ought to mmap
+ in smaller chunks, so that the user doesn't need nn MB of
+ RAM free. If the reason is to be able to write to
+ un-mmappable block devices, then we could try shared mmap
+ and revert to anonymous mmap if the shared mmap fails. */
+ rom_image = mmap(NULL, fslen_ub, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (-1 == (int) (long) rom_image) {
+ perror("ROM image map");
+ exit(1);
+ }
+ offset = write_superblock(root_entry, rom_image);
+ printf("Super block: %d bytes\n", offset);
+
+ offset = write_directory_structure(root_entry->child, rom_image, offset);
+ printf("Directory data: %d bytes\n", offset);
+
+ offset = write_data(root_entry, rom_image, offset);
+
+ /* We always write a multiple of blksize bytes, so that
+ losetup works. */
+ offset = ((offset - 1) | (blksize - 1)) + 1;
+ printf("Everything: %d kilobytes\n", offset >> 10);
+
+ written = write(fd, rom_image, offset);
+ if (written < 0) {
+ perror("rom image");
+ exit(1);
+ }
+ if (offset != written) {
+ fprintf(stderr, "ROM image write failed (%d %d)\n", written, offset);
+ exit(1);
+ }
+
+ /* (These warnings used to come at the start, but they scroll off the
+ screen too quickly.) */
+ if (warn_namelen) /* (can't happen when reading from ext2fs) */
+ fprintf(stderr, /* bytes, not chars: think UTF8. */
+ "warning: filenames truncated to 255 bytes.\n");
+ if (warn_size)
+ fprintf(stderr,
+ "warning: file sizes truncated to %luMB (minus 1 byte).\n",
+ 1L << (SIZE_WIDTH - 20));
+ if (warn_uid) /* (not possible with current Linux versions) */
+ fprintf(stderr,
+ "warning: uids truncated to %u bits. (This may be a security concern.)\n",
+ UID_WIDTH);
+ if (warn_gid)
+ fprintf(stderr,
+ "warning: gids truncated to %u bits. (This may be a security concern.)\n",
+ GID_WIDTH);
+ if (warn_dev)
+ fprintf(stderr,
+ "WARNING: device numbers truncated to %u bits. This almost certainly means\n"
+ "that some device files will be wrong.\n",
+ OFFSET_WIDTH);
+ return 0;
+}
diff --git a/scripts/docgen b/scripts/docgen
new file mode 100644
index 000000000000..8d5fefef3abe
--- /dev/null
+++ b/scripts/docgen
@@ -0,0 +1,3 @@
+#!/bin/sh
+X=`$TOPDIR/scripts/gen-all-syms "$*"`
+$TOPDIR/scripts/docproc $X
diff --git a/scripts/docproc.c b/scripts/docproc.c
new file mode 100644
index 000000000000..465a604a33e1
--- /dev/null
+++ b/scripts/docproc.c
@@ -0,0 +1,103 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+/*
+ * A simple filter for the templates
+ */
+
+int main(int argc, char *argv[])
+{
+ char buf[1024];
+ char *vec[8192];
+ char *fvec[200];
+ char **svec;
+ char type[64];
+ int i;
+ int vp=2;
+ pid_t pid;
+
+
+ if(chdir(getenv("TOPDIR")))
+ {
+ perror("chdir");
+ exit(1);
+ }
+
+ /*
+ * Build the exec array ahead of time.
+ */
+ vec[0]="kernel-doc";
+ vec[1]="-docbook";
+ for(i=1;vp<8189;i++)
+ {
+ if(argv[i]==NULL)
+ break;
+ vec[vp++]=type;
+ vec[vp++]=argv[i];
+ }
+ vec[vp++]=buf+2;
+ vec[vp++]=NULL;
+
+ /*
+ * Now process the template
+ */
+
+ while(fgets(buf, 1024, stdin))
+ {
+ if(*buf!='!') {
+ printf("%s", buf);
+ continue;
+ }
+
+ fflush(stdout);
+ svec = vec;
+ if(buf[1]=='E')
+ strcpy(type, "-function");
+ else if(buf[1]=='I')
+ strcpy(type, "-nofunction");
+ else if(buf[1]=='F') {
+ int snarf = 0;
+ fvec[0] = "kernel-doc";
+ fvec[1] = "-docbook";
+ strcpy (type, "-function");
+ vp = 2;
+ for (i = 2; buf[i]; i++) {
+ if (buf[i] == ' ' || buf[i] == '\n') {
+ buf[i] = '\0';
+ snarf = 1;
+ continue;
+ }
+
+ if (snarf) {
+ snarf = 0;
+ fvec[vp++] = type;
+ fvec[vp++] = &buf[i];
+ }
+ }
+ fvec[vp++] = &buf[2];
+ fvec[vp] = NULL;
+ svec = fvec;
+ } else
+ {
+ fprintf(stderr, "Unknown ! escape.\n");
+ exit(1);
+ }
+ switch(pid=fork())
+ {
+ case -1:
+ perror("fork");
+ exit(1);
+ case 0:
+ execvp("scripts/kernel-doc", svec);
+ perror("exec scripts/kernel-doc");
+ exit(1);
+ default:
+ waitpid(pid, NULL,0);
+ }
+ }
+ exit(0);
+}
diff --git a/scripts/gen-all-syms b/scripts/gen-all-syms
new file mode 100644
index 000000000000..b15b160040e8
--- /dev/null
+++ b/scripts/gen-all-syms
@@ -0,0 +1,7 @@
+#!/bin/sh
+for i in $*
+do
+ grep "EXPORT_SYMBOL.*(.*)" "$i" \
+ | sed -e "s/EXPORT_SYMBOL.*(/ /" \
+ | sed -e "s/).*$//" | sed -e "s/^ //"
+done
diff --git a/scripts/header.tk b/scripts/header.tk
new file mode 100644
index 000000000000..94963425a9a5
--- /dev/null
+++ b/scripts/header.tk
@@ -0,0 +1,636 @@
+# FILE: header.tk
+# This file is boilerplate TCL/TK function definitions for 'make xconfig'.
+#
+# CHANGES
+# =======
+#
+# 8 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Remove unused do_cmd function (part of the 2.0 sound support).
+# - Arrange buttons in three columns for better screen fitting.
+# - Add CONSTANT_Y, CONSTANT_M, CONSTANT_N for commands like:
+# dep_tristate 'foo' CONFIG_FOO m
+#
+# 23 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Shut vfix the hell up.
+#
+# 24 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+# - Improve the exit message (Jeff Ronne).
+
+#
+# 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} ] {
+ set $var 4
+ }
+}
+
+#
+# Constant values used by certain dep_tristate commands.
+#
+set CONSTANT_Y 1
+set CONSTANT_M 2
+set CONSTANT_N 0
+set CONSTANT_E 4
+
+#
+# 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 } {
+ wm title . "$text"
+}
+
+proc menu_option { w menu_num text } {
+ global menus_per_column
+ global processed_top_level
+ set processed_top_level [expr $processed_top_level + 1]
+ if { $processed_top_level <= $menus_per_column } then {
+ set myframe left
+ } elseif { $processed_top_level <= [expr 2 * $menus_per_column] } then {
+ set myframe middle
+ } else {
+ set myframe right
+ }
+ button .f0.x$menu_num -anchor w -text "$text" \
+ -command "$w .$w \"$text\""
+ pack .f0.x$menu_num -pady 0 -side top -fill x -in .f0.$myframe
+}
+
+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
+}
+
+bind all <Alt-q> {maybe_exit .maybe}
+
+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
+ bind $w <Return> "exit"
+ bind $w <Escape> "destroy $w; focus $oldFocus"
+ 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 "Xconfig Internal Error"
+
+ 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 "Xconfig Internal Error"
+
+ 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
+ }
+ if [regexp {([0-9A-Za-z_]+)="([^"]*)"} $line foo var value] {
+ set cmd "global $var; set $var \"$value\""
+ eval $cmd
+ }
+ }
+ close $file1
+ update_choices
+ update_mainmenu
+}
+proc write_comment { file1 file2 text } {
+ puts $file1 ""
+ puts $file1 "#"
+ puts $file1 "# $text"
+ puts $file1 "#"
+ puts $file2 "/*"
+ puts $file2 " * $text"
+ puts $file2 " */"
+}
+
+proc effective_dep { deplist } {
+ global CONFIG_MODULES
+ set depend 1
+ foreach i $deplist {
+ if {$i == 0} then {set depend 0}
+ if {$i == 2 && $depend == 1} then {set depend 2}
+ }
+ if {$depend == 2 && $CONFIG_MODULES == 0} then {set depend 0}
+ return $depend
+}
+
+proc sync_tristate { var dep } {
+ global CONFIG_MODULES
+ if {$dep == 0 && ($var == 1 || $var == 2)} then {
+ set var 0
+ } elseif {$dep == 2 && $var == 1} then {
+ set var 2
+ } elseif {$var == 2 && $CONFIG_MODULES == 0} then {
+ if {$dep == 1} then {set var 1} else {set var 0}
+ }
+ return $var
+}
+
+proc sync_bool { var dep modset } {
+ set var [sync_tristate $var $dep]
+ if {$dep == 2 && $var == 2} then {
+ set var $modset
+ }
+ return $var
+}
+
+proc write_tristate { file1 file2 varname variable deplist modset } {
+ set variable [sync_tristate $variable [effective_dep $deplist]]
+ if { $variable == 2 } \
+ then { set variable $modset }
+ if { $variable == 1 } \
+ then { puts $file1 "$varname=y"; \
+ puts $file2 "#define $varname 1" } \
+ elseif { $variable == 2 } \
+ then { puts $file1 "$varname=m"; \
+ puts $file2 "#undef $varname"; \
+ puts $file2 "#define ${varname}_MODULE 1" } \
+ elseif { $variable == 0 } \
+ then { puts $file1 "# $varname is not set"; \
+ puts $file2 "#undef $varname"} \
+ else { \
+ puts stdout "ERROR - Attempting to write value for unconfigured variable ($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 -nonewline $file2 "#define $varname 0x"; \
+ puts $file2 [exec echo $variable | sed s/^0\[xX\]//]; \
+ }
+}
+
+proc write_string { 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 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 .menu$mnum"
+ pack $w.x$line.help -side right -fill y
+ pack $w.x$line.l -side right -fill both -expand on
+}
+
+proc toggle_switch2 {w mnum line text variable} {
+ frame $w.x$line -relief sunken
+ radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \
+ -relief groove -width 2 -command "update_active"
+ radiobutton $w.x$line.m -text "-" -variable $variable -value 2 \
+ -relief groove -width 2 -command "update_active"
+ radiobutton $w.x$line.n -text "n" -variable $variable -value 0 \
+ -relief groove -width 2 -command "update_active"
+
+ 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 toggle_switch3 {w mnum line text variable} {
+ frame $w.x$line -relief sunken
+ radiobutton $w.x$line.y -text "y" -variable $variable -value 1 \
+ -relief groove -width 2 -command "update_active"
+ radiobutton $w.x$line.m -text "m" -variable $variable -value 2 \
+ -relief groove -width 2 -command "update_active"
+ radiobutton $w.x$line.n -text "n" -variable $variable -value 0 \
+ -relief groove -width 2 -command "update_active"
+
+ option_name $w $mnum $line $text $variable
+
+ global CONFIG_MODULES
+ if {($CONFIG_MODULES == 0)} then {
+ $w.x$line.m configure -state disabled
+ }
+ 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_switch2 $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_switch3 $w $mnum $line $text $variable
+ pack $w.x$line -anchor w -fill both -expand on
+}
+
+proc dep_tristate {w mnum line text variable } {
+ tristate $w $mnum $line $text $variable
+}
+
+proc dep_bool {w mnum line text variable } {
+ bool $w $mnum $line $text $variable
+}
+
+proc int { w mnum line text variable } {
+ frame $w.x$line
+ entry $w.x$line.x -width 18 -relief sunken -borderwidth 2 \
+ -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 istring { 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 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 \
+ -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 menusplit {w m n} {
+ if { $n > 2 } then {
+ update idletasks
+ set menuoptsize [expr [$m yposition 2] - [$m yposition 1]]
+ set maxsize [winfo screenheight $w]
+ set splitpoint [expr $maxsize * 4 / 5 / $menuoptsize - 1]
+ for {set i [expr $splitpoint + 1]} {$i <= $n} {incr i $splitpoint} {
+ $m entryconfigure $i -columnbreak 1
+ }
+ }
+}
+
+proc menutitle {text menu w} {
+ wm title $w "$text"
+}
+
+proc submenu { w mnum line text subnum } {
+ frame $w.x$line
+ button $w.x$line.l -text "" -width 15 -relief groove
+ $w.x$line.l configure -activefore [cget $w.x$line.l -fg] \
+ -activeback [cget $w.x$line.l -bg] -state disabled
+ button $w.x$line.m -text "$text" -relief raised -anchor w \
+ -command "catch {destroy .menu$subnum}; menu$subnum .menu$subnum \"$text\""
+ pack $w.x$line.l -side left -fill both
+ pack $w.x$line.m -anchor w -side right -fill both -expand on
+ pack $w.x$line -anchor w -fill both -expand on
+}
+
+proc comment {w mnum line text } {
+ frame $w.x$line
+ button $w.x$line.l -text "" -width 15 -relief groove
+ $w.x$line.l configure -activefore [cget $w.x$line.l -fg] \
+ -activeback [cget $w.x$line.l -bg] -state disabled
+ button $w.x$line.m -text "$text" -relief groove -anchor w
+ $w.x$line.m configure -activefore [cget $w.x$line.m -fg] \
+ -activeback [cget $w.x$line.m -bg]
+ pack $w.x$line.l -side left -fill both
+ pack $w.x$line.m -anchor w -side right -fill both -expand on
+ pack $w.x$line -anchor w -fill both -expand on
+}
+
+proc dohelp {w var parent} {
+ 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
+ # First escape sed regexp special characters in var:
+ set var [exec echo "$var" | sed s/\[\]\[\/.^$*\]/\\\\&/g]
+ # Now pick out right help text:
+ set message [exec sed -n "
+ /^$var\[ \]*\$/,\${
+ /^$var\[ \]*\$/c\\
+${var}:\\
+
+ /^#/b
+ /^\[^ \]/q
+ s/^ //
+ p
+ }
+ " Documentation/Configure.help]
+ set found [expr [string length "$message"] > 0]
+ }
+
+ frame $w.f1
+ pack $w.f1 -fill both -expand on
+
+ # Do the OK button
+ #
+ set oldFocus [focus]
+ frame $w.f2
+ button $w.f2.ok -text "OK" \
+ -width 10 -command "destroy $w; catch {focus $oldFocus}"
+ pack $w.f2.ok -side bottom -pady 6 -anchor n
+ pack $w.f2 -side bottom -padx 10 -anchor s
+
+ scrollbar $w.f1.vscroll -command "$w.f1.canvas yview"
+ pack $w.f1.vscroll -side right -fill y
+
+ canvas $w.f1.canvas -relief flat -borderwidth 0 \
+ -yscrollcommand "$w.f1.vscroll set"
+ frame $w.f1.f
+ pack $w.f1.canvas -side right -fill y -expand on
+
+ if { $found == 0 } then {
+ if { $filefound == 0 } then {
+ message $w.f1.f.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.f.m -width 400 -aspect 300 -relief flat -text \
+ "No help available for $var"
+ }
+ label $w.f1.bm -bitmap error
+ wm title $w "RTFM"
+ } else {
+ text $w.f1.f.m -width 73 -relief flat -wrap word
+ $w.f1.f.m insert 0.0 $message
+ $w.f1.f.m conf -state disabled -height [$w.f1.f.m index end]
+
+ label $w.f1.bm -bitmap info
+ wm title $w "Configuration help"
+ }
+ pack $w.f1.f.m -side left
+ pack $w.f1.bm $w.f1.f -side left -padx 10
+
+ focus $w
+ set winx [expr [winfo x $parent]+20]
+ set winy [expr [winfo y $parent]+20]
+ wm geometry $w +$winx+$winy
+ set sizok [expr [winfo reqheight $w.f2.ok] + 12]
+ set maxy [expr [winfo screenheight .] * 3 / 4]
+ set canvtotal [winfo reqheight $w.f1.f.m]
+ if [expr $sizok + $canvtotal < $maxy] {
+ set sizy $canvtotal
+ } else {
+ set sizy [expr $maxy - $sizok]
+ }
+ $w.f1.canvas configure -height $sizy -width [winfo reqwidth $w.f1.f.m] \
+ -scrollregion "0 0 [winfo reqwidth $w.f1.f.m] \
+ [winfo reqheight $w.f1.f.m]"
+ $w.f1.canvas create window 0 0 -anchor nw -window $w.f1.f
+ update idletasks
+
+ set maxy [winfo screenheight .]
+ if [expr $sizok + $canvtotal < $maxy] {
+ set sizy [expr $sizok + $canvtotal]
+ } else {
+ set sizy $maxy
+ }
+ wm maxsize $w [winfo width $w] $sizy
+}
+
+bind all <Alt-s> { catch {exec cp -f .config .config.old}; \
+ writeconfig .config include/linux/autoconf.h; wrapup .wrap }
+
+proc wrapup {w } {
+ catch {destroy $w}
+ toplevel $w -class Dialog
+
+ global CONFIG_MODVERSIONS; vfix CONFIG_MODVERSIONS
+ if { ([file exists .hdepend] != 1) || ($CONFIG_MODVERSIONS == 1) } then {
+ message $w.m -width 400 -aspect 300 -relief raised -text \
+ "End of Linux kernel configuration. Check the top-level Makefile for additional configuration. Next, you must run 'make dep'."
+ } else {
+ message $w.m -width 400 -aspect 300 -relief raised -text \
+ "End of Linux kernel configuration. Check the top-level Makefile for additional configuration. Next, you may 'make bzImage', 'make bzdisk', or 'make bzlilo.'"
+ }
+ 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
+ bind $w <Return> "exit"
+ global winx; global winy
+ set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+ wm geometry $w +$winx+$winy
+
+}
+
+proc unregister_active {num} {
+ global active_menus
+ set index [lsearch -exact $active_menus $num]
+ if {$index != -1} then {set active_menus [lreplace $active_menus $index $index]}
+}
+
+proc update_active {} {
+ global active_menus total_menus
+ set max 0
+ if {[llength $active_menus] > 0} then {
+ set max [lindex $active_menus end]
+ update_define [toplevel_menu [lindex $active_menus 0]] $max 0
+ }
+ foreach i $active_menus {
+ if {[winfo exists .menu$i] == 0} then {
+ unregister_active $i
+ } else {
+ update_menu$i
+ }
+ }
+ update_define [expr $max + 1] $total_menus 1
+ update_mainmenu
+}
+
+proc configure_entry {w option items} {
+ foreach i $items {
+ $w.$i configure -state $option
+ }
+}
+
+proc validate_int {name val default} {
+ if {([exec echo $val | sed s/^-//g | tr -d \[:digit:\] ] != "")} then {
+ global $name; set $name $default
+ }
+}
+
+proc validate_hex {name val default} {
+ if {([exec echo $val | tr -d \[:xdigit:\] ] != "")} then {
+ global $name; set $name $default
+ }
+}
+
+proc update_define {first last allow_update} {
+ for {set i $first} {$i <= $last} {incr i} {
+ update_define_menu$i
+ if {$allow_update == 1} then update
+ }
+}
+
+#
+# Next set up the particulars for the top level menu, and define a few
+# buttons which we will stick down at the bottom.
+#
+
+frame .f0
+frame .f0.left
+frame .f0.middle
+frame .f0.right
+
+set active_menus [list]
+set processed_top_level 0
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
new file mode 100644
index 000000000000..4f8fb25becc4
--- /dev/null
+++ b/scripts/kernel-doc
@@ -0,0 +1,998 @@
+#!/usr/bin/perl
+
+## Copyright (c) 1998 Michael Zucchi, All Rights Reserved ##
+## Copyright (C) 2000 Tim Waugh <twaugh@redhat.com> ##
+## ##
+## #define enhancements by Armin Kuster <akuster@mvista.com> ##
+## Copyright (c) 2000 MontaVista Software, Inc. ##
+## ##
+## This software falls under the GNU General Public License. ##
+## Please read the COPYING file for more information ##
+
+# w.o. 03-11-2000: added the '-filelist' option.
+
+#
+# This will read a 'c' file and scan for embedded comments in the
+# style of gnome comments (+minor extensions - see below).
+#
+
+# Note: This only supports 'c'.
+
+# usage:
+# kerneldoc [ -docbook | -html | -text | -man ]
+# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
+# or
+# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
+#
+# Set output format using one of -docbook -html -text or -man. Default is man.
+#
+# -function funcname
+# If set, then only generate documentation for the given function(s). All
+# other functions are ignored.
+#
+# -nofunction funcname
+# If set, then only generate documentation for the other function(s). All
+# other functions are ignored. Cannot be used with -function together
+# (yes thats a bug - perl hackers can fix it 8))
+#
+# c files - list of 'c' files to process
+#
+# All output goes to stdout, with errors to stderr.
+
+#
+# format of comments.
+# In the following table, (...)? signifies optional structure.
+# (...)* signifies 0 or more structure elements
+# /**
+# * function_name(:)? (- short description)?
+# (* @parameterx: (description of parameter x)?)*
+# (* a blank line)?
+# * (Description:)? (Description of function)?
+# * (section header: (section description)? )*
+# (*)?*/
+#
+# So .. the trivial example would be:
+#
+# /**
+# * my_function
+# **/
+#
+# If the Description: header tag is ommitted, then there must be a blank line
+# after the last parameter specification.
+# e.g.
+# /**
+# * my_function - does my stuff
+# * @my_arg: its mine damnit
+# *
+# * Does my stuff explained.
+# */
+#
+# or, could also use:
+# /**
+# * my_function - does my stuff
+# * @my_arg: its mine damnit
+# * Description: Does my stuff explained.
+# */
+# etc.
+#
+# All descriptions can be multiline, apart from the short function description.
+#
+# All descriptive text is further processed, scanning for the following special
+# patterns, which are highlighted appropriately.
+#
+# 'funcname()' - function
+# '$ENVVAR' - environmental variable
+# '&struct_name' - name of a structure (up to two words including 'struct')
+# '@parameter' - name of a parameter
+# '%CONST' - name of a constant.
+
+# match expressions used to find embedded type information
+$type_constant = "\\\%([-_\\w]+)";
+$type_func = "(\\w+)\\(\\)";
+$type_param = "\\\@(\\w+)";
+$type_struct = "\\\&((struct\\s*)?[_\\w]+)";
+$type_env = "(\\\$\\w+)";
+
+
+# Output conversion substitutions.
+# One for each output format
+
+# these work fairly well
+%highlights_html = ( $type_constant, "<i>\$1</i>",
+ $type_func, "<b>\$1</b>",
+ $type_struct, "<i>\$1</i>",
+ $type_param, "<tt><b>\$1</b></tt>" );
+$blankline_html = "<p>";
+
+# sgml, docbook format
+%highlights_sgml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
+ $type_constant, "<constant>\$1</constant>",
+ $type_func, "<function>\$1</function>",
+ $type_struct, "<structname>\$1</structname>",
+ $type_env, "<envar>\$1</envar>",
+ $type_param, "<parameter>\$1</parameter>" );
+$blankline_sgml = "</para><para>\n";
+
+# gnome, docbook format
+%highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
+ $type_func, "<function>\$1</function>",
+ $type_struct, "<structname>\$1</structname>",
+ $type_env, "<envar>\$1</envar>",
+ $type_param, "<parameter>\$1</parameter>" );
+$blankline_gnome = "</para><para>\n";
+
+# these are pretty rough
+%highlights_man = ( $type_constant, "\$1",
+ $type_func, "\\\\fB\$1\\\\fP",
+ $type_struct, "\\\\fI\$1\\\\fP",
+ $type_param, "\\\\fI\$1\\\\fP" );
+$blankline_man = "";
+
+# text-mode
+%highlights_text = ( $type_constant, "\$1",
+ $type_func, "\$1",
+ $type_struct, "\$1",
+ $type_param, "\$1" );
+$blankline_text = "";
+
+
+sub usage {
+ print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
+ print " [ -function funcname [ -function funcname ...] ]\n";
+ print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
+ print " c source file(s) > outputfile\n";
+ exit 1;
+}
+
+# read arguments
+if ($#ARGV==-1) {
+ usage();
+}
+
+$verbose = 0;
+$output_mode = "man";
+%highlights = %highlights_man;
+$blankline = $blankline_man;
+$modulename = "API Documentation";
+$function_only = 0;
+$filelist = '';
+
+while ($ARGV[0] =~ m/^-(.*)/) {
+ $cmd = shift @ARGV;
+ if ($cmd eq "-html") {
+ $output_mode = "html";
+ %highlights = %highlights_html;
+ $blankline = $blankline_html;
+ } elsif ($cmd eq "-man") {
+ $output_mode = "man";
+ %highlights = %highlights_man;
+ $blankline = $blankline_man;
+ } elsif ($cmd eq "-text") {
+ $output_mode = "text";
+ %highlights = %highlights_text;
+ $blankline = $blankline_text;
+ } elsif ($cmd eq "-docbook") {
+ $output_mode = "sgml";
+ %highlights = %highlights_sgml;
+ $blankline = $blankline_sgml;
+ } elsif ($cmd eq "-gnome") {
+ $output_mode = "gnome";
+ %highlights = %highlights_gnome;
+ $blankline = $blankline_gnome;
+ } elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
+ $modulename = shift @ARGV;
+ } elsif ($cmd eq "-function") { # to only output specific functions
+ $function_only = 1;
+ $function = shift @ARGV;
+ $function_table{$function} = 1;
+ } elsif ($cmd eq "-nofunction") { # to only output specific functions
+ $function_only = 2;
+ $function = shift @ARGV;
+ $function_table{$function} = 1;
+ } elsif ($cmd eq "-v") {
+ $verbose = 1;
+ } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
+ usage();
+ } elsif ($cmd eq '-filelist') {
+ $filelist = shift @ARGV;
+ }
+}
+
+
+# generate a sequence of code that will splice in highlighting information
+# using the s// operator.
+$dohighlight = "";
+foreach $pattern (keys %highlights) {
+# print "scanning pattern $pattern ($highlights{$pattern})\n";
+ $dohighlight .= "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
+}
+
+##
+# dumps section contents to arrays/hashes intended for that purpose.
+#
+sub dump_section {
+ my $name = shift @_;
+ my $contents = join "\n", @_;
+
+ if ($name =~ m/$type_constant/) {
+ $name = $1;
+# print STDERR "constant section '$1' = '$contents'\n";
+ $constants{$name} = $contents;
+ } elsif ($name =~ m/$type_param/) {
+# print STDERR "parameter def '$1' = '$contents'\n";
+ $name = $1;
+ $parameters{$name} = $contents;
+ } else {
+# print STDERR "other section '$name' = '$contents'\n";
+ $sections{$name} = $contents;
+ push @sectionlist, $name;
+ }
+}
+
+##
+# output function
+#
+# parameters, a hash.
+# function => "function name"
+# parameterlist => @list of parameters
+# parameters => %parameter descriptions
+# sectionlist => @list of sections
+# sections => %descriont descriptions
+#
+
+sub output_highlight {
+ my $contents = join "\n", @_;
+ my $line;
+
+ eval $dohighlight;
+ foreach $line (split "\n", $contents) {
+ if ($line eq ""){
+ print $lineprefix, $blankline;
+ } else {
+ $line =~ s/\\\\\\/\&/g;
+ print $lineprefix, $line;
+ }
+ print "\n";
+ }
+}
+
+
+# output in html
+sub output_html {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ print "<h2>Function</h2>\n";
+
+ print "<i>".$args{'functiontype'}."</i>\n";
+ print "<b>".$args{'function'}."</b>\n";
+ print "(";
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
+ } else {
+ print "<i>".$type."</i> <b>".$parameter."</b>";
+ }
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",\n";
+ }
+ }
+ print ")\n";
+
+ print "<h3>Arguments</h3>\n";
+ print "<dl>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "<dt><b>".$parameter."</b>\n";
+ print "<dd>";
+ output_highlight($args{'parameters'}{$parameter});
+ }
+ print "</dl>\n";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<h3>$section</h3>\n";
+ print "<blockquote>\n";
+ output_highlight($args{'sections'}{$section});
+ print "</blockquote>\n";
+ }
+ print "<hr>\n";
+}
+
+
+# output in html
+sub output_intro_html {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<h3>$section</h3>\n";
+ print "<ul>\n";
+ output_highlight($args{'sections'}{$section});
+ print "</ul>\n";
+ }
+ print "<hr>\n";
+}
+
+
+
+# output in sgml DocBook
+sub output_sgml {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ my $id;
+
+ $id = "API-".$args{'function'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ print "<refentry>\n";
+ print "<refmeta>\n";
+ print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
+ print "</refmeta>\n";
+ print "<refnamediv>\n";
+ print " <refname>".$args{'function'}."</refname>\n";
+ print " <refpurpose>\n";
+ print " ";
+ output_highlight ($args{'purpose'});
+ print " </refpurpose>\n";
+ print "</refnamediv>\n";
+
+ print "<refsynopsisdiv>\n";
+ print " <title>Synopsis</title>\n";
+ print " <funcsynopsis>\n";
+ print " <funcdef>".$args{'functiontype'}." ";
+ print "<function>".$args{'function'}." ";
+ print "</function></funcdef>\n";
+
+# print "<refsect1>\n";
+# print " <title>Synopsis</title>\n";
+# print " <funcsynopsis>\n";
+# print " <funcdef>".$args{'functiontype'}." ";
+# print "<function>".$args{'function'}." ";
+# print "</function></funcdef>\n";
+
+ $count = 0;
+ if ($#{$args{'parameterlist'}} >= 0) {
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print " <paramdef>$1<parameter>$parameter</parameter>)\n";
+ print " <funcparams>$2</funcparams></paramdef>\n";
+ } else {
+ print " <paramdef>".$type;
+ print " <parameter>$parameter</parameter></paramdef>\n";
+ }
+ }
+ } else {
+ print " <void>\n";
+ }
+ print " </funcsynopsis>\n";
+ print "</refsynopsisdiv>\n";
+# print "</refsect1>\n";
+
+ # print parameters
+ print "<refsect1>\n <title>Arguments</title>\n";
+# print "<para>\nArguments\n";
+ if ($#{$args{'parameterlist'}} >= 0) {
+ print " <variablelist>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
+ print " <listitem>\n <para>\n";
+ $lineprefix=" ";
+ output_highlight($args{'parameters'}{$parameter});
+ print " </para>\n </listitem>\n </varlistentry>\n";
+ }
+ print " </variablelist>\n";
+ } else {
+ print " <para>\n None\n </para>\n";
+ }
+ print "</refsect1>\n";
+
+ # print out each section
+ $lineprefix=" ";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<refsect1>\n <title>$section</title>\n <para>\n";
+# print "<para>\n$section\n";
+ if ($section =~ m/EXAMPLE/i) {
+ print "<example><para>\n";
+ }
+ output_highlight($args{'sections'}{$section});
+# print "</para>";
+ if ($section =~ m/EXAMPLE/i) {
+ print "</para></example>\n";
+ }
+ print " </para>\n</refsect1>\n";
+ }
+
+ print "</refentry>\n\n";
+}
+
+# output in sgml DocBook
+sub output_intro_sgml {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ my $id;
+
+ $id = $args{'module'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ # print out each section
+ $lineprefix=" ";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<refsect1>\n <title>$section</title>\n <para>\n";
+# print "<para>\n$section\n";
+ if ($section =~ m/EXAMPLE/i) {
+ print "<example><para>\n";
+ }
+ output_highlight($args{'sections'}{$section});
+# print "</para>";
+ if ($section =~ m/EXAMPLE/i) {
+ print "</para></example>\n";
+ }
+ print " </para>\n</refsect1>\n";
+ }
+
+ print "\n\n";
+}
+
+# output in sgml DocBook
+sub output_gnome {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ my $id;
+
+ $id = $args{'module'}."-".$args{'function'};
+ $id =~ s/[^A-Za-z0-9]/-/g;
+
+ print "<sect2>\n";
+ print " <title id=\"$id\">".$args{'function'}."</title>\n";
+
+# print "<simplesect>\n";
+# print " <title>Synopsis</title>\n";
+ print " <funcsynopsis>\n";
+ print " <funcdef>".$args{'functiontype'}." ";
+ print "<function>".$args{'function'}." ";
+ print "</function></funcdef>\n";
+
+ $count = 0;
+ if ($#{$args{'parameterlist'}} >= 0) {
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print " <paramdef>$1 <parameter>$parameter</parameter>)\n";
+ print " <funcparams>$2</funcparams></paramdef>\n";
+ } else {
+ print " <paramdef>".$type;
+ print " <parameter>$parameter</parameter></paramdef>\n";
+ }
+ }
+ } else {
+ print " <void>\n";
+ }
+ print " </funcsynopsis>\n";
+# print "</simplesect>\n";
+# print "</refsect1>\n";
+
+ # print parameters
+# print "<simplesect>\n <title>Arguments</title>\n";
+# if ($#{$args{'parameterlist'}} >= 0) {
+# print " <variablelist>\n";
+# foreach $parameter (@{$args{'parameterlist'}}) {
+# print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n";
+# print " <listitem>\n <para>\n";
+# $lineprefix=" ";
+# output_highlight($args{'parameters'}{$parameter});
+# print " </para>\n </listitem>\n </varlistentry>\n";
+# }
+# print " </variablelist>\n";
+# } else {
+# print " <para>\n None\n </para>\n";
+# }
+# print "</simplesect>\n";
+
+# print "<simplesect>\n <title>Arguments</title>\n";
+ if ($#{$args{'parameterlist'}} >= 0) {
+ print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
+ print "<tgroup cols=\"2\">\n";
+ print "<colspec colwidth=\"2*\">\n";
+ print "<colspec colwidth=\"8*\">\n";
+ print "<tbody>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
+ print " <entry>\n";
+ $lineprefix=" ";
+ output_highlight($args{'parameters'}{$parameter});
+ print " </entry></row>\n";
+ }
+ print " </tbody></tgroup></informaltable>\n";
+ } else {
+ print " <para>\n None\n </para>\n";
+ }
+# print "</simplesect>\n";
+
+ # print out each section
+ $lineprefix=" ";
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<simplesect>\n <title>$section</title>\n";
+# print "<para>\n$section\n";
+ if ($section =~ m/EXAMPLE/i) {
+ print "<example><programlisting>\n";
+ } else {
+ }
+ print "<para>\n";
+ output_highlight($args{'sections'}{$section});
+# print "</para>";
+ print "</para>\n";
+ if ($section =~ m/EXAMPLE/i) {
+ print "</programlisting></example>\n";
+ } else {
+ }
+ print " </simplesect>\n";
+ }
+
+ print "</sect2>\n\n";
+}
+
+##
+# output in man
+sub output_man {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+
+ print ".TH \"$args{'module'}\" 4 \"$args{'function'}\" \"25 May 1998\" \"API Manual\" LINUX\n";
+
+ print ".SH NAME\n";
+ print $args{'function'}." \\- ".$args{'purpose'}."\n";
+
+ print ".SH SYNOPSIS\n";
+ print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
+ $count = 0;
+ $parenth = "(";
+ $post = ",";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ if ($count == $#{$args{'parameterlist'}}) {
+ $post = ");";
+ }
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n";
+ } else {
+ $type =~ s/([^\*])$/\1 /;
+ print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n";
+ }
+ $count++;
+ $parenth = "";
+ }
+
+ print ".SH Arguments\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print ".IP \"".$parameter."\" 12\n";
+ output_highlight($args{'parameters'}{$parameter});
+ }
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+sub output_intro_man {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+
+ print ".TH \"$args{'module'}\" 4 \"$args{'module'}\" \"25 May 1998\" \"API Manual\" LINUX\n";
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+##
+# output in text
+sub output_text {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ print "Function:\n\n";
+ $start=$args{'functiontype'}." ".$args{'function'}." (";
+ print $start;
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print $1.$parameter.") (".$2;
+ } else {
+ print $type." ".$parameter;
+ }
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",\n";
+ print " " x length($start);
+ } else {
+ print ");\n\n";
+ }
+ }
+
+ print "Arguments:\n\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print $parameter."\n\t".$args{'parameters'}{$parameter}."\n";
+ }
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "$section:\n\n";
+ output_highlight($args{'sections'}{$section});
+ }
+ print "\n\n";
+}
+
+sub output_intro_text {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print " $section:\n";
+ print " -> ";
+ output_highlight($args{'sections'}{$section});
+ }
+}
+
+##
+# generic output function - calls the right one based
+# on current output mode.
+sub output_function {
+# output_html(@_);
+ eval "output_".$output_mode."(\@_);";
+}
+
+##
+# generic output function - calls the right one based
+# on current output mode.
+sub output_intro {
+# output_html(@_);
+ eval "output_intro_".$output_mode."(\@_);";
+}
+
+
+##
+# takes a function prototype and spits out all the details
+# stored in the global arrays/hashes.
+sub dump_function {
+ my $prototype = shift @_;
+
+ $prototype =~ s/^static +//;
+ $prototype =~ s/^extern +//;
+ $prototype =~ s/^inline +//;
+ $prototype =~ s/^__inline__ +//;
+ $prototype =~ s/^#define +//; #ak added
+
+ # Yes, this truly is vile. We are looking for:
+ # 1. Return type (may be nothing if we're looking at a macro)
+ # 2. Function name
+ # 3. Function parameters.
+ #
+ # All the while we have to watch out for function pointer parameters
+ # (which IIRC is what the two sections are for), C types (these
+ # regexps don't even start to express all the possibilities), and
+ # so on.
+ #
+ # If you mess with these regexps, it's a good idea to check that
+ # the following functions' documentation still comes out right:
+ # - parport_register_device (function pointer parameters)
+ # - atomic_set (macro)
+ # - pci_match_device (long return type)
+
+ if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
+ $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
+ $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
+ $return_type = $1;
+ $function_name = $2;
+ $args = $3;
+
+ # allow for up to fours args to function pointers
+ $args =~ s/(\([^\),]+),/\1#/g;
+ $args =~ s/(\([^\),]+),/\1#/g;
+ $args =~ s/(\([^\),]+),/\1#/g;
+# print STDERR "ARGS = '$args'\n";
+
+ foreach $arg (split ',', $args) {
+ # strip leading/trailing spaces
+ $arg =~ s/^\s*//;
+ $arg =~ s/\s*$//;
+
+ if ($arg =~ m/\(/) {
+ # pointer-to-function
+ $arg =~ tr/#/,/;
+ $arg =~ m/[^\(]+\(\*([^\)]+)\)/;
+ $param = $1;
+ $type = $arg;
+ $type =~ s/([^\(]+\(\*)$param/\1/;
+ } else {
+ # evil magic to get fixed array parameters to work
+ $arg =~ s/(.+\s+)(.+)\[.*/\1* \2/;
+# print STDERR "SCAN ARG: '$arg'\n";
+ @args = split('\s', $arg);
+
+# print STDERR " -> @args\n";
+ $param = pop @args;
+# print STDERR " -> @args\n";
+ if ($param =~ m/^(\*+)(.*)/) {
+ $param = $2;
+ push @args, $1;
+ }
+ $type = join " ", @args;
+ }
+
+ if ($type eq "" && $param eq "...")
+ {
+ $type="...";
+ $param="...";
+ $parameters{"..."} = "variable arguments";
+ }
+ elsif ($type eq "" && $param eq "")
+ {
+ $type="";
+ $param="void";
+ $parameters{void} = "no arguments";
+ }
+ if ($type ne "" && $parameters{$param} eq "") {
+ $parameters{$param} = "-- undescribed --";
+ print STDERR "Warning($file:$lineno): Function parameter '$param' not described in '$function_name'\n";
+ }
+
+ push @parameterlist, $param;
+ $parametertypes{$param} = $type;
+# print STDERR "param = '$param', type = '$type'\n";
+ }
+ } else {
+ print STDERR "Error($lineno): cannot understand prototype: '$prototype'\n";
+ return;
+ }
+
+ if ($function_only==0 ||
+ ( $function_only == 1 && defined($function_table{$function_name})) ||
+ ( $function_only == 2 && !defined($function_table{$function_name})))
+ {
+ output_function({'function' => $function_name,
+ 'module' => $modulename,
+ 'functiontype' => $return_type,
+ 'parameterlist' => \@parameterlist,
+ 'parameters' => \%parameters,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $function_purpose
+ });
+ }
+}
+
+######################################################################
+# main
+# states
+# 0 - normal code
+# 1 - looking for function name
+# 2 - scanning field start.
+# 3 - scanning prototype.
+$state = 0;
+$section = "";
+
+$doc_special = "\@\%\$\&";
+
+$doc_start = "^/\\*\\*\$";
+$doc_end = "\\*/";
+$doc_com = "\\s*\\*\\s*";
+$doc_func = $doc_com."(\\w+):?";
+$doc_sect = $doc_com."([".$doc_special."]?[\\w ]+):(.*)";
+$doc_content = $doc_com."(.*)";
+$doc_block = $doc_com."DOC:\\s*(.*)?";
+
+%constants = ();
+%parameters = ();
+@parameterlist = ();
+%sections = ();
+@sectionlist = ();
+
+$contents = "";
+$section_default = "Description"; # default section
+$section_intro = "Introduction";
+$section = $section_default;
+
+if( $filelist ne '' ) {
+ open(FLIST,"<$filelist") or die "Can't open file list $filelist";
+ while(<FLIST>) {
+ chop;
+ process_file($_);
+ }
+}
+
+foreach $file (@ARGV) {
+ chomp($file);
+ process_file($file);
+}
+
+sub process_file($) {
+ my ($file) = @_;
+
+ if (!open(IN,"<$file")) {
+ print STDERR "Error: Cannot open file $file\n";
+ return;
+ }
+
+ $lineno = 0;
+ while (<IN>) {
+ $lineno++;
+
+ if ($state == 0) {
+ if (/$doc_start/o) {
+ $state = 1; # next line is always the function name
+ }
+ } elsif ($state == 1) { # this line is the function name (always)
+ if (/$doc_block/o) {
+ $state = 4;
+ $contents = "";
+ if ( $1 eq "" ) {
+ $section = $section_intro;
+ } else {
+ $section = $1;
+ }
+ }
+ elsif (/$doc_func/o) {
+ $function = $1;
+ $state = 2;
+ if (/-(.*)/) {
+ $function_purpose = $1;
+ } else {
+ $function_purpose = "";
+ }
+ if ($verbose) {
+ print STDERR "Info($lineno): Scanning doc for $function\n";
+ }
+ } else {
+ print STDERR "WARN($lineno): Cannot understand $_ on line $lineno",
+ " - I thought it was a doc line\n";
+ $state = 0;
+ }
+ } elsif ($state == 2) { # look for head: lines, and include content
+ if (/$doc_sect/o) {
+ $newsection = $1;
+ $newcontents = $2;
+
+ if ($contents ne "") {
+ $contents =~ s/\&/\\\\\\amp;/g;
+ $contents =~ s/\</\\\\\\lt;/g;
+ $contents =~ s/\>/\\\\\\gt;/g;
+ dump_section($section, $contents);
+ $section = $section_default;
+ }
+
+ $contents = $newcontents;
+ if ($contents ne "") {
+ $contents .= "\n";
+ }
+ $section = $newsection;
+ } elsif (/$doc_end/) {
+
+ if ($contents ne "") {
+ $contents =~ s/\&/\\\\\\amp;/g;
+ $contents =~ s/\</\\\\\\lt;/g;
+ $contents =~ s/\>/\\\\\\gt;/g;
+ dump_section($section, $contents);
+ $section = $section_default;
+ $contents = "";
+ }
+
+# print STDERR "end of doc comment, looking for prototype\n";
+ $prototype = "";
+ $state = 3;
+ } elsif (/$doc_content/) {
+ # miguel-style comment kludge, look for blank lines after
+ # @parameter line to signify start of description
+ if ($1 eq "" && $section =~ m/^@/) {
+ $contents =~ s/\&/\\\\\\amp;/g;
+ $contents =~ s/\</\\\\\\lt;/g;
+ $contents =~ s/\>/\\\\\\gt;/g;
+ dump_section($section, $contents);
+ $section = $section_default;
+ $contents = "";
+ } else {
+ $contents .= $1."\n";
+ }
+ } else {
+ # i dont know - bad line? ignore.
+ print STDERR "WARNING($lineno): bad line: $_";
+ }
+ } elsif ($state == 3) { # scanning for function { (end of prototype)
+ if (m#\s*/\*\s+MACDOC\s*#io) {
+ # do nothing
+ }
+ elsif (/([^\{]*)/) {
+ $prototype .= $1;
+ }
+ if (/\{/ || /\#/) { # added for #define AK
+ $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
+ $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
+ $prototype =~ s@^ +@@gos; # strip leading spaces
+ dump_function($prototype);
+
+ $function = "";
+ %constants = ();
+ %parameters = ();
+ %parametertypes = ();
+ @parameterlist = ();
+ %sections = ();
+ @sectionlist = ();
+ $prototype = "";
+
+ $state = 0;
+ }
+ } elsif ($state == 4) {
+ # Documentation block
+ if (/$doc_block/) {
+ dump_section($section, $contents);
+ output_intro({'sectionlist' => \@sectionlist,
+ 'sections' => \%sections });
+ $contents = "";
+ $function = "";
+ %constants = ();
+ %parameters = ();
+ %parametertypes = ();
+ @parameterlist = ();
+ %sections = ();
+ @sectionlist = ();
+ $prototype = "";
+ if ( $1 eq "" ) {
+ $section = $section_intro;
+ } else {
+ $section = $1;
+ }
+ }
+ elsif (/$doc_end/)
+ {
+ dump_section($section, $contents);
+ output_intro({'sectionlist' => \@sectionlist,
+ 'sections' => \%sections });
+ $contents = "";
+ $function = "";
+ %constants = ();
+ %parameters = ();
+ %parametertypes = ();
+ @parameterlist = ();
+ %sections = ();
+ @sectionlist = ();
+ $prototype = "";
+ $state = 0;
+ }
+ elsif (/$doc_content/)
+ {
+ if ( $1 eq "" )
+ {
+ $contents .= $blankline;
+ }
+ else
+ {
+ $contents .= $1 . "\n";
+ }
+ }
+ }
+ }
+}
+
diff --git a/scripts/ksymoops/README b/scripts/ksymoops/README
new file mode 100644
index 000000000000..f6cb06e3f30e
--- /dev/null
+++ b/scripts/ksymoops/README
@@ -0,0 +1,8 @@
+ksymoops has been removed from the kernel. It was always meant to be a
+free standing utility, not linked to any particular kernel version.
+The latest version can be found in
+ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops together
+with patches to other utilities in order to give more accurate Oops
+debugging.
+
+Keith Owens <kaos@ocs.com.au> Sat Jun 19 10:30:34 EST 1999
diff --git a/scripts/lxdialog/BIG.FAT.WARNING b/scripts/lxdialog/BIG.FAT.WARNING
new file mode 100644
index 000000000000..a8999d82bdb3
--- /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 000000000000..ed8d17c37823
--- /dev/null
+++ b/scripts/lxdialog/Makefile
@@ -0,0 +1,46 @@
+HOSTCFLAGS += -DLOCALE
+LIBS = -lncurses
+
+ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
+ HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
+else
+ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
+ HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
+else
+ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
+ HOSTCFLAGS += -DCURSES_LOC="<ncurses.h>"
+else
+ HOSTCFLAGS += -DCURSES_LOC="<curses.h>"
+endif
+endif
+endif
+
+
+OBJS = checklist.o menubox.o textbox.o yesno.o inputbox.o \
+ util.o lxdialog.o msgbox.o
+
+%.o: %.c
+ $(HOSTCC) $(HOSTCFLAGS) -c -o $@ $<
+
+all: ncurses lxdialog
+
+lxdialog: $(OBJS)
+ $(HOSTCC) -o lxdialog $(OBJS) $(LIBS)
+
+ncurses:
+ @echo "main() {}" > lxtemp.c
+ @if $(HOSTCC) -lncurses lxtemp.c ; then \
+ rm -f lxtemp.c a.out; \
+ else \
+ rm -f lxtemp.c; \
+ echo -e "\007" ;\
+ echo ">> Unable to find the Ncurses libraries." ;\
+ echo ">>" ;\
+ 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 000000000000..a1bf1f738bcb
--- /dev/null
+++ b/scripts/lxdialog/checklist.c
@@ -0,0 +1,359 @@
+/*
+ * 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 && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ list_width = width - 6;
+ box_y = height - list_height - 5;
+ box_x = (width - list_width) / 2 - 1;
+
+ /* create new window for the list */
+ list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
+
+ keypad (list, TRUE);
+
+ /* draw a box around the list items */
+ draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /* Find length of longest item in order to center checklist */
+ check_x = 0;
+ for (i = 0; i < item_no; i++)
+ check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4);
+
+ check_x = (list_width - check_x) / 2;
+ item_x = check_x + 4;
+
+ if (choice >= list_height) {
+ scroll = choice - list_height + 1;
+ choice -= scroll;
+ }
+
+ /* Print the list */
+ for (i = 0; i < max_choice; i++) {
+ print_item (list, items[(scroll+i) * 3 + 1],
+ status[i+scroll], i, i == choice);
+ }
+
+ 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 000000000000..d34dd37c6f74
--- /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 000000000000..0e30d00d0b25
--- /dev/null
+++ b/scripts/lxdialog/dialog.h
@@ -0,0 +1,184 @@
+
+/*
+ * dialog.h -- common declarations for all dialog modules
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include CURSES_LOC
+
+/*
+ * Colors in ncurses 1.9.9e do not work properly since foreground and
+ * background colors are OR'd rather than separately masked. This version
+ * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible
+ * with standard curses. The simplest fix (to make this work with standard
+ * curses) uses the wbkgdset() function, not used in the original hack.
+ * Turn it off if we're building with 1.9.9e, since it just confuses things.
+ */
+#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
+#define OLD_NCURSES 1
+#undef wbkgdset
+#define wbkgdset(w,p) /*nothing*/
+#else
+#define OLD_NCURSES 0
+#endif
+
+#define TR(params) _tracef params
+
+#define ESC 27
+#define TAB 9
+#define MAX_LEN 2048
+#define BUF_SIZE (10*1024)
+#define MIN(x,y) (x < y ? x : y)
+#define MAX(x,y) (x > y ? x : y)
+
+
+#ifndef ACS_ULCORNER
+#define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#define ACS_URCORNER '+'
+#endif
+#ifndef ACS_LRCORNER
+#define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#define ACS_VLINE '|'
+#endif
+#ifndef ACS_LTEE
+#define ACS_LTEE '+'
+#endif
+#ifndef ACS_RTEE
+#define ACS_RTEE '+'
+#endif
+#ifndef ACS_UARROW
+#define ACS_UARROW '^'
+#endif
+#ifndef ACS_DARROW
+#define ACS_DARROW 'v'
+#endif
+
+/*
+ * Attribute names
+ */
+#define screen_attr attributes[0]
+#define shadow_attr attributes[1]
+#define dialog_attr attributes[2]
+#define title_attr attributes[3]
+#define border_attr attributes[4]
+#define button_active_attr attributes[5]
+#define button_inactive_attr attributes[6]
+#define button_key_active_attr attributes[7]
+#define button_key_inactive_attr attributes[8]
+#define button_label_active_attr attributes[9]
+#define button_label_inactive_attr attributes[10]
+#define inputbox_attr attributes[11]
+#define inputbox_border_attr attributes[12]
+#define searchbox_attr attributes[13]
+#define searchbox_title_attr attributes[14]
+#define searchbox_border_attr attributes[15]
+#define position_indicator_attr attributes[16]
+#define menubox_attr attributes[17]
+#define menubox_border_attr attributes[18]
+#define item_attr attributes[19]
+#define item_selected_attr attributes[20]
+#define tag_attr attributes[21]
+#define tag_selected_attr attributes[22]
+#define tag_key_attr attributes[23]
+#define tag_key_selected_attr attributes[24]
+#define check_attr attributes[25]
+#define check_selected_attr attributes[26]
+#define uarrow_attr attributes[27]
+#define darrow_attr attributes[28]
+
+/* number of attributes */
+#define ATTRIBUTE_COUNT 29
+
+/*
+ * Global variables
+ */
+extern bool use_colors;
+extern bool use_shadow;
+
+extern chtype attributes[];
+
+extern const char *backtitle;
+
+/*
+ * Function prototypes
+ */
+extern void create_rc (const char *filename);
+extern int parse_rc (void);
+
+
+void init_dialog (void);
+void end_dialog (void);
+void attr_clear (WINDOW * win, int height, int width, chtype attr);
+void dialog_clear (void);
+void color_setup (void);
+void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
+void print_button (WINDOW * win, const char *label, int y, int x, int selected);
+void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
+ chtype border);
+void draw_shadow (WINDOW * win, int y, int x, int height, int width);
+
+int first_alpha (const char *string, const char *exempt);
+int dialog_yesno (const char *title, const char *prompt, int height, int width);
+int dialog_msgbox (const char *title, const char *prompt, int height,
+ int width, int pause);
+int dialog_textbox (const char *title, const char *file, int height, int width);
+int dialog_menu (const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *choice, int item_no,
+ const char * const * items);
+int dialog_checklist (const char *title, const char *prompt, int height,
+ int width, int list_height, int item_no,
+ const char * const * items, int flag);
+extern unsigned char dialog_input_result[];
+int dialog_inputbox (const char *title, const char *prompt, int height,
+ int width, const char *init);
+
+/*
+ * This is the base for fictitious keys, which activate
+ * the buttons.
+ *
+ * Mouse-generated keys are the following:
+ * -- the first 32 are used as numbers, in addition to '0'-'9'
+ * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
+ * -- uppercase chars are used to invoke the button (M_EVENT + 'O')
+ */
+#define M_EVENT (KEY_MAX+1)
+
+
+/*
+ * The `flag' parameter in checklist is used to select between
+ * radiolist and checklist
+ */
+#define FLAG_CHECK 1
+#define FLAG_RADIO 0
diff --git a/scripts/lxdialog/inputbox.c b/scripts/lxdialog/inputbox.c
new file mode 100644
index 000000000000..fa7bebc693b9
--- /dev/null
+++ b/scripts/lxdialog/inputbox.c
@@ -0,0 +1,240 @@
+/*
+ * inputbox.c -- implements the input box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+unsigned char dialog_input_result[MAX_LEN + 1];
+
+/*
+ * Print the termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button (dialog, " Ok ", y, x, selected==0);
+ print_button (dialog, " Help ", y, x + 14, selected==1);
+
+ wmove(dialog, y, x+1+14*selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int
+dialog_inputbox (const char *title, const char *prompt, int height, int width,
+ const char *init)
+{
+ int i, x, y, box_y, box_x, box_width;
+ int input_x = 0, scroll = 0, key = 0, button = -1;
+ unsigned char *instr = dialog_input_result;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ /* Draw the input field box */
+ box_width = width - 6;
+ getyx (dialog, y, x);
+ box_y = y + 2;
+ box_x = (width - box_width) / 2;
+ draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
+ border_attr, dialog_attr);
+
+ print_buttons(dialog, height, width, 0);
+
+ /* Set up the initial value */
+ wmove (dialog, box_y, box_x);
+ wattrset (dialog, inputbox_attr);
+
+ if (!init)
+ instr[0] = '\0';
+ else
+ strcpy (instr, init);
+
+ input_x = strlen (instr);
+
+ if (input_x >= box_width) {
+ scroll = input_x - box_width + 1;
+ input_x = box_width - 1;
+ for (i = 0; i < box_width - 1; i++)
+ waddch (dialog, instr[scroll + i]);
+ } else
+ waddstr (dialog, instr);
+
+ wmove (dialog, box_y, box_x + input_x);
+
+ wrefresh (dialog);
+
+ while (key != ESC) {
+ key = wgetch (dialog);
+
+ if (button == -1) { /* Input box selected */
+ switch (key) {
+ case TAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ break;
+ case KEY_LEFT:
+ continue;
+ case KEY_RIGHT:
+ continue;
+ case KEY_BACKSPACE:
+ case 127:
+ if (input_x || scroll) {
+ wattrset (dialog, inputbox_attr);
+ if (!input_x) {
+ scroll = scroll < box_width - 1 ?
+ 0 : scroll - (box_width - 1);
+ wmove (dialog, box_y, box_x);
+ for (i = 0; i < box_width; i++)
+ waddch (dialog, instr[scroll + input_x + i] ?
+ instr[scroll + input_x + i] : ' ');
+ input_x = strlen (instr) - scroll;
+ } else
+ input_x--;
+ instr[scroll + input_x] = '\0';
+ mvwaddch (dialog, box_y, input_x + box_x, ' ');
+ wmove (dialog, box_y, input_x + box_x);
+ wrefresh (dialog);
+ }
+ continue;
+ default:
+ if (key < 0x100 && isprint (key)) {
+ if (scroll + input_x < MAX_LEN) {
+ wattrset (dialog, inputbox_attr);
+ instr[scroll + input_x] = key;
+ instr[scroll + input_x + 1] = '\0';
+ if (input_x == box_width - 1) {
+ scroll++;
+ wmove (dialog, box_y, box_x);
+ for (i = 0; i < box_width - 1; i++)
+ waddch (dialog, instr[scroll + i]);
+ } else {
+ wmove (dialog, box_y, input_x++ + box_x);
+ waddch (dialog, key);
+ }
+ wrefresh (dialog);
+ } else
+ flash (); /* Alarm user about overflow */
+ continue;
+ }
+ }
+ }
+ switch (key) {
+ case 'O':
+ case 'o':
+ delwin (dialog);
+ return 0;
+ case 'H':
+ case 'h':
+ delwin (dialog);
+ return 1;
+ case KEY_UP:
+ case KEY_LEFT:
+ switch (button) {
+ case -1:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 0:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove (dialog, box_y, box_x + input_x);
+ wrefresh (dialog);
+ break;
+ case 1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ }
+ break;
+ case TAB:
+ case KEY_DOWN:
+ case KEY_RIGHT:
+ switch (button) {
+ case -1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ case 0:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 1:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove (dialog, box_y, box_x + input_x);
+ wrefresh (dialog);
+ break;
+ }
+ break;
+ case ' ':
+ case '\n':
+ delwin (dialog);
+ return (button == -1 ? 0 : button);
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c
new file mode 100644
index 000000000000..6f4c1fd4eba5
--- /dev/null
+++ b/scripts/lxdialog/lxdialog.c
@@ -0,0 +1,226 @@
+/*
+ * dialog - Display simple dialog boxes from shell scripts
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void Usage (const char *name);
+
+typedef int (jumperFn) (const char *title, int argc, const char * const * argv);
+
+struct Mode {
+ char *name;
+ int argmin, argmax, argmod;
+ jumperFn *jumper;
+};
+
+jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox;
+jumperFn j_msgbox, j_infobox;
+
+static struct Mode modes[] =
+{
+ {"--menu", 9, 0, 3, j_menu},
+ {"--checklist", 9, 0, 3, j_checklist},
+ {"--radiolist", 9, 0, 3, j_radiolist},
+ {"--yesno", 5,5,1, j_yesno},
+ {"--textbox", 5,5,1, j_textbox},
+ {"--inputbox", 5, 6, 1, j_inputbox},
+ {"--msgbox", 5, 5, 1, j_msgbox},
+ {"--infobox", 5, 5, 1, j_infobox},
+ {NULL, 0, 0, 0, NULL}
+};
+
+static struct Mode *modePtr;
+
+#ifdef LOCALE
+#include <locale.h>
+#endif
+
+int
+main (int argc, const char * const * argv)
+{
+ int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
+ const char *title = NULL;
+
+#ifdef LOCALE
+ (void) setlocale (LC_ALL, "");
+#endif
+
+#ifdef TRACE
+ trace(TRACE_CALLS|TRACE_UPDATE);
+#endif
+ if (argc < 2) {
+ Usage (argv[0]);
+ exit (-1);
+ }
+
+ while (offset < argc - 1 && !end_common_opts) { /* Common options */
+ if (!strcmp (argv[offset + 1], "--title")) {
+ if (argc - offset < 3 || title != NULL) {
+ Usage (argv[0]);
+ exit (-1);
+ } else {
+ title = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp (argv[offset + 1], "--backtitle")) {
+ if (backtitle != NULL) {
+ Usage (argv[0]);
+ exit (-1);
+ } else {
+ backtitle = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp (argv[offset + 1], "--clear")) {
+ if (clear_screen) { /* Hey, "--clear" can't appear twice! */
+ Usage (argv[0]);
+ exit (-1);
+ } else if (argc == 2) { /* we only want to clear the screen */
+ init_dialog ();
+ refresh (); /* init_dialog() will clear the screen for us */
+ end_dialog ();
+ return 0;
+ } else {
+ clear_screen = 1;
+ offset++;
+ }
+ } else /* no more common options */
+ end_common_opts = 1;
+ }
+
+ if (argc - 1 == offset) { /* no more options */
+ Usage (argv[0]);
+ exit (-1);
+ }
+ /* use a table to look for the requested mode, to avoid code duplication */
+
+ for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
+ if (!strcmp (argv[offset + 1], modePtr->name))
+ break;
+
+ if (!modePtr->name)
+ Usage (argv[0]);
+ if (argc - offset < modePtr->argmin)
+ Usage (argv[0]);
+ if (modePtr->argmax && argc - offset > modePtr->argmax)
+ Usage (argv[0]);
+
+
+
+ init_dialog ();
+ retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
+
+ if (clear_screen) { /* clear screen before exit */
+ attr_clear (stdscr, LINES, COLS, screen_attr);
+ refresh ();
+ }
+ end_dialog();
+
+ exit (retval);
+}
+
+/*
+ * Print program usage
+ */
+static void
+Usage (const char *name)
+{
+ fprintf (stderr, "\
+\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
+\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
+\n modified/gutted for use as a Linux kernel config tool by \
+\n William Roadcap (roadcapw@cfw.com)\
+\n\
+\n* Display dialog boxes from shell scripts *\
+\n\
+\nUsage: %s --clear\
+\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
+\n\
+\nBox options:\
+\n\
+\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
+\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --textbox <file> <height> <width>\
+\n --inputbox <text> <height> <width> [<init>]\
+\n --yesno <text> <height> <width>\
+\n", name, name);
+ exit (-1);
+}
+
+/*
+ * These are the program jumpers
+ */
+
+int
+j_menu (const char *t, int ac, const char * const * av)
+{
+ return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), av[6], (ac - 6) / 2, av + 7);
+}
+
+int
+j_checklist (const char *t, int ac, const char * const * av)
+{
+ return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK);
+}
+
+int
+j_radiolist (const char *t, int ac, const char * const * av)
+{
+ return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
+ atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO);
+}
+
+int
+j_textbox (const char *t, int ac, const char * const * av)
+{
+ return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4]));
+}
+
+int
+j_yesno (const char *t, int ac, const char * const * av)
+{
+ return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4]));
+}
+
+int
+j_inputbox (const char *t, int ac, const char * const * av)
+{
+ int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]),
+ ac == 6 ? av[5] : (char *) NULL);
+ if (ret == 0)
+ fprintf(stderr, dialog_input_result);
+ return ret;
+}
+
+int
+j_msgbox (const char *t, int ac, const char * const * av)
+{
+ return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1);
+}
+
+int
+j_infobox (const char *t, int ac, const char * const * av)
+{
+ return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0);
+}
+
diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c
new file mode 100644
index 000000000000..d6dc07d4046b
--- /dev/null
+++ b/scripts/lxdialog/menubox.c
@@ -0,0 +1,437 @@
+/*
+ * menubox.c -- implements the menu box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Changes by Clifford Wolf (god@clifford.at)
+ *
+ * [ 1998-06-13 ]
+ *
+ * *) A bugfix for the Page-Down problem
+ *
+ * *) Formerly when I used Page Down and Page Up, the cursor would be set
+ * to the first position in the menu box. Now lxdialog is a bit
+ * smarter and works more like other menu systems (just have a look at
+ * it).
+ *
+ * *) Formerly if I selected something my scrolling would be broken because
+ * lxdialog is re-invoked by the Menuconfig shell script, can't
+ * remember the last scrolling position, and just sets it so that the
+ * cursor is at the bottom of the box. Now it writes the temporary file
+ * lxdialog.scrltmp which contains this information. The file is
+ * deleted by lxdialog if the user leaves a submenu or enters a new
+ * one, but it would be nice if Menuconfig could make another "rm -f"
+ * just to be sure. Just try it out - you will recognise a difference!
+ *
+ * [ 1998-06-14 ]
+ *
+ * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
+ * and menus change their size on the fly.
+ *
+ * *) If for some reason the last scrolling position is not saved by
+ * lxdialog, it sets the scrolling so that the selected item is in the
+ * middle of the menu box, not at the bottom.
+ *
+ * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
+ * fscanf would read in 'scroll', and eventually that value would get used.
+ */
+
+#include "dialog.h"
+
+static int menu_width, item_x;
+
+/*
+ * Print menu item
+ */
+static void
+print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
+{
+ int j;
+ char menu_item[menu_width+1];
+
+ strncpy(menu_item, item, menu_width);
+ menu_item[menu_width] = 0;
+ j = first_alpha(menu_item, "YyNnMm");
+
+ /* Clear 'residue' of last item */
+ wattrset (win, menubox_attr);
+ wmove (win, choice, 0);
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < menu_width; i++)
+ waddch (win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+ wattrset (win, selected ? item_selected_attr : item_attr);
+ mvwaddstr (win, choice, item_x, menu_item);
+ if (hotkey) {
+ wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
+ mvwaddch(win, choice, item_x+j, menu_item[j]);
+ }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void
+print_arrows (WINDOW * win, int item_no, int scroll,
+ int y, int x, int height)
+{
+ int cur_y, cur_x;
+
+ getyx(win, cur_y, cur_x);
+
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset (win, uarrow_attr);
+ waddch (win, ACS_UARROW);
+ waddstr (win, "(-)");
+ }
+ else {
+ wattrset (win, menubox_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+
+ if ((height < item_no) && (scroll + height < item_no)) {
+ wattrset (win, darrow_attr);
+ waddch (win, ACS_DARROW);
+ waddstr (win, "(+)");
+ }
+ else {
+ wattrset (win, menubox_border_attr);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ waddch (win, ACS_HLINE);
+ }
+
+ wmove(win, cur_y, cur_x);
+}
+
+/*
+ * Display the termination buttons.
+ */
+static void
+print_buttons (WINDOW *win, int height, int width, int selected)
+{
+ int x = width / 2 - 16;
+ int y = height - 2;
+
+ print_button (win, "Select", y, x, selected == 0);
+ print_button (win, " Exit ", y, x + 12, selected == 1);
+ print_button (win, " Help ", y, x + 24, selected == 2);
+
+ wmove(win, y, x+1+12*selected);
+ wrefresh (win);
+}
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int
+dialog_menu (const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *current, int item_no,
+ const char * const * items)
+
+{
+ int i, j, x, y, box_x, box_y;
+ int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
+ WINDOW *dialog, *menu;
+ FILE *f;
+
+ max_choice = MIN (menu_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ wbkgdset (dialog, dialog_attr & A_COLOR);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ menu_width = width - 6;
+ box_y = height - menu_height - 5;
+ box_x = (width - menu_width) / 2 - 1;
+
+ /* create new window for the menu */
+ menu = subwin (dialog, menu_height, menu_width,
+ y + box_y + 1, x + box_x + 1);
+ keypad (menu, TRUE);
+
+ /* draw a box around the menu items */
+ draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /*
+ * Find length of longest item in order to center menu.
+ * Set 'choice' to default item.
+ */
+ item_x = 0;
+ for (i = 0; i < item_no; i++) {
+ item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2));
+ if (strcmp(current, items[i*2]) == 0) choice = i;
+ }
+
+ item_x = (menu_width - item_x) / 2;
+
+ /* get the scroll info from the temp file */
+ if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
+ if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
+ (scroll+max_choice > choice) && (scroll >= 0) &&
+ (scroll+max_choice <= item_no) ) {
+ first_item = scroll;
+ choice = choice - scroll;
+ fclose(f);
+ } else {
+ scroll=0;
+ remove("lxdialog.scrltmp");
+ fclose(f);
+ f=NULL;
+ }
+ }
+ if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
+ if (choice >= item_no-max_choice/2)
+ scroll = first_item = item_no-max_choice;
+ else
+ scroll = first_item = choice - max_choice/2;
+ choice = choice - scroll;
+ }
+
+ /* Print the menu */
+ for (i=0; i < max_choice; i++) {
+ print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice,
+ (items[(first_item + i)*2][0] != ':'));
+ }
+
+ wnoutrefresh (menu);
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x+item_x+1, menu_height);
+
+ print_buttons (dialog, height, width, 0);
+
+ 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); i++) {
+ if (scroll > 0) {
+ wscrl (menu, -1);
+ scroll--;
+ print_item (menu, items[scroll * 2 + 1], 0, FALSE,
+ (items[scroll*2][0] != ':'));
+ } else {
+ if (choice > 0)
+ choice--;
+ }
+ }
+ scrollok (menu, FALSE);
+
+ } else if (key == KEY_NPAGE) {
+ for (i=0; (i < max_choice); i++) {
+ if (scroll+max_choice < item_no) {
+ scrollok (menu, TRUE);
+ scroll(menu);
+ scrollok (menu, FALSE);
+ scroll++;
+ print_item (menu, items[(scroll+max_choice-1)*2+1],
+ max_choice-1, FALSE,
+ (items[(scroll+max_choice-1)*2][0] != ':'));
+ } else {
+ if (choice+1 < max_choice)
+ choice++;
+ }
+ }
+
+ } else
+ choice = i;
+
+ print_item (menu, items[(scroll+choice)*2+1], choice, TRUE,
+ (items[(scroll+choice)*2][0] != ':'));
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x+item_x+1, menu_height);
+
+ wnoutrefresh (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':
+ /* save scroll info */
+ if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
+ fprintf(f,"%d\n",scroll);
+ fclose(f);
+ }
+ delwin (dialog);
+ fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+ switch (key) {
+ case 's': return 3;
+ case 'y': return 3;
+ case 'n': return 4;
+ case 'm': return 5;
+ case ' ': return 6;
+ }
+ return 0;
+ case 'h':
+ case '?':
+ button = 2;
+ case '\n':
+ delwin (dialog);
+ if (button == 2)
+ fprintf(stderr, "%s \"%s\"\n",
+ items[(scroll + choice) * 2],
+ items[(scroll + choice) * 2 + 1] +
+ first_alpha(items[(scroll + choice) * 2 + 1],""));
+ else
+ fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+
+ remove("lxdialog.scrltmp");
+ return button;
+ case 'e':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ remove("lxdialog.scrltmp");
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/msgbox.c b/scripts/lxdialog/msgbox.c
new file mode 100644
index 000000000000..93692e1fbcc2
--- /dev/null
+++ b/scripts/lxdialog/msgbox.c
@@ -0,0 +1,85 @@
+/*
+ * msgbox.c -- implements the message box and info box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display a message box. Program will pause and display an "OK" button
+ * if the parameter 'pause' is non-zero.
+ */
+int
+dialog_msgbox (const char *title, const char *prompt, int height, int width,
+ int pause)
+{
+ int i, x, y, key = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 2);
+
+ if (pause) {
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ print_button (dialog, " Ok ",
+ height - 2, width / 2 - 4, TRUE);
+
+ wrefresh (dialog);
+ while (key != ESC && key != '\n' && key != ' ' &&
+ key != 'O' && key != 'o' && key != 'X' && key != 'x')
+ key = wgetch (dialog);
+ } else {
+ key = '\n';
+ wrefresh (dialog);
+ }
+
+ delwin (dialog);
+ return key == ESC ? -1 : 0;
+}
diff --git a/scripts/lxdialog/textbox.c b/scripts/lxdialog/textbox.c
new file mode 100644
index 000000000000..ecf55410e2d6
--- /dev/null
+++ b/scripts/lxdialog/textbox.c
@@ -0,0 +1,556 @@
+/*
+ * textbox.c -- implements the text box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+static void back_lines (int n);
+static void print_page (WINDOW * win, int height, int width);
+static void print_line (WINDOW * win, int row, int width);
+static char *get_line (void);
+static void print_position (WINDOW * win, int height, int width);
+
+static int hscroll = 0, fd, file_size, bytes_read;
+static int begin_reached = 1, end_reached = 0, page_length;
+static char *buf, *page;
+
+/*
+ * Display text from a file in a dialog box.
+ */
+int
+dialog_textbox (const char *title, const char *file, int height, int width)
+{
+ int i, x, y, cur_x, cur_y, fpos, key = 0;
+ int passed_end;
+ char search_term[MAX_LEN + 1];
+ WINDOW *dialog, *text;
+
+ search_term[0] = '\0'; /* no search term entered yet */
+
+ /* Open input file for reading */
+ if ((fd = open (file, O_RDONLY)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nCan't open input file in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Get file size. Actually, 'file_size' is the real file size - 1,
+ since it's only the last byte offset from the beginning */
+ if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Restore file pointer to beginning of file after getting file size */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ /* Allocate space for read buffer */
+ if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
+ endwin ();
+ fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0'; /* mark end of valid data */
+ page = buf; /* page is pointer to start of page to be displayed */
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ /* Create window for text region, used for scrolling text */
+ text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
+ wattrset (text, dialog_attr);
+ wbkgdset (text, dialog_attr & A_COLOR);
+
+ keypad (text, TRUE);
+
+ /* register the new window, along with its borders */
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ wbkgdset (dialog, dialog_attr & A_COLOR);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+ print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
+ wnoutrefresh (dialog);
+ getyx (dialog, cur_y, cur_x); /* Save cursor position */
+
+ /* Print first page of text */
+ attr_clear (text, height - 4, width - 2, dialog_attr);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+
+ while ((key != ESC) && (key != '\n')) {
+ key = wgetch (dialog);
+ switch (key) {
+ case 'E': /* Exit */
+ case 'e':
+ case 'X':
+ case 'x':
+ delwin (dialog);
+ free (buf);
+ close (fd);
+ return 0;
+ case 'g': /* First page */
+ case KEY_HOME:
+ if (!begin_reached) {
+ begin_reached = 1;
+ /* First page not in buffer? */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) { /* Yes, we have to read it in */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf;
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case 'G': /* Last page */
+ case KEY_END:
+
+ end_reached = 1;
+ /* Last page not in buffer? */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if (fpos < file_size) { /* Yes, we have to read it in */
+ if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in dialog_textbox().\n");
+ exit (-1);
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError reading file in dialog_textbox().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf + bytes_read;
+ back_lines (height - 4);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ break;
+ case 'K': /* Previous line */
+ case 'k':
+ case KEY_UP:
+ if (!begin_reached) {
+ back_lines (page_length + 1);
+
+ /* We don't call print_page() here but use scrolling to ensure
+ faster screen update. However, 'end_reached' and
+ 'page_length' should still be updated, and 'page' should
+ point to start of next page. This is done by calling
+ get_line() in the following 'for' loop. */
+ scrollok (text, TRUE);
+ wscrl (text, -1); /* Scroll text region down one line */
+ scrollok (text, FALSE);
+ page_length = 0;
+ passed_end = 0;
+ for (i = 0; i < height - 4; i++) {
+ if (!i) {
+ /* print first line of page */
+ print_line (text, 0, width - 2);
+ wnoutrefresh (text);
+ } else
+ /* Called to update 'end_reached' and 'page' */
+ get_line ();
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case 'B': /* Previous page */
+ case 'b':
+ case KEY_PPAGE:
+ if (begin_reached)
+ break;
+ back_lines (page_length + height - 4);
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case 'J': /* Next line */
+ case 'j':
+ case KEY_DOWN:
+ if (!end_reached) {
+ begin_reached = 0;
+ scrollok (text, TRUE);
+ scroll (text); /* Scroll text region up one line */
+ scrollok (text, FALSE);
+ print_line (text, height - 5, width - 2);
+ wnoutrefresh (text);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh (dialog);
+ }
+ break;
+ case KEY_NPAGE: /* Next page */
+ case ' ':
+ if (end_reached)
+ break;
+
+ begin_reached = 0;
+ print_page (text, height - 4, width - 2);
+ print_position (dialog, height, width);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case '0': /* Beginning of line */
+ case 'H': /* Scroll left */
+ case 'h':
+ case KEY_LEFT:
+ if (hscroll <= 0)
+ break;
+
+ if (key == '0')
+ hscroll = 0;
+ else
+ hscroll--;
+ /* Reprint current page to scroll horizontally */
+ back_lines (page_length);
+ print_page (text, height - 4, width - 2);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case 'L': /* Scroll right */
+ case 'l':
+ case KEY_RIGHT:
+ if (hscroll >= MAX_LEN)
+ break;
+ hscroll++;
+ /* Reprint current page to scroll horizontally */
+ back_lines (page_length);
+ print_page (text, height - 4, width - 2);
+ wmove (dialog, cur_y, cur_x);
+ wrefresh (dialog);
+ break;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ free (buf);
+ close (fd);
+ return -1; /* ESC pressed */
+}
+
+/*
+ * Go back 'n' lines in text file. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void
+back_lines (int n)
+{
+ int i, fpos;
+
+ begin_reached = 0;
+ /* We have to distinguish between end_reached and !end_reached
+ since at end of file, the line is not ended by a '\n'.
+ The code inside 'if' basically does a '--page' to move one
+ character backward so as to skip '\n' of the previous line */
+ if (!end_reached) {
+ /* Either beginning of buffer or beginning of file reached? */
+ if (page == buf) {
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) { /* Not beginning of file yet */
+ /* We've reached beginning of buffer, but not beginning of
+ file yet, so read previous part of file into buffer.
+ Note that we only move backward for BUF_SIZE/2 bytes,
+ but not BUF_SIZE bytes to avoid re-reading again in
+ print_page() later */
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
+ == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in back_lines().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ if (*(--page) != '\n') { /* '--page' here */
+ /* Something's wrong... */
+ endwin ();
+ fprintf (stderr, "\nInternal error in back_lines().\n");
+ exit (-1);
+ }
+ }
+ /* Go back 'n' lines */
+ for (i = 0; i < n; i++)
+ do {
+ if (page == buf) {
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr,
+ "\nError moving file pointer in back_lines().\n");
+ exit (-1);
+ }
+ if (fpos > bytes_read) {
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek (fd, 0, SEEK_SET) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
+ SEEK_CUR) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer"
+ " in back_lines().\n");
+ exit (-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in "
+ "back_lines().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ } while (*(--page) != '\n');
+ page++;
+}
+
+/*
+ * Print a new page of text. Called by dialog_textbox().
+ */
+static void
+print_page (WINDOW * win, int height, int width)
+{
+ int i, passed_end = 0;
+
+ page_length = 0;
+ for (i = 0; i < height; i++) {
+ print_line (win, i, width);
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+ wnoutrefresh (win);
+}
+
+/*
+ * Print a new line of text. Called by dialog_textbox() and print_page().
+ */
+static void
+print_line (WINDOW * win, int row, int width)
+{
+ int y, x;
+ char *line;
+
+ line = get_line ();
+ line += MIN (strlen (line), hscroll); /* Scroll horizontally */
+ wmove (win, row, 0); /* move cursor to correct line */
+ waddch (win, ' ');
+ waddnstr (win, line, MIN (strlen (line), width - 2));
+
+ getyx (win, y, x);
+ /* Clear 'residue' of previous line */
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < width - x; i++)
+ waddch (win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *
+get_line (void)
+{
+ int i = 0, fpos;
+ static char line[MAX_LEN + 1];
+
+ end_reached = 0;
+ while (*page != '\n') {
+ if (*page == '\0') {
+ /* Either end of file or end of buffer reached */
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in "
+ "get_line().\n");
+ exit (-1);
+ }
+ if (fpos < file_size) { /* Not end of file yet */
+ /* We've reached end of buffer, but not end of file yet,
+ so read next part of file into buffer */
+ if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError reading file in get_line().\n");
+ exit (-1);
+ }
+ buf[bytes_read] = '\0';
+ page = buf;
+ } else {
+ if (!end_reached)
+ end_reached = 1;
+ break;
+ }
+ } else if (i < MAX_LEN)
+ line[i++] = *(page++);
+ else {
+ /* Truncate lines longer than MAX_LEN characters */
+ if (i == MAX_LEN)
+ line[i++] = '\0';
+ page++;
+ }
+ }
+ if (i <= MAX_LEN)
+ line[i] = '\0';
+ if (!end_reached)
+ page++; /* move pass '\n' */
+
+ return line;
+}
+
+/*
+ * Print current position
+ */
+static void
+print_position (WINDOW * win, int height, int width)
+{
+ int fpos, percent;
+
+ if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
+ endwin ();
+ fprintf (stderr, "\nError moving file pointer in print_position().\n");
+ exit (-1);
+ }
+ wattrset (win, position_indicator_attr);
+ wbkgdset (win, position_indicator_attr & A_COLOR);
+ percent = !file_size ?
+ 100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
+ wmove (win, height - 3, width - 9);
+ wprintw (win, "(%3d%%)", percent);
+}
diff --git a/scripts/lxdialog/util.c b/scripts/lxdialog/util.c
new file mode 100644
index 000000000000..b3a7af9d2dda
--- /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 000000000000..11fcc25f5159
--- /dev/null
+++ b/scripts/lxdialog/yesno.c
@@ -0,0 +1,118 @@
+/*
+ * yesno.c -- implements the yes/no box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "dialog.h"
+
+/*
+ * Display termination buttons
+ */
+static void
+print_buttons(WINDOW *dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 10;
+ int y = height - 2;
+
+ print_button (dialog, " Yes ", y, x, selected == 0);
+ print_button (dialog, " No ", y, x + 13, selected == 1);
+
+ wmove(dialog, y, x+1 + 13*selected );
+ wrefresh (dialog);
+}
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int
+dialog_yesno (const char *title, const char *prompt, int height, int width)
+{
+ int i, x, y, key = 0, button = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow (stdscr, y, x, height, width);
+
+ dialog = newwin (height, width, y, x);
+ keypad (dialog, TRUE);
+
+ draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset (dialog, border_attr);
+ mvwaddch (dialog, height-3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch (dialog, ACS_HLINE);
+ wattrset (dialog, dialog_attr);
+ waddch (dialog, ACS_RTEE);
+
+ if (title != NULL && strlen(title) >= width-2 ) {
+ /* truncate long title -- mec */
+ char * title2 = malloc(width-2+1);
+ memcpy( title2, title, width-2 );
+ title2[width-2] = '\0';
+ title = title2;
+ }
+
+ if (title != NULL) {
+ wattrset (dialog, title_attr);
+ mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
+ waddstr (dialog, (char *)title);
+ waddch (dialog, ' ');
+ }
+
+ wattrset (dialog, dialog_attr);
+ print_autowrap (dialog, prompt, width - 2, 1, 3);
+
+ print_buttons(dialog, height, width, 0);
+
+ while (key != ESC) {
+ key = wgetch (dialog);
+ switch (key) {
+ case 'Y':
+ case 'y':
+ delwin (dialog);
+ return 0;
+ case 'N':
+ case 'n':
+ delwin (dialog);
+ return 1;
+
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh (dialog);
+ break;
+ case ' ':
+ case '\n':
+ delwin (dialog);
+ return button;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin (dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/makelst b/scripts/makelst
new file mode 100644
index 000000000000..f341229df566
--- /dev/null
+++ b/scripts/makelst
@@ -0,0 +1,21 @@
+#!/bin/bash
+# A script to dump mixed source code & assembly
+# with correct relocations from System.map
+# Requires the following lines in Rules.make.
+#
+#%.lst: %.c
+# $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $<
+# $(TOPDIR)/scripts/makelst $* $(TOPDIR) $(OBJDUMP)
+#
+# Copyright (C) 2000 IBM Corporation
+# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+#
+
+t1=`$3 --syms $2/$1.o | grep .text | grep " F " | head -n 1`
+t2=`echo $t1 | gawk '{ print $6 }'`
+t3=`grep $t2 $2/System.map`
+t4=`echo $t3 | gawk '{ print $1 }'`
+t5=`echo $t1 | gawk '{ print $1 }'`
+t6=`echo $t4 - $t5 | sed s/a/A/g | sed s/b/B/g | sed s/c/C/g | sed s/d/D/g | sed s/e/E/g | sed s/f/F/g`
+t7=`( echo ibase=16 ; echo $t6 ) | bc`
+$3 --source --adjust-vma=$t7 $2/$1.o > $2/$1.lst
diff --git a/scripts/mkdep.c b/scripts/mkdep.c
new file mode 100644
index 000000000000..4c0e7521d42e
--- /dev/null
+++ b/scripts/mkdep.c
@@ -0,0 +1,562 @@
+/*
+ * Originally by Linus Torvalds.
+ * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain.
+ *
+ * Usage: mkdep file ...
+ *
+ * Read source files and output makefile dependency lines for them.
+ * I make simple dependency lines for #include <*.h> and #include "*.h".
+ * I also find instances of CONFIG_FOO and generate dependencies
+ * like include/config/foo.h.
+ *
+ * 1 August 1999, Michael Elizabeth Chastain, <mec@shout.net>
+ * - Keith Owens reported a bug in smart config processing. There used
+ * to be an optimization for "#define CONFIG_FOO ... #ifdef CONFIG_FOO",
+ * so that the file would not depend on CONFIG_FOO because the file defines
+ * this symbol itself. But this optimization is bogus! Consider this code:
+ * "#if 0 \n #define CONFIG_FOO \n #endif ... #ifdef CONFIG_FOO". Here
+ * the definition is inactivated, but I still used it. It turns out this
+ * actually happens a few times in the kernel source. The simple way to
+ * fix this problem is to remove this particular optimization.
+ *
+ * 2.3.99-pre1, Andrew Morton <andrewm@uow.edu.au>
+ * - Changed so that 'filename.o' depends upon 'filename.[cS]'. This is so that
+ * missing source files are noticed, rather than silently ignored.
+ */
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+
+
+char __depname[512] = "\n\t@touch ";
+#define depname (__depname+9)
+int hasdep;
+
+struct path_struct {
+ int len;
+ char buffer[256-sizeof(int)];
+} path_array[2] = {
+ { 0, "" },
+ { 0, "" }
+};
+
+
+/* Current input file */
+static const char *g_filename;
+
+/*
+ * This records all the configuration options seen.
+ * In perl this would be a hash, but here it's a long string
+ * of values separated by newlines. This is simple and
+ * extremely fast.
+ */
+char * str_config = NULL;
+int size_config = 0;
+int len_config = 0;
+
+static void
+do_depname(void)
+{
+ if (!hasdep) {
+ hasdep = 1;
+ printf("%s:", depname);
+ if (g_filename)
+ printf(" %s", g_filename);
+ }
+}
+
+/*
+ * Grow the configuration string to a desired length.
+ * Usually the first growth is plenty.
+ */
+void grow_config(int len)
+{
+ while (len_config + len > size_config) {
+ if (size_config == 0)
+ size_config = 2048;
+ str_config = realloc(str_config, size_config *= 2);
+ if (str_config == NULL)
+ { perror("malloc config"); exit(1); }
+ }
+}
+
+
+
+/*
+ * Lookup a value in the configuration string.
+ */
+int is_defined_config(const char * name, int len)
+{
+ const char * pconfig;
+ const char * plast = str_config + len_config - len;
+ for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
+ if (pconfig[ -1] == '\n'
+ && pconfig[len] == '\n'
+ && !memcmp(pconfig, name, len))
+ return 1;
+ }
+ return 0;
+}
+
+
+
+/*
+ * Add a new value to the configuration string.
+ */
+void define_config(const char * name, int len)
+{
+ grow_config(len + 1);
+
+ memcpy(str_config+len_config, name, len);
+ len_config += len;
+ str_config[len_config++] = '\n';
+}
+
+
+
+/*
+ * Clear the set of configuration strings.
+ */
+void clear_config(void)
+{
+ len_config = 0;
+ define_config("", 0);
+}
+
+
+
+/*
+ * This records all the precious .h filenames. No need for a hash,
+ * it's a long string of values enclosed in tab and newline.
+ */
+char * str_precious = NULL;
+int size_precious = 0;
+int len_precious = 0;
+
+
+
+/*
+ * Grow the precious string to a desired length.
+ * Usually the first growth is plenty.
+ */
+void grow_precious(int len)
+{
+ while (len_precious + len > size_precious) {
+ if (size_precious == 0)
+ size_precious = 2048;
+ str_precious = realloc(str_precious, size_precious *= 2);
+ if (str_precious == NULL)
+ { perror("malloc"); exit(1); }
+ }
+}
+
+
+
+/*
+ * Add a new value to the precious string.
+ */
+void define_precious(const char * filename)
+{
+ int len = strlen(filename);
+ grow_precious(len + 4);
+ *(str_precious+len_precious++) = '\t';
+ memcpy(str_precious+len_precious, filename, len);
+ len_precious += len;
+ memcpy(str_precious+len_precious, " \\\n", 3);
+ len_precious += 3;
+}
+
+
+
+/*
+ * Handle an #include line.
+ */
+void handle_include(int type, const char * name, int len)
+{
+ struct path_struct *path = path_array+type;
+
+ if (len == 14 && !memcmp(name, "linux/config.h", len))
+ return;
+
+ if (len >= 7 && !memcmp(name, "config/", 7))
+ define_config(name+7, len-7-2);
+
+ memcpy(path->buffer+path->len, name, len);
+ path->buffer[path->len+len] = '\0';
+ if (access(path->buffer, F_OK) != 0)
+ return;
+
+ do_depname();
+ printf(" \\\n %s", path->buffer);
+}
+
+
+
+/*
+ * Record the use of a CONFIG_* word.
+ */
+void use_config(const char * name, int len)
+{
+ char *pc;
+ int i;
+
+ pc = path_array[0].buffer + path_array[0].len;
+ memcpy(pc, "config/", 7);
+ pc += 7;
+
+ for (i = 0; i < len; i++) {
+ char c = name[i];
+ if (isupper(c)) c = tolower(c);
+ if (c == '_') c = '/';
+ pc[i] = c;
+ }
+ pc[len] = '\0';
+
+ if (is_defined_config(pc, len))
+ return;
+
+ define_config(pc, len);
+
+ do_depname();
+ printf(" \\\n $(wildcard %s.h)", path_array[0].buffer);
+}
+
+
+
+/*
+ * Macros for stunningly fast map-based character access.
+ * __buf is a register which holds the current word of the input.
+ * Thus, there is one memory access per sizeof(unsigned long) characters.
+ */
+
+#if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__MIPSEL__) \
+ || defined(__arm__)
+#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 ((unsigned long) next % sizeof(unsigned long) == 0) { \
+ if (next >= end) \
+ break; \
+ __buf = * (unsigned long *) next; \
+ } \
+ next++; \
+}
+
+/*
+ * State machine macros.
+ */
+#define CASE(c,label) if (current == c) goto label
+#define NOTCASE(c,label) if (current != c) goto label
+
+/*
+ * Yet another state machine speedup.
+ */
+#define MAX2(a,b) ((a)>(b)?(a):(b))
+#define MIN2(a,b) ((a)<(b)?(a):(b))
+#define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e)))))
+#define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e)))))
+
+
+
+/*
+ * The state machine looks for (approximately) these Perl regular expressions:
+ *
+ * m|\/\*.*?\*\/|
+ * m|\/\/.*|
+ * m|'.*?'|
+ * m|".*?"|
+ * m|#\s*include\s*"(.*?)"|
+ * m|#\s*include\s*<(.*?>"|
+ * m|#\s*(?define|undef)\s*CONFIG_(\w*)|
+ * m|(?!\w)CONFIG_|
+ *
+ * About 98% of the CPU time is spent here, and most of that is in
+ * the 'start' paragraph. Because the current characters are
+ * in a register, the start loop usually eats 4 or 8 characters
+ * per memory read. The MAX5 and MIN5 tests dispose of most
+ * input characters with 1 or 2 comparisons.
+ */
+void state_machine(const char * map, const char * end)
+{
+ const char * next = map;
+ const char * map_dot;
+ unsigned long __buf = 0;
+
+ for (;;) {
+start:
+ GETNEXT
+__start:
+ if (current > MAX5('/','\'','"','#','C')) goto start;
+ if (current < MIN5('/','\'','"','#','C')) goto start;
+ CASE('/', slash);
+ CASE('\'', squote);
+ CASE('"', dquote);
+ CASE('#', pound);
+ CASE('C', cee);
+ goto start;
+
+/* // */
+slash_slash:
+ GETNEXT
+ CASE('\n', start);
+ NOTCASE('\\', slash_slash);
+ GETNEXT
+ goto slash_slash;
+
+/* / */
+slash:
+ GETNEXT
+ CASE('/', slash_slash);
+ NOTCASE('*', __start);
+slash_star_dot_star:
+ GETNEXT
+__slash_star_dot_star:
+ NOTCASE('*', slash_star_dot_star);
+ GETNEXT
+ NOTCASE('/', __slash_star_dot_star);
+ goto start;
+
+/* '.*?' */
+squote:
+ GETNEXT
+ CASE('\'', start);
+ NOTCASE('\\', squote);
+ GETNEXT
+ goto squote;
+
+/* ".*?" */
+dquote:
+ GETNEXT
+ CASE('"', start);
+ NOTCASE('\\', dquote);
+ GETNEXT
+ goto dquote;
+
+/* #\s* */
+pound:
+ GETNEXT
+ CASE(' ', pound);
+ CASE('\t', pound);
+ CASE('i', pound_i);
+ CASE('d', pound_d);
+ CASE('u', pound_u);
+ goto __start;
+
+/* #\s*i */
+pound_i:
+ GETNEXT NOTCASE('n', __start);
+ GETNEXT NOTCASE('c', __start);
+ GETNEXT NOTCASE('l', __start);
+ GETNEXT NOTCASE('u', __start);
+ GETNEXT NOTCASE('d', __start);
+ GETNEXT NOTCASE('e', __start);
+ goto pound_include;
+
+/* #\s*include\s* */
+pound_include:
+ GETNEXT
+ CASE(' ', pound_include);
+ CASE('\t', pound_include);
+ map_dot = next;
+ CASE('"', pound_include_dquote);
+ CASE('<', pound_include_langle);
+ goto __start;
+
+/* #\s*include\s*"(.*)" */
+pound_include_dquote:
+ GETNEXT
+ CASE('\n', start);
+ NOTCASE('"', pound_include_dquote);
+ handle_include(1, map_dot, next - map_dot - 1);
+ goto start;
+
+/* #\s*include\s*<(.*)> */
+pound_include_langle:
+ GETNEXT
+ CASE('\n', start);
+ NOTCASE('>', pound_include_langle);
+ handle_include(0, map_dot, next - map_dot - 1);
+ goto start;
+
+/* #\s*d */
+pound_d:
+ GETNEXT NOTCASE('e', __start);
+ GETNEXT NOTCASE('f', __start);
+ GETNEXT NOTCASE('i', __start);
+ GETNEXT NOTCASE('n', __start);
+ GETNEXT NOTCASE('e', __start);
+ goto pound_define_undef;
+
+/* #\s*u */
+pound_u:
+ GETNEXT NOTCASE('n', __start);
+ GETNEXT NOTCASE('d', __start);
+ GETNEXT NOTCASE('e', __start);
+ GETNEXT NOTCASE('f', __start);
+ goto pound_define_undef;
+
+/*
+ * #\s*(define|undef)\s*CONFIG_(\w*)
+ *
+ * this does not define the word, because it could be inside another
+ * conditional (#if 0). But I do parse the word so that this instance
+ * does not count as a use. -- mec
+ */
+pound_define_undef:
+ GETNEXT
+ CASE(' ', pound_define_undef);
+ CASE('\t', pound_define_undef);
+
+ NOTCASE('C', __start);
+ GETNEXT NOTCASE('O', __start);
+ GETNEXT NOTCASE('N', __start);
+ GETNEXT NOTCASE('F', __start);
+ GETNEXT NOTCASE('I', __start);
+ GETNEXT NOTCASE('G', __start);
+ GETNEXT NOTCASE('_', __start);
+
+ map_dot = next;
+pound_define_undef_CONFIG_word:
+ GETNEXT
+ if (isalnum(current) || current == '_')
+ goto pound_define_undef_CONFIG_word;
+ goto __start;
+
+/* \<CONFIG_(\w*) */
+cee:
+ if (next >= map+2 && (isalnum(next[-2]) || next[-2] == '_'))
+ goto start;
+ GETNEXT NOTCASE('O', __start);
+ GETNEXT NOTCASE('N', __start);
+ GETNEXT NOTCASE('F', __start);
+ GETNEXT NOTCASE('I', __start);
+ GETNEXT NOTCASE('G', __start);
+ GETNEXT NOTCASE('_', __start);
+
+ map_dot = next;
+cee_CONFIG_word:
+ GETNEXT
+ if (isalnum(current) || current == '_')
+ goto cee_CONFIG_word;
+ use_config(map_dot, next - map_dot - 1);
+ goto __start;
+ }
+}
+
+
+
+/*
+ * Generate dependencies for one file.
+ */
+void do_depend(const char * filename, const char * command)
+{
+ int mapsize;
+ int pagesizem1 = getpagesize()-1;
+ int fd;
+ struct stat st;
+ char * map;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ return;
+ }
+
+ fstat(fd, &st);
+ if (st.st_size == 0) {
+ fprintf(stderr,"%s is empty\n",filename);
+ close(fd);
+ return;
+ }
+
+ mapsize = st.st_size;
+ mapsize = (mapsize+pagesizem1) & ~pagesizem1;
+ map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
+ if ((long) map == -1) {
+ perror("mkdep: mmap");
+ close(fd);
+ return;
+ }
+ if ((unsigned long) map % sizeof(unsigned long) != 0)
+ {
+ fprintf(stderr, "do_depend: map not aligned\n");
+ exit(1);
+ }
+
+ hasdep = 0;
+ clear_config();
+ state_machine(map, map+st.st_size);
+ if (hasdep) {
+ puts(command);
+ if (*command)
+ define_precious(filename);
+ }
+
+ munmap(map, mapsize);
+ close(fd);
+}
+
+
+
+/*
+ * Generate dependencies for all files.
+ */
+int main(int argc, char **argv)
+{
+ int len;
+ char *hpath;
+
+ hpath = getenv("HPATH");
+ if (!hpath) {
+ fputs("mkdep: HPATH not set in environment. "
+ "Don't bypass the top level Makefile.\n", stderr);
+ return 1;
+ }
+ len = strlen(hpath);
+ memcpy(path_array[0].buffer, hpath, len);
+ if (len && hpath[len-1] != '/')
+ path_array[0].buffer[len++] = '/';
+ path_array[0].buffer[len] = '\0';
+ path_array[0].len = len;
+
+ while (--argc > 0) {
+ const char * filename = *++argv;
+ const char * command = __depname;
+ g_filename = 0;
+ len = strlen(filename);
+ memcpy(depname, filename, len+1);
+ if (len > 2 && filename[len-2] == '.') {
+ if (filename[len-1] == 'c' || filename[len-1] == 'S') {
+ depname[len-1] = 'o';
+ g_filename = filename;
+ command = "";
+ }
+ }
+ do_depend(filename, command);
+ }
+ if (len_precious) {
+ *(str_precious+len_precious) = '\0';
+ printf(".PRECIOUS:%s\n", str_precious);
+ }
+ return 0;
+}
diff --git a/scripts/patch-kernel b/scripts/patch-kernel
new file mode 100755
index 000000000000..328c01b080a0
--- /dev/null
+++ b/scripts/patch-kernel
@@ -0,0 +1,94 @@
+#! /bin/sh
+# Script to apply kernel patches.
+# usage: patch-kernel [ sourcedir [ patchdir [ stopversion ] ] ]
+# 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.
+#
+# Added support for handling multiple types of compression. What includes
+# gzip, bzip, bzip2, zip, compress, and plaintext.
+#
+# Adam Sulmicki <adam@cfar.umd.edu>, 1st January 1997.
+#
+# Added ability to stop at a given version number
+# Put the full version number (i.e. 2.3.31) as the last parameter
+# Dave Gilbert <linux@treblig.org>, 11th December 1999.
+
+# Set directories from arguments, or use defaults.
+sourcedir=${1-/usr/src/linux}
+patchdir=${2-.}
+stopvers=${3-imnotaversion}
+
+# 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`
+ FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+
+ patch=patch-$FULLVERSION
+ if [ -r $patchdir/${patch}.gz ]; then
+ ext=".gz"
+ name="gzip"
+ uncomp="gunzip -dc"
+ elif [ -r $patchdir/${patch}.bz ]; then
+ ext=".bz"
+ name="bzip"
+ uncomp="bunzip -dc"
+ elif [ -r $patchdir/${patch}.bz2 ]; then
+ ext=".bz2"
+ name="bzip2"
+ uncomp="bunzip2 -dc"
+ elif [ -r $patchdir/${patch}.zip ]; then
+ ext=".zip"
+ name="zip"
+ uncomp="unzip -d"
+ elif [ -r $patchdir/${patch}.Z ]; then
+ ext=".Z"
+ name="uncompress"
+ uncomp="uncompress -c"
+ elif [ -r $patchdir/${patch} ]; then
+ ext=""
+ name="plaintext"
+ uncomp="cat"
+ else
+ break
+ fi
+
+ echo -n "Applying ${patch} (${name})... "
+ if $uncomp ${patchdir}/${patch}${ext} | 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 {} \;
+
+ if [ $stopvers = $FULLVERSION ]
+ then
+ echo "Stoping at $FULLVERSION as requested. Enjoy."
+ break
+ fi
+done
diff --git a/scripts/pathdown.sh b/scripts/pathdown.sh
new file mode 100644
index 000000000000..16c17b2a8067
--- /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/split-include.c b/scripts/split-include.c
new file mode 100644
index 000000000000..4c02cc897fa1
--- /dev/null
+++ b/scripts/split-include.c
@@ -0,0 +1,226 @@
+/*
+ * split-include.c
+ *
+ * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
+ * This is a C version of syncdep.pl by Werner Almesberger.
+ *
+ * This program takes autoconf.h as input and outputs a directory full
+ * of one-line include files, merging onto the old values.
+ *
+ * Think of the configuration options as key-value pairs. Then there
+ * are five cases:
+ *
+ * key old value new value action
+ *
+ * KEY-1 VALUE-1 VALUE-1 leave file alone
+ * KEY-2 VALUE-2A VALUE-2B write VALUE-2B into file
+ * KEY-3 - VALUE-3 write VALUE-3 into file
+ * KEY-4 VALUE-4 - write an empty file
+ * KEY-5 (empty) - leave old empty file alone
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ERROR_EXIT(strExit) \
+ { \
+ const int errnoSave = errno; \
+ fprintf(stderr, "%s: ", str_my_name); \
+ errno = errnoSave; \
+ perror((strExit)); \
+ exit(1); \
+ }
+
+
+
+int main(int argc, const char * argv [])
+{
+ const char * str_my_name;
+ const char * str_file_autoconf;
+ const char * str_dir_config;
+
+ FILE * fp_config;
+ FILE * fp_target;
+ FILE * fp_find;
+
+ int buffer_size;
+
+ char * line;
+ char * old_line;
+ char * list_target;
+ char * ptarget;
+
+ struct stat stat_buf;
+
+ /* Check arg count. */
+ if (argc != 3)
+ {
+ fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
+ exit(1);
+ }
+
+ str_my_name = argv[0];
+ str_file_autoconf = argv[1];
+ str_dir_config = argv[2];
+
+ /* Find a buffer size. */
+ if (stat(str_file_autoconf, &stat_buf) != 0)
+ ERROR_EXIT(str_file_autoconf);
+ buffer_size = 2 * stat_buf.st_size + 4096;
+
+ /* Allocate buffers. */
+ if ( (line = malloc(buffer_size)) == NULL
+ || (old_line = malloc(buffer_size)) == NULL
+ || (list_target = malloc(buffer_size)) == NULL )
+ ERROR_EXIT(str_file_autoconf);
+
+ /* Open autoconfig file. */
+ if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
+ ERROR_EXIT(str_file_autoconf);
+
+ /* Make output directory if needed. */
+ if (stat(str_dir_config, &stat_buf) != 0)
+ {
+ if (mkdir(str_dir_config, 0755) != 0)
+ ERROR_EXIT(str_dir_config);
+ }
+
+ /* Change to output directory. */
+ if (chdir(str_dir_config) != 0)
+ ERROR_EXIT(str_dir_config);
+
+ /* Put initial separator into target list. */
+ ptarget = list_target;
+ *ptarget++ = '\n';
+
+ /* Read config lines. */
+ while (fgets(line, buffer_size, fp_config))
+ {
+ const char * str_config;
+ int is_same;
+ int itarget;
+
+ if (line[0] != '#')
+ continue;
+ if ((str_config = strstr(line, "CONFIG_")) == NULL)
+ continue;
+
+ /* Make the output file name. */
+ str_config += sizeof("CONFIG_") - 1;
+ for (itarget = 0; !isspace(str_config[itarget]); itarget++)
+ {
+ char c = str_config[itarget];
+ if (isupper(c)) c = tolower(c);
+ if (c == '_') c = '/';
+ ptarget[itarget] = c;
+ }
+ ptarget[itarget++] = '.';
+ ptarget[itarget++] = 'h';
+ ptarget[itarget++] = '\0';
+
+ /* Check for existing file. */
+ is_same = 0;
+ if ((fp_target = fopen(ptarget, "r")) != NULL)
+ {
+ fgets(old_line, buffer_size, fp_target);
+ if (fclose(fp_target) != 0)
+ ERROR_EXIT(ptarget);
+ if (!strcmp(line, old_line))
+ is_same = 1;
+ }
+
+ if (!is_same)
+ {
+ /* Auto-create directories. */
+ int islash;
+ for (islash = 0; islash < itarget; islash++)
+ {
+ if (ptarget[islash] == '/')
+ {
+ ptarget[islash] = '\0';
+ if (stat(ptarget, &stat_buf) != 0
+ && mkdir(ptarget, 0755) != 0)
+ ERROR_EXIT( ptarget );
+ ptarget[islash] = '/';
+ }
+ }
+
+ /* Write the file. */
+ if ((fp_target = fopen(ptarget, "w" )) == NULL)
+ ERROR_EXIT(ptarget);
+ fputs(line, fp_target);
+ if (ferror(fp_target) || fclose(fp_target) != 0)
+ ERROR_EXIT(ptarget);
+ }
+
+ /* Update target list */
+ ptarget += itarget;
+ *(ptarget-1) = '\n';
+ }
+
+ /*
+ * Close autoconfig file.
+ * Terminate the target list.
+ */
+ if (fclose(fp_config) != 0)
+ ERROR_EXIT(str_file_autoconf);
+ *ptarget = '\0';
+
+ /*
+ * Fix up existing files which have no new value.
+ * This is Case 4 and Case 5.
+ *
+ * I re-read the tree and filter it against list_target.
+ * This is crude. But it avoids data copies. Also, list_target
+ * is compact and contiguous, so it easily fits into cache.
+ *
+ * Notice that list_target contains strings separated by \n,
+ * with a \n before the first string and after the last.
+ * fgets gives the incoming names a terminating \n.
+ * So by having an initial \n, strstr will find exact matches.
+ */
+
+ fp_find = popen("find * -type f -print", "r");
+ if (fp_find == 0)
+ ERROR_EXIT( "find" );
+
+ line[0] = '\n';
+ while (fgets(line+1, buffer_size, fp_find))
+ {
+ if (strstr(list_target, line) == NULL)
+ {
+ /*
+ * This is an old file with no CONFIG_* flag in autoconf.h.
+ */
+
+ /* First strip the \n. */
+ line[strlen(line)-1] = '\0';
+
+ /* Grab size. */
+ if (stat(line+1, &stat_buf) != 0)
+ ERROR_EXIT(line);
+
+ /* If file is not empty, make it empty and give it a fresh date. */
+ if (stat_buf.st_size != 0)
+ {
+ if ((fp_target = fopen(line+1, "w")) == NULL)
+ ERROR_EXIT(line);
+ if (fclose(fp_target) != 0)
+ ERROR_EXIT(line);
+ }
+ }
+ }
+
+ if (pclose(fp_find) != 0)
+ ERROR_EXIT("find");
+
+ return 0;
+}
diff --git a/scripts/tail.tk b/scripts/tail.tk
new file mode 100644
index 000000000000..49d7aa37a324
--- /dev/null
+++ b/scripts/tail.tk
@@ -0,0 +1,89 @@
+# FILE: tail.tk
+# This file is boilerplate TCL/TK function definitions for 'make xconfig'.
+#
+# CHANGES
+# =======
+#
+# 8 January 1998, Michael Elizabeth Chastain, <mec@shout.net>
+# Arrange buttons in three columns for better screen fitting.
+#
+
+#
+# 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_define 1 $total_menus 0
+update_mainmenu
+
+button .f0.right.save -anchor w -text "Save and Exit" -underline 0\
+ -command { catch {exec cp -f .config .config.old}; \
+ writeconfig .config include/linux/autoconf.h; wrapup .wrap }
+
+button .f0.right.quit -anchor w -text "Quit Without Saving" -underline 0\
+ -command { maybe_exit .maybe }
+
+button .f0.right.load -anchor w -text "Load Configuration from File" \
+ -command { load_configfile .load "Load Configuration from file" read_config_file
+}
+
+button .f0.right.store -anchor w -text "Store Configuration to File" \
+ -command { load_configfile .load "Store Configuration to file" write_config_file }
+
+#
+# Now pack everything.
+#
+
+pack .f0.right.store .f0.right.load .f0.right.quit .f0.right.save \
+ -padx 0 -pady 0 -side bottom -fill x
+pack .f0.left .f0.middle .f0.right -side left -padx 5 -pady 0 -fill y
+pack .f0 -padx 5 -pady 5
+
+update idletasks
+set winy [expr 10 + [winfo reqheight .f0]]
+set scry [lindex [wm maxsize .] 1]
+set winx [expr 10 + [winfo reqwidth .f0]]
+set scrx [lindex [wm maxsize .] 0]
+if {$winx < $scrx} then {set maxx -1} else {set maxx $winx}
+if {$winy < $scry} then {set maxy -1} else {set maxy $winy}
+.f0 configure -width $winx -height $winy
+wm maxsize . $maxx $maxy
+
+#
+# If we cannot write our config files, disable the write button.
+#
+if { [file exists .config] == 1 } then {
+ if { [file writable .config] == 0 } then {
+ .f0.right.save configure -state disabled
+ }
+ } else {
+ if { [file writable .] == 0 } then {
+ .f0.right.save configure -state disabled
+ }
+ }
+
+if { [file exists include/linux/autoconf.h] == 1 } then {
+ if { [file writable include/linux/autoconf.h] == 0 } then {
+ .f0.right.save configure -state disabled
+ }
+ } else {
+ if { [file writable include/linux/] == 0 } then {
+ .f0.right.save configure -state disabled
+ }
+ }
diff --git a/scripts/tkcond.c b/scripts/tkcond.c
new file mode 100644
index 000000000000..34c923fe9e5f
--- /dev/null
+++ b/scripts/tkcond.c
@@ -0,0 +1,602 @@
+/*
+ * tkcond.c
+ *
+ * Eric Youngdale was the original author of xconfig.
+ * Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
+ *
+ * This file takes the tokenized statement list and transforms 'if ...'
+ * statements. For each simple statement, I find all of the 'if' statements
+ * that enclose it, and attach the aggregate conditionals of those 'if'
+ * statements to the cond list of the simple statement.
+ *
+ * 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+ * - Steam-clean this file. I tested this by generating kconfig.tk for
+ * every architecture and comparing it character-for-character against
+ * the output of the old tkparse.
+ *
+ * 07 July 1999, Andrzej M. Krzysztofowicz <ankry@mif.pg.gda.pl>
+ * - kvariables removed; all variables are stored in a single table now
+ * - some elimination of options non-valid for current architecture
+ * implemented.
+ * - negation (!) eliminated from conditions
+ *
+ * TO DO:
+ * - xconfig is at the end of its life cycle. Contact <mec@shout.net> if
+ * you are interested in working on the replacement.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tkparse.h"
+
+
+
+/*
+ * Mark variables which are defined anywhere.
+ */
+static void mark_variables( struct kconfig * scfg )
+{
+ struct kconfig * cfg;
+ int i;
+
+ for ( i = 1; i <= max_varnum; i++ )
+ vartable[i].defined = 0;
+ for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ {
+ if ( cfg->token == token_bool
+ || cfg->token == token_choice_item
+ || cfg->token == token_define_bool
+ || cfg->token == token_define_hex
+ || cfg->token == token_define_int
+ || cfg->token == token_define_string
+ || cfg->token == token_define_tristate
+ || cfg->token == token_dep_bool
+ || cfg->token == token_dep_mbool
+ || cfg->token == token_dep_tristate
+ || cfg->token == token_hex
+ || cfg->token == token_int
+ || cfg->token == token_string
+ || cfg->token == token_tristate
+ || cfg->token == token_unset )
+ {
+ if ( cfg->nameindex > 0 ) /* paranoid */
+ {
+ vartable[cfg->nameindex].defined = 1;
+ }
+ }
+ }
+}
+
+
+
+static void free_cond( struct condition *cond )
+{
+ struct condition *tmp, *tmp1;
+ for ( tmp = cond; tmp; tmp = tmp1 )
+ {
+ tmp1 = tmp->next;
+ free( (void*)tmp );
+ }
+}
+
+
+
+/*
+ * Remove the bang operator from a condition to avoid priority problems.
+ * "!" has different priorities as "test" command argument and in
+ * a tk script.
+ */
+static struct condition * remove_bang( struct condition * condition )
+{
+ struct condition * conda, * condb, * prev = NULL;
+
+ for ( conda = condition; conda; conda = conda->next )
+ {
+ if ( conda->op == op_bang && conda->next &&
+ ( condb = conda->next->next ) )
+ {
+ if ( condb->op == op_eq || condb->op == op_neq )
+ {
+ condb->op = (condb->op == op_eq) ? op_neq : op_eq;
+ conda->op = op_nuked;
+ if ( prev )
+ {
+ prev->next = conda->next;
+ }
+ else
+ {
+ condition = conda->next;
+ }
+ conda->next = NULL;
+ free_cond( conda );
+ conda = condb;
+ }
+ }
+ prev = conda;
+ }
+ return condition;
+}
+
+
+
+/*
+ * Make a new condition chain by joining the current condition stack with
+ * the "&&" operator for glue.
+ */
+static struct condition * join_condition_stack( struct condition * conditions [],
+ int depth )
+{
+ struct condition * cond_list;
+ struct condition * cond_last;
+ int i, is_first = 1;
+
+ cond_list = cond_last = NULL;
+
+ for ( i = 0; i < depth; i++ )
+ {
+ if ( conditions[i]->op == op_false )
+ {
+ struct condition * cnew;
+
+ /* It is always false condition */
+ cnew = malloc( sizeof(*cnew) );
+ memset( cnew, 0, sizeof(*cnew) );
+ cnew->op = op_false;
+ cond_list = cond_last = cnew;
+ goto join_done;
+ }
+ }
+ for ( i = 0; i < depth; i++ )
+ {
+ struct condition * cond;
+ struct condition * cnew;
+ int add_paren;
+
+ /* omit always true conditions */
+ if ( conditions[i]->op == op_true )
+ continue;
+
+ /* if i have another condition, add an '&&' operator */
+ if ( !is_first )
+ {
+ cnew = malloc( sizeof(*cnew) );
+ memset( cnew, 0, sizeof(*cnew) );
+ cnew->op = op_and;
+ cond_last->next = cnew;
+ cond_last = cnew;
+ }
+
+ if ( conditions[i]->op != op_lparen )
+ {
+ /* add a '(' */
+ add_paren = 1;
+ cnew = malloc( sizeof(*cnew) );
+ memset( cnew, 0, sizeof(*cnew) );
+ cnew->op = op_lparen;
+ if ( cond_last == NULL )
+ { cond_list = cond_last = cnew; }
+ else
+ { cond_last->next = cnew; cond_last = cnew; }
+ }
+ else
+ {
+ add_paren = 0;
+ }
+
+ /* duplicate the chain */
+ for ( cond = conditions [i]; cond != NULL; cond = cond->next )
+ {
+ cnew = malloc( sizeof(*cnew) );
+ cnew->next = NULL;
+ cnew->op = cond->op;
+ cnew->str = cond->str ? strdup( cond->str ) : NULL;
+ cnew->nameindex = cond->nameindex;
+ if ( cond_last == NULL )
+ { cond_list = cond_last = cnew; }
+ else
+ { cond_last->next = cnew; cond_last = cnew; }
+ }
+
+ if ( add_paren )
+ {
+ /* add a ')' */
+ cnew = malloc( sizeof(*cnew) );
+ memset( cnew, 0, sizeof(*cnew) );
+ cnew->op = op_rparen;
+ cond_last->next = cnew;
+ cond_last = cnew;
+ }
+ is_first = 0;
+ }
+
+ /*
+ * Remove duplicate conditions.
+ */
+ {
+ struct condition *cond1, *cond1b, *cond1c, *cond1d, *cond1e, *cond1f;
+
+ for ( cond1 = cond_list; cond1 != NULL; cond1 = cond1->next )
+ {
+ if ( cond1->op == op_lparen )
+ {
+ cond1b = cond1 ->next; if ( cond1b == NULL ) break;
+ cond1c = cond1b->next; if ( cond1c == NULL ) break;
+ cond1d = cond1c->next; if ( cond1d == NULL ) break;
+ cond1e = cond1d->next; if ( cond1e == NULL ) break;
+ cond1f = cond1e->next; if ( cond1f == NULL ) break;
+
+ if ( cond1b->op == op_variable
+ && ( cond1c->op == op_eq || cond1c->op == op_neq )
+ && cond1d->op == op_constant
+ && cond1e->op == op_rparen )
+ {
+ struct condition *cond2, *cond2b, *cond2c, *cond2d, *cond2e, *cond2f;
+
+ for ( cond2 = cond1f->next; cond2 != NULL; cond2 = cond2->next )
+ {
+ if ( cond2->op == op_lparen )
+ {
+ cond2b = cond2 ->next; if ( cond2b == NULL ) break;
+ cond2c = cond2b->next; if ( cond2c == NULL ) break;
+ cond2d = cond2c->next; if ( cond2d == NULL ) break;
+ cond2e = cond2d->next; if ( cond2e == NULL ) break;
+ cond2f = cond2e->next;
+
+ /* look for match */
+ if ( cond2b->op == op_variable
+ && cond2b->nameindex == cond1b->nameindex
+ && cond2c->op == cond1c->op
+ && cond2d->op == op_constant
+ && strcmp( cond2d->str, cond1d->str ) == 0
+ && cond2e->op == op_rparen )
+ {
+ /* one of these must be followed by && */
+ if ( cond1f->op == op_and
+ || ( cond2f != NULL && cond2f->op == op_and ) )
+ {
+ /* nuke the first duplicate */
+ cond1 ->op = op_nuked;
+ cond1b->op = op_nuked;
+ cond1c->op = op_nuked;
+ cond1d->op = op_nuked;
+ cond1e->op = op_nuked;
+ if ( cond1f->op == op_and )
+ cond1f->op = op_nuked;
+ else
+ cond2f->op = op_nuked;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+join_done:
+ return cond_list;
+}
+
+
+
+static char * current_arch = NULL;
+
+/*
+ * Eliminating conditions with ARCH = <not current>.
+ */
+static struct condition *eliminate_other_arch( struct condition *list )
+{
+ struct condition *cond1a = list, *cond1b = NULL, *cond1c = NULL, *cond1d = NULL;
+ if ( current_arch == NULL )
+ current_arch = getenv( "ARCH" );
+ if ( current_arch == NULL )
+ {
+ fprintf( stderr, "error: ARCH undefined\n" );
+ exit( 1 );
+ }
+ if ( cond1a->op == op_variable
+ && ! strcmp( vartable[cond1a->nameindex].name, "ARCH" ) )
+ {
+ cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
+ cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
+ cond1d = cond1c->next;
+ if ( cond1c->op == op_constant && cond1d == NULL )
+ {
+ if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
+ || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
+ {
+ /* This is for another architecture */
+ cond1a->op = op_false;
+ cond1a->next = NULL;
+ free_cond( cond1b );
+ return cond1a;
+ }
+ else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
+ || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
+ {
+ /* This is for current architecture */
+ cond1a->op = op_true;
+ cond1a->next = NULL;
+ free_cond( cond1b );
+ return cond1a;
+ }
+ }
+ else if ( cond1c->op == op_constant && cond1d->op == op_or )
+ {
+ if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
+ || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
+ {
+ /* This is for another architecture */
+ cond1b = cond1d->next;
+ cond1d->next = NULL;
+ free_cond( cond1a );
+ return eliminate_other_arch( cond1b );
+ }
+ else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
+ || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
+ {
+ /* This is for current architecture */
+ cond1a->op = op_true;
+ cond1a->next = NULL;
+ free_cond( cond1b );
+ return cond1a;
+ }
+ }
+ else if ( cond1c->op == op_constant && cond1d->op == op_and )
+ {
+ if ( (cond1b->op == op_eq && strcmp( cond1c->str, current_arch ))
+ || (cond1b->op == op_neq && ! strcmp( cond1c->str, current_arch )) )
+ {
+ /* This is for another architecture */
+ int l_par = 0;
+
+ for ( cond1c = cond1d->next; cond1c; cond1c = cond1c->next )
+ {
+ if ( cond1c->op == op_lparen )
+ l_par++;
+ else if ( cond1c->op == op_rparen )
+ l_par--;
+ else if ( cond1c->op == op_or && l_par == 0 )
+ /* Expression too complex - don't touch */
+ return cond1a;
+ else if ( l_par < 0 )
+ {
+ fprintf( stderr, "incorrect condition: programming error ?\n" );
+ exit( 1 );
+ }
+ }
+ cond1a->op = op_false;
+ cond1a->next = NULL;
+ free_cond( cond1b );
+ return cond1a;
+ }
+ else if ( (cond1b->op == op_neq && strcmp( cond1c->str, current_arch ))
+ || (cond1b->op == op_eq && ! strcmp( cond1c->str, current_arch )) )
+ {
+ /* This is for current architecture */
+ cond1b = cond1d->next;
+ cond1d->next = NULL;
+ free_cond( cond1a );
+ return eliminate_other_arch( cond1b );
+ }
+ }
+ }
+ if ( cond1a->op == op_variable && ! vartable[cond1a->nameindex].defined )
+ {
+ cond1b = cond1a->next; if ( cond1b == NULL ) goto done;
+ cond1c = cond1b->next; if ( cond1c == NULL ) goto done;
+ cond1d = cond1c->next;
+
+ if ( cond1c->op == op_constant
+ && ( cond1d == NULL || cond1d->op == op_and ) ) /*???*/
+ {
+ if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
+ {
+ cond1a->op = op_false;
+ cond1a->next = NULL;
+ free_cond( cond1b );
+ return cond1a;
+ }
+ }
+ else if ( cond1c->op == op_constant && cond1d->op == op_or )
+ {
+ if ( cond1b->op == op_eq && strcmp( cond1c->str, "" ) )
+ {
+ cond1b = cond1d->next;
+ cond1d->next = NULL;
+ free_cond( cond1a );
+ return eliminate_other_arch( cond1b );
+ }
+ }
+ }
+done:
+ return list;
+}
+
+
+
+/*
+ * This is the main transformation function.
+ */
+void fix_conditionals( struct kconfig * scfg )
+{
+ struct kconfig * cfg;
+
+ /*
+ * Transform op_variable to op_kvariable.
+ */
+ mark_variables( scfg );
+
+ /*
+ * Walk the statement list, maintaining a stack of current conditions.
+ * token_if push its condition onto the stack.
+ * token_else invert the condition on the top of the stack.
+ * token_endif pop the stack.
+ *
+ * For a simple statement, create a condition chain by joining together
+ * all of the conditions on the stack.
+ */
+ {
+ struct condition * cond_stack [32];
+ int depth = 0;
+ struct kconfig * prev = NULL;
+
+ for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ {
+ int good = 1;
+ switch ( cfg->token )
+ {
+ default:
+ break;
+
+ case token_if:
+ cond_stack [depth++] =
+ remove_bang( eliminate_other_arch( cfg->cond ) );
+ cfg->cond = NULL;
+ break;
+
+ case token_else:
+ {
+ /*
+ * Invert the condition chain.
+ *
+ * Be careful to transfrom op_or to op_and1, not op_and.
+ * I will need this later in the code that removes
+ * duplicate conditions.
+ */
+ struct condition * cond;
+
+ for ( cond = cond_stack [depth-1];
+ cond != NULL;
+ cond = cond->next )
+ {
+ switch( cond->op )
+ {
+ default: break;
+ case op_and: cond->op = op_or; break;
+ case op_or: cond->op = op_and1; break;
+ case op_neq: cond->op = op_eq; break;
+ case op_eq: cond->op = op_neq; break;
+ case op_true: cond->op = op_false;break;
+ case op_false:cond->op = op_true; break;
+ }
+ }
+ }
+ break;
+
+ case token_fi:
+ --depth;
+ break;
+
+ case token_bool:
+ case token_choice_item:
+ case token_choice_header:
+ case token_comment:
+ case token_define_bool:
+ case token_define_hex:
+ case token_define_int:
+ case token_define_string:
+ case token_define_tristate:
+ case token_endmenu:
+ case token_hex:
+ case token_int:
+ case token_mainmenu_option:
+ case token_string:
+ case token_tristate:
+ case token_unset:
+ cfg->cond = join_condition_stack( cond_stack, depth );
+ if ( cfg->cond && cfg->cond->op == op_false )
+ {
+ good = 0;
+ if ( prev )
+ prev->next = cfg->next;
+ else
+ scfg = cfg->next;
+ }
+ break;
+
+ case token_dep_bool:
+ case token_dep_mbool:
+ case token_dep_tristate:
+ /*
+ * Same as the other simple statements, plus an additional
+ * condition for the dependency.
+ */
+ if ( cfg->cond )
+ {
+ cond_stack [depth] = eliminate_other_arch( cfg->cond );
+ cfg->cond = join_condition_stack( cond_stack, depth+1 );
+ }
+ else
+ {
+ cfg->cond = join_condition_stack( cond_stack, depth );
+ }
+ if ( cfg->cond && cfg->cond->op == op_false )
+ {
+ good = 0;
+ if ( prev )
+ prev->next = cfg->next;
+ else
+ scfg = cfg->next;
+ }
+ break;
+ }
+ if ( good )
+ prev = cfg;
+ }
+ }
+}
+
+
+
+#if 0
+void dump_condition( struct condition *list )
+{
+ struct condition *tmp;
+ for ( tmp = list; tmp; tmp = tmp->next )
+ {
+ switch (tmp->op)
+ {
+ default:
+ break;
+ case op_variable:
+ printf( " %s", vartable[tmp->nameindex].name );
+ break;
+ case op_constant:
+ printf( " %s", tmp->str );
+ break;
+ case op_eq:
+ printf( " =" );
+ break;
+ case op_bang:
+ printf( " !" );
+ break;
+ case op_neq:
+ printf( " !=" );
+ break;
+ case op_and:
+ case op_and1:
+ printf( " -a" );
+ break;
+ case op_or:
+ printf( " -o" );
+ break;
+ case op_true:
+ printf( " TRUE" );
+ break;
+ case op_false:
+ printf( " FALSE" );
+ break;
+ case op_lparen:
+ printf( " (" );
+ break;
+ case op_rparen:
+ printf( " )" );
+ break;
+ }
+ }
+ printf( "\n" );
+}
+#endif
diff --git a/scripts/tkgen.c b/scripts/tkgen.c
new file mode 100644
index 000000000000..9faede6102de
--- /dev/null
+++ b/scripts/tkgen.c
@@ -0,0 +1,1521 @@
+/* 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.
+ *
+ * 1997 12 08
+ * Michael Chastain - Remove sound driver special cases.
+ *
+ * 1997 11 15
+ * Michael Chastain - For choice buttons, write values for all options,
+ * not just the single chosen one. This is compatible
+ * with 'make config' and 'make oldconfig', and is
+ * needed so smart-config dependencies work if the
+ * user switches from one configuration method to
+ * another.
+ *
+ * 1998 03 09
+ * Axel Boldt - Smaller layout of main menu - it's still too big for 800x600.
+ * - Display help in text window to allow for cut and paste.
+ * - Allow for empty lines in help texts.
+ * - update_define should not set all variables unconditionally to
+ * 0: they may have been set to 1 elsewhere. CONFIG_NETLINK is
+ * an example.
+ *
+ * 1999 01 04
+ * Michael Elizabeth Chastain <mec@shout.net>
+ * - Call clear_globalflags when writing out update_mainmenu.
+ * This fixes the missing global/vfix lines for ARCH=alpha on 2.2.0-pre4.
+ *
+ * 8 January 1999, Michael Elizabeth Chastain <mec@shout.net>
+ * - Emit menus_per_column
+ *
+ * 14 January 1999, Michael Elizabeth Chastain <mec@shout.net>
+ * - Steam-clean this file. I tested this by generating kconfig.tk for every
+ * architecture and comparing it character-for-character against the output
+ * of the old tkparse.
+ * - Fix flattening of nested menus. The old code simply assigned items to
+ * the most recent token_mainmenu_option, without paying attention to scope.
+ * For example: "menu-1 bool-a menu-2 bool-b endmenu bool-c bool-d endmenu".
+ * The old code would put bool-a in menu-1, bool-b in menu-2, and bool-c
+ * and bool-d in *menu-2*. This hosed the nested submenus in
+ * drives/net/Config.in and other places.
+ * - Fix menu line wraparound at 128 menus (some fool used a 'char' for
+ * a counter).
+ *
+ * 23 January 1999, Michael Elizabeth Chastain <mec@shout.net>
+ * - Remove bug-compatible code.
+ *
+ * 07 July 1999, Andrzej M. Krzysztofowicz <ankry@mif.pg.gda.pl>
+ * Some bugfixes, including
+ * - disabling "m" options when CONFIG_MODULES is set to "n" as well as "y"
+ * option in dep_tristate when dependency is set to "m",
+ * - deactivating choices which should not be available,
+ * - basic validation for int and hex introduced if the entered one is not
+ * valid,
+ * - updates of all opened menus instead of the active only. I was afraid
+ * that it would slow down updates, but I don't even see any speed difference
+ * on my machine. If it slows you can still work with only a single menu
+ * opened,
+ * - fixed error when focussing non-existent window (especially Help windows),
+ * Higher level submenus implemented.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "tkparse.h"
+
+
+/*
+ * Total number of menus.
+ */
+static int tot_menu_num = 0;
+
+/*
+ * Pointers to mainmenu_option and endmenu of each menu.
+ */
+struct kconfig * menu_first [100];
+struct kconfig * menu_last [100];
+
+/*
+ * Generate portion of wish script for the beginning of a submenu.
+ * The guts get filled in with the various options.
+ */
+static void start_proc( char * label, int menu_num, int toplevel )
+{
+ if ( toplevel )
+ printf( "menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label );
+ printf( "proc menu%d {w title} {\n", menu_num );
+ printf( "\tset oldFocus [focus]\n" );
+ if ( menu_first[menu_num]->menu_number != 0 )
+ printf( "\tcatch {focus .menu%d}\n",
+ menu_first[menu_num]->menu_number );
+ printf( "\tcatch {destroy $w; unregister_active %d}\n", menu_num );
+ printf( "\ttoplevel $w -class Dialog\n" );
+ printf( "\twm withdraw $w\n" );
+ printf( "\tglobal active_menus\n" );
+ printf( "\tset active_menus [lsort -integer [linsert $active_menus end %d]]\n", menu_num );
+ printf( "\tmessage $w.m -width 400 -aspect 300 -text \\\n" );
+ printf( "\t\t\"%s\" -relief raised\n", label );
+ printf( "\tpack $w.m -pady 10 -side top -padx 10\n" );
+ printf( "\twm title $w \"%s\" \n\n", label );
+
+ printf( "\tbind $w <Escape> \"catch {focus $oldFocus}; destroy $w; unregister_active %d; break\"\n", menu_num);
+
+ printf("\tset nextscript ");
+ printf("\"catch {focus $oldFocus}; " );
+ /*
+ * We are checking which windows should be destroyed and which are
+ * common parrents with the next one. Remember that menu_num field
+ * in mainmenu_option record reports number of its *parent* menu.
+ */
+ if ( menu_num < tot_menu_num
+ && menu_first[menu_num + 1]->menu_number != menu_num )
+ {
+ int to_destr;
+
+ printf( "destroy $w; unregister_active %d; ", menu_num );
+ to_destr = menu_first[menu_num]->menu_number;
+ while ( to_destr > 0 && menu_first[menu_num + 1]->menu_number != to_destr )
+ {
+ printf( "catch {destroy .menu%d}; unregister_active %d; ",
+ to_destr, to_destr );
+ to_destr = menu_first[to_destr]->menu_number;
+ }
+ }
+ printf( "menu%d .menu%d \\\"$title\\\"\"\n",
+ menu_num+1, menu_num+1 );
+
+ /*
+ * Attach the "Prev", "Next" and "OK" buttons at the end of the window.
+ */
+ printf( "\tframe $w.f\n" );
+ if ( toplevel )
+ printf( "\tbutton $w.f.back -text \"Main Menu\" \\\n" );
+ else
+ printf( "\tbutton $w.f.back -text \"OK\" \\\n" );
+ printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d\"\n",
+ menu_num );
+ printf( "\tbutton $w.f.next -text \"Next\" -underline 0\\\n" );
+ printf( "\t\t-width 15 -command $nextscript\n");
+
+ if ( menu_num == tot_menu_num ) {
+ printf( "\t$w.f.next configure -state disabled\n" );
+ /*
+ * this is a bit hackish but Alt-n must be rebound
+ * otherwise if the user press Alt-n on the last menu
+ * it will give him/her the next menu of one of the
+ * previous options
+ */
+ printf( "\tbind all <Alt-n> \"puts \\\"no more menus\\\" \"\n");
+ }
+ else
+ {
+ /*
+ * I should be binding to $w not all - but if I do nehat I get the error "unknown path"
+ */
+ printf( "\tbind all <Alt-n> $nextscript\n");
+ }
+ printf( "\tbutton $w.f.prev -text \"Prev\" -underline 0\\\n" );
+ printf( "\t\t-width 15 -command \"catch {focus $oldFocus}; destroy $w; unregister_active %d; menu%d .menu%d \\\"$title\\\"\"\n",
+ menu_num, menu_num-1, menu_num-1 );
+ if ( menu_num == 1 ) {
+ printf( "\t$w.f.prev configure -state disabled\n" );
+ }
+ else
+ {
+ printf( "\tbind $w <Alt-p> \"catch {focus $oldFocus}; destroy $w; unregister_active %d; menu%d .menu%d \\\"$title\\\";break\"\n",
+ menu_num, menu_num-1, menu_num-1 );
+ }
+ 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" );
+ printf( "\t\t-relief flat -borderwidth 0 -yscrollcommand \"$w.config.vscroll set\" \\\n" );
+ printf( "\t\t-width [expr [winfo screenwidth .] * 1 / 2] \n" );
+ printf( "\tframe $w.config.f\n" );
+ printf( "\tbind $w <Key-Down> \"$w.config.canvas yview scroll 1 unit;break;\"\n");
+ printf( "\tbind $w <Key-Up> \"$w.config.canvas yview scroll -1 unit;break;\"\n");
+ printf( "\tbind $w <Key-Next> \"$w.config.canvas yview scroll 1 page;break;\"\n");
+ printf( "\tbind $w <Key-Prior> \"$w.config.canvas yview scroll -1 page;break;\"\n");
+ printf( "\tbind $w <Key-Home> \"$w.config.canvas yview moveto 0;break;\"\n");
+ printf( "\tbind $w <Key-End> \"$w.config.canvas yview moveto 1 ;break;\"\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.
+ */
+static void clear_globalflags(void)
+{
+ int i;
+ for ( i = 1; i <= max_varnum; i++ )
+ vartable[i].global_written = 0;
+}
+
+
+
+/*
+ * 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 global( const char *var )
+{
+ printf( "\tglobal %s\n", var );
+}
+
+
+
+/*
+ * This function walks the chain of conditions that we got from cond.c
+ * and creates a TCL conditional to enable/disable a given widget.
+ */
+void generate_if( struct kconfig * cfg, struct condition * ocond,
+ int menu_num, int line_num )
+{
+ struct condition * cond;
+ struct dependency * tmp;
+ struct kconfig * cfg1;
+
+ if ( line_num >= -1 )
+ {
+ if ( cfg->token == token_define_bool || cfg->token == token_define_hex
+ || cfg->token == token_define_int || cfg->token == token_define_string
+ || cfg->token == token_define_tristate || cfg->token == token_unset )
+ return;
+ if ( cfg->token == token_comment && line_num == -1 )
+ return;
+ }
+ else
+ {
+ if ( cfg->token == token_string || cfg->token == token_mainmenu_option )
+ return;
+ }
+
+ /*
+ * First write any global declarations we need for this conditional.
+ */
+ for ( cond = ocond; cond != NULL; cond = cond->next )
+ {
+ switch ( cond->op )
+ {
+ default:
+ break;
+
+ case op_variable:
+ if ( ! vartable[cond->nameindex].global_written )
+ {
+ vartable[cond->nameindex].global_written = 1;
+ global( vartable[cond->nameindex].name );
+ }
+ break;
+ }
+ }
+
+ /*
+ * Now write this option.
+ */
+ if ( cfg->nameindex > 0 && ! vartable[cfg->nameindex].global_written )
+ {
+ vartable[cfg->nameindex].global_written = 1;
+ global( vartable[cfg->nameindex].name );
+ }
+
+ /*
+ * Generate the body of the conditional.
+ */
+ printf( "\tif {" );
+ for ( cond = ocond; cond != NULL; cond = cond->next )
+ {
+ switch ( cond->op )
+ {
+ default:
+ break;
+
+ case op_bang: printf( " ! " ); break;
+ case op_eq: printf( " == " ); break;
+ case op_neq: printf( " != " ); break;
+ case op_and: printf( " && " ); break;
+ 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", vartable[cond->nameindex].name );
+ break;
+
+ case op_constant:
+ if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" );
+ else if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" );
+ else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" );
+ else if ( strcmp( cond->str, "" ) == 0 ) printf( "4" );
+ else
+ printf( "\"%s\"", cond->str );
+ break;
+ }
+ }
+ printf( "} then {" );
+
+ /*
+ * Generate a procedure call to write the value.
+ * This code depends on procedures in header.tk.
+ */
+ if ( line_num >= -1 )
+ {
+ int modtoyes = 0;
+
+ switch ( cfg->token )
+ {
+ default:
+ printf( " }\n" );
+ break;
+
+ case token_dep_mbool:
+ modtoyes = 1;
+ case token_dep_bool:
+ printf( "\n" );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ if ( ! vartable[get_varnum( tmp->name )].global_written )
+ {
+ global( tmp->name );
+ }
+ printf( "\tset tmpvar_dep [effective_dep [list" );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ printf( " $%s", tmp->name );
+ printf( "]];set %s [sync_bool $%s $tmpvar_dep %d];",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name,
+ modtoyes );
+ printf( "if {$tmpvar_dep != 1" );
+ if (modtoyes)
+ printf( " && $tmpvar_dep != 2" );
+ printf( "} then {configure_entry .menu%d.config.f.x%d disabled {y};",
+ menu_num, line_num );
+ printf( "} else {" );
+ printf( "configure_entry .menu%d.config.f.x%d normal {y};",
+ menu_num, line_num );
+ printf( "}; " );
+ case token_bool:
+ if ( cfg->token == token_bool )
+ printf( "\n\t" );
+ printf( "configure_entry .menu%d.config.f.x%d normal {n l",
+ menu_num, line_num );
+ if ( cfg->token == token_bool )
+ printf( " y" );
+ printf( "}" );
+ printf( "} else {");
+ printf( "configure_entry .menu%d.config.f.x%d disabled {y n l}}\n",
+ menu_num, line_num );
+ break;
+
+ case token_choice_header:
+ printf( "configure_entry .menu%d.config.f.x%d normal {x l}",
+ menu_num, line_num );
+ printf( "} else {" );
+ printf( "configure_entry .menu%d.config.f.x%d disabled {x l}",
+ menu_num, line_num );
+ printf( "}\n" );
+ break;
+
+ case token_choice_item:
+ fprintf( stderr, "Internal error on token_choice_item\n" );
+ exit( 1 );
+
+ case token_dep_tristate:
+ printf( "\n" );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ if ( ! vartable[get_varnum( tmp->name )].global_written )
+ {
+ global( tmp->name );
+ }
+ printf( "\tset tmpvar_dep [effective_dep [list" );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ printf( " $%s", tmp->name );
+ printf( "]];set %s [sync_tristate $%s $tmpvar_dep];",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ printf( "\tif {$tmpvar_dep != 1} then {" );
+ printf( "configure_entry .menu%d.config.f.x%d disabled {y}",
+ menu_num, line_num );
+ printf( "} else {" );
+ printf( "configure_entry .menu%d.config.f.x%d normal {y}",
+ menu_num, line_num );
+ printf( "}; " );
+ printf( "if {$tmpvar_dep == 0} then {" );
+ printf( "configure_entry .menu%d.config.f.x%d disabled {m}",
+ menu_num, line_num );
+ printf( "} else {" );
+ printf( "configure_entry .menu%d.config.f.x%d normal {m}",
+ menu_num, line_num );
+ printf( "}; " );
+ case token_tristate:
+ if ( cfg->token == token_tristate )
+ {
+ printf( "\n\tconfigure_entry .menu%d.config.f.x%d normal {y}; ",
+ menu_num, line_num );
+ }
+ printf( "if {($CONFIG_MODULES == 1)} then {" );
+ printf( "configure_entry .menu%d.config.f.x%d normal {m}} else {",
+ menu_num, line_num );
+ printf( "configure_entry .menu%d.config.f.x%d disabled {m}}; ",
+ menu_num, line_num );
+ printf( "configure_entry .menu%d.config.f.x%d normal {n l}",
+ menu_num, line_num );
+
+ /*
+ * Or in a bit to the variable - this causes all of the radiobuttons
+ * to be deselected (i.e. not be red).
+ */
+ printf( "} else {" );
+ printf( "configure_entry .menu%d.config.f.x%d disabled {y n m l}}\n",
+ menu_num, line_num );
+ break;
+
+ case token_hex:
+ case token_int:
+ case token_string:
+ printf( ".menu%d.config.f.x%d.x configure -state normal -foreground [ cget .ref -foreground ]; ",
+ menu_num, line_num );
+ printf( ".menu%d.config.f.x%d.l configure -state normal; ",
+ menu_num, line_num );
+ printf( "} else {" );
+ printf( ".menu%d.config.f.x%d.x configure -state disabled -foreground [ cget .ref -disabledforeground ]; ",
+ menu_num, line_num );
+ printf( ".menu%d.config.f.x%d.l configure -state disabled}\n",
+ menu_num, line_num );
+ break;
+
+ case token_comment:
+ case token_mainmenu_option:
+ if ( line_num >= 0 )
+ {
+ printf( "configure_entry .menu%d.config.f.x%d normal {m}",
+ menu_num, line_num );
+ printf( "} else {" );
+ printf( "configure_entry .menu%d.config.f.x%d disabled {m}}\n",
+ menu_num, line_num );
+ }
+ else
+ printf( ".f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
+ menu_num, menu_num );
+ break;
+ }
+ }
+ else
+ {
+ int modtoyes = 0;
+
+ switch ( cfg->token )
+ {
+ default:
+ printf( " }\n" );
+ break;
+
+ case token_dep_mbool:
+ modtoyes = 1;
+ case token_dep_bool:
+ printf( "\n" );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ if ( ! vartable[get_varnum( tmp->name )].global_written )
+ {
+ global( tmp->name );
+ }
+ printf( "\tset tmpvar_dep [effective_dep [list" );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ printf( " $%s", tmp->name );
+ printf( "]];set %s [sync_bool $%s $tmpvar_dep %d];",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name,
+ modtoyes );
+ case token_bool:
+ if ( cfg->token == token_bool )
+ printf( "\n\t" );
+ printf( "set %s [expr $%s&15]",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ printf( "} else {");
+ printf( "set %s [expr $%s|16]}\n",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ break;
+
+ case token_choice_header:
+ printf( "} else {" );
+ for ( cfg1 = cfg->next;
+ cfg1 != NULL && cfg1->token == token_choice_item;
+ cfg1 = cfg1->next )
+ printf( "set %s 4;", vartable[cfg1->nameindex].name );
+ printf( "}\n" );
+ break;
+
+ case token_choice_item:
+ fprintf( stderr, "Internal error on token_choice_item\n" );
+ exit( 1 );
+
+ case token_define_bool:
+ case token_define_tristate:
+ if ( ! vartable[get_varnum( cfg->value )].global_written )
+ {
+ global( cfg->value );
+ }
+ printf( "set %s $%s }\n",
+ vartable[cfg->nameindex].name, cfg->value );
+ break;
+
+ case token_define_hex:
+ case token_define_int:
+ printf( "set %s %s }\n",
+ vartable[cfg->nameindex].name, cfg->value );
+ break;
+
+ case token_define_string:
+ printf( "set %s \"%s\" }\n",
+ vartable[cfg->nameindex].name, cfg->value );
+ break;
+
+ case token_dep_tristate:
+ printf( "\n" );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ if ( ! vartable[get_varnum( tmp->name )].global_written )
+ {
+ global( tmp->name );
+ }
+ printf( "\tset tmpvar_dep [effective_dep [list" );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ printf( " $%s", tmp->name );
+ printf( "]]; set %s [sync_tristate $%s $tmpvar_dep]; ",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ case token_tristate:
+ if ( cfg->token == token_tristate )
+ printf( "if {($CONFIG_MODULES == 0) && ($%s == 2)} then {set %s 1}; ",
+ vartable[cfg->nameindex].name,
+ vartable[cfg->nameindex].name );
+ /*
+ * Or in a bit to the variable - this causes all of the radiobuttons
+ * to be deselected (i.e. not be red).
+ */
+ printf( "set %s [expr $%s&15]",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ printf( "} else {" );
+
+ /*
+ * Clear the disable bit to enable the correct radiobutton.
+ */
+ printf( "set %s [expr $%s|16]}\n",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ break;
+
+ case token_hex:
+ case token_int:
+ if ( cfg->value && *cfg->value == '$' )
+ {
+ int index = get_varnum( cfg->value+1 );
+ printf( "\n" );
+ if ( ! vartable[index].global_written )
+ {
+ global( vartable[index].name );
+ }
+ printf( "\t" );
+ }
+ if ( cfg->token == token_hex )
+ printf( "validate_hex " );
+ else if ( cfg->token == token_int )
+ printf( "validate_int " );
+ printf( "%s \"$%s\" %s}\n",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name,
+ cfg->value );
+ break;
+
+ case token_unset:
+ printf( "set %s 4}\n", vartable[cfg->nameindex].name );
+ break;
+ }
+ }
+}
+
+
+/*
+ * Generate a line that writes a variable to the output file.
+ */
+void generate_writeconfig( struct kconfig * cfg )
+{
+ struct condition * cond;
+ struct dependency * tmp;
+ int depmod = 2;
+
+ /*
+ * Generate global declaration for this symbol.
+ */
+ if ( cfg->token != token_comment )
+ {
+ if ( cfg->nameindex > 0 && ! vartable[cfg->nameindex].global_written )
+ {
+ vartable[cfg->nameindex].global_written = 1;
+ global( vartable[cfg->nameindex].name );
+ }
+ if ( cfg->token == token_define_tristate || cfg->token == token_define_bool )
+ {
+ if ( ! vartable[get_varnum( cfg->value )].global_written )
+ {
+ vartable[get_varnum( cfg->value )].global_written = 1;
+ global( cfg->value );
+ }
+ }
+ else if ( cfg->nameindex <= 0 && cfg->token == token_choice_header )
+ {
+ printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) );
+ }
+ }
+
+ /*
+ * Generate global declarations for the condition chain.
+ */
+ for ( cond = cfg->cond; cond != NULL; cond = cond->next )
+ {
+ switch( cond->op )
+ {
+ default:
+ break;
+
+ case op_variable:
+ if ( ! vartable[cond->nameindex].global_written )
+ {
+ vartable[cond->nameindex].global_written = 1;
+ global( vartable[cond->nameindex].name );
+ }
+ break;
+ }
+ }
+
+ /*
+ * Generate indentation.
+ */
+ printf( "\t" );
+
+ /*
+ * Generate the conditional.
+ */
+ if ( cfg->cond != NULL )
+ {
+ printf( "if {" );
+ for ( cond = cfg->cond; cond != NULL; cond = cond->next )
+ {
+ switch ( cond->op )
+ {
+ default: break;
+ case op_bang: printf( " ! " ); break;
+ case op_eq: printf( " == " ); break;
+ case op_neq: printf( " != " ); break;
+ case op_and: printf( " && " ); break;
+ 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", vartable[cond->nameindex].name );
+ break;
+
+ case op_constant:
+ if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" );
+ else if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" );
+ else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" );
+ else if ( strcmp( cond->str, "" ) == 0 ) printf( "4" );
+ else
+ printf( "\"%s\"", cond->str );
+ break;
+ }
+ }
+ printf( "} then {" );
+ }
+
+ /*
+ * Generate a procedure call to write the value.
+ * This code depends on the write_* procedures in header.tk.
+ */
+ switch ( cfg->token )
+ {
+ default:
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+
+ case token_bool:
+ case token_tristate:
+ printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+
+ case token_choice_header:
+ /*
+ * This is funky code -- it fails if there were any conditionals.
+ * Fortunately all the conditionals got stripped off somewhere
+ * else.
+ */
+ {
+ struct kconfig * cfg1;
+ for ( cfg1 = cfg->next;
+ cfg1 != NULL && cfg1->token == token_choice_item;
+ cfg1 = cfg1->next )
+ {
+ printf("\n\tif { $tmpvar_%d == \"%s\" } then { write_tristate $cfg $autocfg %s 1 [list $notmod] 2 } else { write_tristate $cfg $autocfg %s 0 [list $notmod] 2 }",
+ -(cfg->nameindex), cfg1->label,
+ vartable[cfg1->nameindex].name,
+ vartable[cfg1->nameindex].name );
+ }
+ }
+ if ( cfg->cond != NULL )
+ printf( "}" );
+ printf( "\n" );
+ break;
+
+ case token_choice_item:
+ fprintf( stderr, "Internal error on token_choice_item\n" );
+ exit( 1 );
+
+ case token_comment:
+ printf( "write_comment $cfg $autocfg \"%s\"",
+ cfg->label );
+ if ( cfg->cond != NULL )
+ printf( "}" );
+ printf( "\n" );
+ break;
+
+ case token_define_bool:
+ case token_define_tristate:
+ if ( cfg->cond == NULL )
+ {
+ printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2\n",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ }
+ else
+ {
+ printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2 }\n",
+ vartable[cfg->nameindex].name, cfg->value );
+ }
+ break;
+
+ case token_dep_mbool:
+ depmod = 1;
+ case token_dep_bool:
+ case token_dep_tristate:
+ printf( "write_tristate $cfg $autocfg %s $%s [list",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ for ( tmp = cfg->depend; tmp; tmp = tmp->next )
+ printf( " $%s", tmp->name );
+ printf( "] %d", depmod );
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+
+ case token_define_hex:
+ printf( "write_hex $cfg $autocfg %s %s $notmod",
+ vartable[cfg->nameindex].name, cfg->value );
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+
+ case token_define_int:
+ printf( "write_int $cfg $autocfg %s %s $notmod",
+ vartable[cfg->nameindex].name, cfg->value );
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+
+ case token_define_string:
+ printf( "write_string $cfg $autocfg %s \"%s\" $notmod",
+ vartable[cfg->nameindex].name, cfg->value );
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+
+ case token_hex:
+ printf( "write_hex $cfg $autocfg %s $%s $notmod",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+
+ case token_int:
+ printf( "write_int $cfg $autocfg %s $%s $notmod",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+
+ case token_string:
+ printf( "write_string $cfg $autocfg %s \"$%s\" $notmod",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ if ( cfg->cond != NULL )
+ printf( " }" );
+ printf( "\n" );
+ break;
+ }
+}
+
+static void generate_update_var( struct kconfig * scfg, int menu_num )
+{
+ struct kconfig * cfg;
+
+ if ( menu_num>0 )
+ {
+ printf( "proc update_define_menu%d {} {\n", menu_num );
+ printf( "\tupdate_define_mainmenu\n" );
+ }
+ else
+ printf( "proc update_define_mainmenu {} {\n" );
+ clear_globalflags();
+ global( "CONFIG_MODULES" );
+ vartable[ get_varnum( "CONFIG_MODULES" ) ].global_written = 1;
+ for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ {
+ if ( cfg->menu_number == menu_num && (cfg->token == token_define_bool || cfg->token == token_define_tristate
+ || cfg->token == token_define_hex || cfg->token == token_define_int
+ || cfg->token == token_define_string || cfg->token == token_unset
+ || cfg->token == token_tristate) )
+ {
+ if ( ! vartable[cfg->nameindex].global_written )
+ {
+ vartable[cfg->nameindex].global_written = 1;
+ global( vartable[cfg->nameindex].name );
+ }
+ }
+ }
+
+ for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ {
+ char tmp[20];
+ struct kconfig * cfg1;
+
+ if ( cfg->menu_number == menu_num )
+ {
+ switch ( cfg->token )
+ {
+ default:
+ case token_choice_item:
+ break;
+ case token_choice_header:
+ sprintf( tmp, "tmpvar_%d", -(cfg->nameindex) );
+ global( tmp );
+ for ( cfg1 = cfg->next;
+ cfg1 != NULL && cfg1->token == token_choice_item;
+ cfg1 = cfg1->next )
+ {
+ vartable[cfg1->nameindex].global_written = 1;
+ global( vartable[cfg1->nameindex].name );
+ printf( "\tif {$tmpvar_%d == \"%s\"} then {set %s 1} else {set %s 0}\n",
+ -(cfg->nameindex), cfg1->label,
+ vartable[cfg1->nameindex].name,
+ vartable[cfg1->nameindex].name );
+ }
+ break;
+ case token_bool:
+ case token_define_bool:
+ case token_define_tristate:
+ case token_define_hex:
+ case token_define_int:
+ case token_define_string:
+ case token_dep_bool:
+ case token_dep_tristate:
+ case token_dep_mbool:
+ case token_int:
+ case token_hex:
+ case token_mainmenu_option:
+ case token_tristate:
+ case token_unset:
+ if ( cfg->cond != NULL )
+ generate_if( cfg, cfg->cond, menu_num, -2 );
+ else switch ( cfg->token )
+ {
+ case token_tristate:
+ printf( "\n\tif {($CONFIG_MODULES == 0)} then {if {($%s == 2)} then {set %s 1}}\n",
+ vartable[cfg->nameindex].name, vartable[cfg->nameindex].name );
+ break;
+ case token_define_bool:
+ case token_define_tristate:
+ if ( ! vartable[get_varnum( cfg->value )].global_written )
+ {
+ vartable[get_varnum( cfg->value )].global_written = 1;
+ global( cfg->value );
+ }
+ printf( "\tset %s $%s\n", vartable[cfg->nameindex].name,
+ cfg->value );
+ break;
+ case token_define_hex:
+ case token_define_int:
+ printf( "\tset %s %s\n", vartable[cfg->nameindex].name,
+ cfg->value );
+ break;
+ case token_define_string:
+ printf( "\tset %s \"%s\"\n", vartable[cfg->nameindex].name,
+ cfg->value );
+ break;
+ case token_unset:
+ printf( "\tset %s 4\n", vartable[cfg->nameindex].name );
+ default:
+ break;
+ }
+ }
+ }
+ }
+ printf( "}\n\n\n" );
+}
+
+
+/*
+ * Generates the end of a menu procedure.
+ */
+static void end_proc( struct kconfig * scfg, int menu_num )
+{
+ struct kconfig * cfg;
+ int i;
+
+ printf( "\n\n\n" );
+ printf( "\tfocus $w\n" );
+ printf( "\tupdate_active\n" );
+ printf( "\tglobal winx; global winy\n" );
+ if ( menu_first[menu_num]->menu_number != 0 )
+ {
+ printf( "\tif {[winfo exists .menu%d] == 0} then ",
+ menu_first[menu_num]->menu_number );
+ printf( "{menu%d .menu%d \"%s\"}\n",
+ menu_first[menu_num]->menu_number, menu_first[menu_num]->menu_number,
+ menu_first[menu_first[menu_num]->menu_number]->label );
+ printf( "\tset winx [expr [winfo x .menu%d]+30]; set winy [expr [winfo y .menu%d]+30]\n",
+ menu_first[menu_num]->menu_number, menu_first[menu_num]->menu_number );
+ }
+ else
+ printf( "\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n" );
+ printf( "\tif {[winfo exists $w]} then {wm 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( "\tif {[winfo exists $w]} then {$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n" );
+ printf( "\t$w.config.canvas configure \\\n" );
+ printf( "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n" );
+ printf( "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n" );
+ printf( "\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" );
+ printf( "\t\t$w.config.canvas configure -height $canvtotal\n" );
+ printf( "\t} else {\n" );
+ printf( "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n" );
+ printf( "\t\t}\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( "\tif {[winfo exists $w]} then {\n\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 {} {\n", menu_num );
+
+ /*
+ * Clear all of the booleans that are defined in this menu.
+ */
+ clear_globalflags();
+ for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ {
+ if ( cfg->menu_number == menu_num
+ && cfg->token != token_mainmenu_option
+ && cfg->token != token_choice_item )
+ {
+ if ( cfg->cond != NULL )
+ {
+ int i;
+ if ( (cfg->token == token_tristate || cfg->token == token_dep_tristate)
+ && ! vartable[i = get_varnum( "CONFIG_MODULES" )].global_written )
+ {
+ global( "CONFIG_MODULES" );
+ vartable[i].global_written = 1;
+ }
+ generate_if( cfg, cfg->cond, cfg->menu_number, cfg->menu_line );
+ }
+ else
+ {
+ if ( cfg->token == token_tristate )
+ {
+ if ( ! vartable[cfg->nameindex].global_written )
+ {
+ vartable[cfg->nameindex].global_written = 1;
+ printf( "\tglobal %s\n", vartable[cfg->nameindex].name );
+ }
+ if ( ! vartable[i = get_varnum( "CONFIG_MODULES" )].global_written )
+ {
+ global( "CONFIG_MODULES" );
+ vartable[i].global_written = 1;
+ }
+ printf( "\n\tif {($CONFIG_MODULES == 1)} then {configure_entry .menu%d.config.f.x%d normal {m}} else {configure_entry .menu%d.config.f.x%d disabled {m}}\n",
+ menu_num, cfg->menu_line,
+ menu_num, cfg->menu_line );
+ }
+ }
+ }
+ else if ( cfg->token == token_mainmenu_option
+ && cfg->menu_number == menu_num
+ && cfg->cond != NULL )
+ {
+ generate_if( cfg, cfg->cond, menu_num, cfg->menu_line );
+ }
+ }
+ printf("}\n\n\n");
+
+ generate_update_var( scfg, menu_num );
+}
+
+/*
+ * This is the top level function for generating the tk script.
+ */
+void dump_tk_script( struct kconfig * scfg )
+{
+ int menu_depth;
+ int menu_num [64];
+ int imenu, i;
+ int top_level_num = 0;
+ struct kconfig * cfg;
+ struct kconfig * cfg1 = NULL;
+ const char * name = "No Name";
+
+ /*
+ * Mark begin and end of each menu so I can omit submenus when walking
+ * over a parent menu.
+ */
+ tot_menu_num = 0;
+ menu_depth = 0;
+ menu_num [0] = 0;
+
+ for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ {
+ switch ( cfg->token )
+ {
+ default:
+ break;
+
+ case token_mainmenu_name:
+ name = cfg->label;
+ break;
+
+ case token_mainmenu_option:
+ if ( ++menu_depth >= 64 )
+ { fprintf( stderr, "menus too deep\n" ); exit( 1 ); }
+ if ( ++tot_menu_num >= 100 )
+ { fprintf( stderr, "too many menus\n" ); exit( 1 ); }
+ menu_num [menu_depth] = tot_menu_num;
+ menu_first [tot_menu_num] = cfg;
+ menu_last [tot_menu_num] = cfg;
+ /*
+ * Note, that menu_number is set to the number of parent
+ * (upper level) menu.
+ */
+ cfg->menu_number = menu_num[menu_depth - 1];
+ if ( menu_depth == 1 )
+ ++top_level_num;
+ break;
+
+ case token_endmenu:
+ menu_last [menu_num [menu_depth]] = cfg;
+ /* flatten menus with proper scoping */
+ if ( --menu_depth < 0 )
+ { fprintf( stderr, "unmatched endmenu\n" ); exit( 1 ); }
+ break;
+
+ case token_bool:
+ case token_choice_header:
+ case token_choice_item:
+ case token_comment:
+ case token_dep_bool:
+ case token_dep_tristate:
+ case token_dep_mbool:
+ case token_hex:
+ case token_int:
+ case token_string:
+ case token_tristate:
+ cfg->menu_number = menu_num[menu_depth];
+ if ( menu_depth == 0 )
+ { fprintf( stderr, "statement not in menu\n" ); exit( 1 ); }
+ break;
+
+ case token_define_bool:
+ case token_define_hex:
+ case token_define_int:
+ case token_define_string:
+ case token_define_tristate:
+ case token_unset:
+ cfg->menu_number = menu_num[menu_depth];
+ break;
+ }
+ }
+
+ /*
+ * Generate menus per column setting.
+ * There are:
+ * four extra buttons for save/quit/load/store;
+ * one blank button
+ * add two to round up for division
+ */
+ printf( "set menus_per_column %d\n", (top_level_num + 4 + 1 + 2) / 3 );
+ printf( "set total_menus %d\n\n", tot_menu_num );
+
+ printf( "proc toplevel_menu {num} {\n" );
+ for ( imenu = 1; imenu <= tot_menu_num; ++imenu )
+ {
+ int parent = 1;
+
+ if ( menu_first[imenu]->menu_number == 0 )
+ parent = menu_first[imenu]->menu_number;
+ else
+ printf( "\tif {$num == %d} then {return %d}\n",
+ imenu, menu_first[imenu]->menu_number );
+ }
+ printf( "\treturn $num\n}\n\n" );
+
+ /*
+ * Generate the menus.
+ */
+ printf( "mainmenu_name \"%s\"\n", name );
+ for ( imenu = 1; imenu <= tot_menu_num; ++imenu )
+ {
+ int menu_line = 0;
+ int nr_submenu = imenu;
+ int menu_name_omitted = 0;
+ int opt_count = 0;
+
+ clear_globalflags();
+ start_proc( menu_first[imenu]->label, imenu,
+ !menu_first[imenu]->menu_number );
+
+ for ( cfg = menu_first[imenu]->next; cfg != NULL && cfg != menu_last[imenu]; cfg = cfg->next )
+ {
+ switch ( cfg->token )
+ {
+ default:
+ break;
+
+ case token_mainmenu_option:
+ while ( menu_first[++nr_submenu]->menu_number > imenu )
+ ;
+ cfg->menu_line = menu_line++;
+ printf( "\tsubmenu $w.config.f %d %d \"%s\" %d\n",
+ cfg->menu_number, cfg->menu_line, cfg->label, nr_submenu );
+ cfg = menu_last[nr_submenu];
+ break;
+
+ case token_comment:
+ if ( !cfg->menu_line && !menu_name_omitted )
+ {
+ cfg->menu_line = -1;
+ menu_name_omitted = 1;
+ }
+ else
+ {
+ menu_name_omitted = 1;
+ cfg->menu_line = menu_line++;
+ printf( "\tcomment $w.config.f %d %d \"%s\"\n",
+ cfg->menu_number, cfg->menu_line, cfg->label );
+ }
+ break;
+
+ case token_bool:
+ cfg->menu_line = menu_line++;
+ printf( "\tbool $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number, cfg->menu_line, cfg->label,
+ vartable[cfg->nameindex].name );
+ break;
+
+ case token_choice_header:
+ /*
+ * I need the first token_choice_item to pick out the right
+ * help text from Documentation/Configure.help.
+ */
+ cfg->menu_line = menu_line++;
+ printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) );
+ printf( "\tminimenu $w.config.f %d %d \"%s\" tmpvar_%d %s\n",
+ cfg->menu_number, cfg->menu_line, cfg->label,
+ -(cfg->nameindex), vartable[cfg->next->nameindex].name );
+ printf( "\tmenu $w.config.f.x%d.x.menu -tearoffcommand \"menutitle \\\"%s\\\"\"\n",
+ cfg->menu_line, cfg->label );
+ cfg1 = cfg;
+ opt_count = 0;
+ break;
+
+ case token_choice_item:
+ /* note: no menu line; uses choice header menu line */
+ printf( "\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable tmpvar_%d -value \"%s\" -command \"update_active\"\n",
+ cfg1->menu_line, cfg->label, -(cfg1->nameindex),
+ cfg->label );
+ opt_count++;
+ if ( cfg->next && cfg->next->token != token_choice_item ) {
+ /* last option in the menu */
+ printf( "\tmenusplit $w $w.config.f.x%d.x.menu %d\n",
+ cfg1->menu_line, opt_count );
+ }
+ break;
+
+ case token_dep_bool:
+ case token_dep_mbool:
+ cfg->menu_line = menu_line++;
+ printf( "\tdep_bool $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number, cfg->menu_line, cfg->label,
+ vartable[cfg->nameindex].name );
+ break;
+
+ case token_dep_tristate:
+ cfg->menu_line = menu_line++;
+ printf( "\tdep_tristate $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number, cfg->menu_line, cfg->label,
+ vartable[cfg->nameindex].name );
+ break;
+
+ case token_hex:
+ cfg->menu_line = menu_line++;
+ printf( "\thex $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number, cfg->menu_line, cfg->label,
+ vartable[cfg->nameindex].name );
+ break;
+
+ case token_int:
+ cfg->menu_line = menu_line++;
+ printf( "\tint $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number, cfg->menu_line, cfg->label,
+ vartable[cfg->nameindex].name );
+ break;
+
+ case token_string:
+ cfg->menu_line = menu_line++;
+ printf( "\tistring $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number, cfg->menu_line, cfg->label,
+ vartable[cfg->nameindex].name );
+ break;
+
+ case token_tristate:
+ cfg->menu_line = menu_line++;
+ printf( "\ttristate $w.config.f %d %d \"%s\" %s\n",
+ cfg->menu_number, cfg->menu_line, cfg->label,
+ vartable[cfg->nameindex].name );
+ break;
+ }
+ }
+
+ end_proc( scfg, imenu );
+ }
+
+ /*
+ * The top level menu also needs an update function. When we update a
+ * submenu, we may need to disable one or more of the submenus on
+ * the top level menu, and this procedure will ensure that things are
+ * correct.
+ */
+ clear_globalflags();
+ printf( "proc update_mainmenu {} {\n" );
+ for ( imenu = 1; imenu <= tot_menu_num; imenu++ )
+ {
+ if ( menu_first[imenu]->cond != NULL && menu_first[imenu]->menu_number == 0 )
+ generate_if( menu_first[imenu], menu_first[imenu]->cond, imenu, -1 );
+ }
+ printf( "}\n\n\n" );
+
+ clear_globalflags();
+ /*
+ * Generate code to load the default settings into the variables.
+ * 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->token )
+ {
+ default:
+ break;
+
+ case token_bool:
+ case token_choice_item:
+ case token_dep_bool:
+ case token_dep_tristate:
+ case token_dep_mbool:
+ case token_tristate:
+ if ( ! vartable[cfg->nameindex].global_written )
+ {
+ printf( "set %s 0\n", vartable[cfg->nameindex].name );
+ vartable[cfg->nameindex].global_written = 1;
+ }
+ break;
+
+ case token_choice_header:
+ printf( "set tmpvar_%d \"(not set)\"\n", -(cfg->nameindex) );
+ break;
+
+ case token_hex:
+ case token_int:
+ if ( ! vartable[cfg->nameindex].global_written )
+ {
+ printf( "set %s %s\n", vartable[cfg->nameindex].name, cfg->value ? cfg->value : "0" );
+ vartable[cfg->nameindex].global_written = 1;
+ }
+ break;
+
+ case token_string:
+ if ( ! vartable[cfg->nameindex].global_written )
+ {
+ printf( "set %s \"%s\"\n", vartable[cfg->nameindex].name, cfg->value );
+ vartable[cfg->nameindex].global_written = 1;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Define to an empty value all other variables (which are never defined)
+ */
+ for ( i = 1; i <= max_varnum; i++ )
+ {
+ if ( ! vartable[i].global_written
+ && strncmp( vartable[i].name, "CONSTANT_", 9 ) )
+ printf( "set %s 4\n", vartable[i].name );
+ }
+
+ /*
+ * Generate a function to write all of the variables to a file.
+ */
+ 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" );
+ 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" );
+ printf( "\tputs $autocfg \"#define AUTOCONF_INCLUDED\"\n" );
+
+ clear_globalflags();
+ for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ {
+ switch ( cfg->token )
+ {
+ default:
+ break;
+
+ case token_bool:
+ case token_choice_header:
+ case token_comment:
+ case token_define_bool:
+ case token_define_hex:
+ case token_define_int:
+ case token_define_string:
+ case token_define_tristate:
+ case token_dep_bool:
+ case token_dep_tristate:
+ case token_dep_mbool:
+ case token_hex:
+ case token_int:
+ case token_string:
+ case token_tristate:
+ generate_writeconfig( cfg );
+ break;
+ }
+ }
+ printf( "\tclose $cfg\n" );
+ printf( "\tclose $autocfg\n" );
+ printf( "}\n\n\n" );
+
+ /*
+ * Generate 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->token == token_choice_header )
+ {
+ for ( cfg1 = cfg->next;
+ cfg1 != NULL && cfg1->token == token_choice_item;
+ cfg1 = cfg1->next )
+ {
+ printf( "\tglobal %s; set %s 0\n",
+ vartable[cfg1->nameindex].name,
+ vartable[cfg1->nameindex].name );
+ }
+ }
+ }
+ printf( "}\n\n\n" );
+
+ printf( "proc update_choices { } {\n" );
+ for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ {
+ if ( cfg->token == token_choice_header )
+ {
+ printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) );
+ printf("\tset tmpvar_%d \"%s\"\n", -(cfg->nameindex), cfg->value);
+ for ( cfg1 = cfg->next;
+ cfg1 != NULL && cfg1->token == token_choice_item;
+ cfg1 = cfg1->next )
+ {
+ printf( "\tglobal %s\n", vartable[cfg1->nameindex].name );
+ printf( "\tif { $%s == 1 } then { set tmpvar_%d \"%s\" }\n",
+ vartable[cfg1->nameindex].name,
+ -(cfg->nameindex), cfg1->label );
+ }
+ }
+ }
+ printf( "}\n\n\n" );
+
+ generate_update_var( scfg, 0 );
+
+ /*
+ * 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 000000000000..241640f23cf3
--- /dev/null
+++ b/scripts/tkparse.c
@@ -0,0 +1,822 @@
+/*
+ * tkparse.c
+ *
+ * Eric Youngdale was the original author of xconfig.
+ * Michael Elizabeth Chastain (mec@shout.net) is the current maintainer.
+ *
+ * Parse a config.in file and translate it to a wish script.
+ * This task has three parts:
+ *
+ * tkparse.c tokenize the input
+ * tkcond.c transform 'if ...' statements
+ * tkgen.c generate output
+ *
+ * Change History
+ *
+ * 7 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+ * - Teach dep_tristate about a few literals, such as:
+ * dep_tristate 'foo' CONFIG_FOO m
+ * Also have it print an error message and exit on some parse failures.
+ *
+ * 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+ * - Don't fclose stdin. Thanks to Tony Hoyle for nailing this one.
+ *
+ * 14 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+ * - Steam-clean this file. I tested this by generating kconfig.tk for
+ * every architecture and comparing it character-for-character against
+ * the output of the old tkparse.
+ *
+ * 23 January 1999, Michael Elizabeth Chastain, <mec@shout.net>
+ * - Remove bug-compatible code.
+ *
+ * 07 July 1999, Andrzej M. Krzysztofowicz, <ankry@mif.pg.gda.pl>
+ * - Submenus implemented,
+ * - plenty of option updating/displaying fixes,
+ * - dep_bool, define_hex, define_int, define_string, define_tristate and
+ * undef implemented,
+ * - dep_tristate fixed to support multiple dependencies,
+ * - handling of variables with an empty value implemented,
+ * - value checking for int and hex fields,
+ * - more checking during condition parsing; choice variables are treated as
+ * all others now,
+ *
+ * TO DO:
+ * - xconfig is at the end of its life cycle. Contact <mec@shout.net> if
+ * you are interested in working on the replacement.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tkparse.h"
+
+static struct kconfig * config_list = NULL;
+static struct kconfig * config_last = NULL;
+static const char * current_file = "<unknown file>";
+static int lineno = 0;
+
+static void do_source( const char * );
+
+#undef strcmp
+int my_strcmp( const char * s1, const char * s2 ) { return strcmp( s1, s2 ); }
+#define strcmp my_strcmp
+
+/*
+ * Report a syntax error.
+ */
+static void syntax_error( const char * msg )
+{
+ fprintf( stderr, "%s: %d: %s\n", current_file, lineno, msg );
+ exit( 1 );
+}
+
+
+
+/*
+ * Find index of a specyfic variable in the symbol table.
+ * Create a new entry if it does not exist yet.
+ */
+#define VARTABLE_SIZE 2048
+struct variable vartable[VARTABLE_SIZE];
+int max_varnum = 0;
+
+int get_varnum( char * name )
+{
+ int i;
+
+ for ( i = 1; i <= max_varnum; i++ )
+ if ( strcmp( vartable[i].name, name ) == 0 )
+ return i;
+ if (max_varnum > VARTABLE_SIZE-1)
+ syntax_error( "Too many variables defined." );
+ vartable[++max_varnum].name = malloc( strlen( name )+1 );
+ strcpy( vartable[max_varnum].name, name );
+ return max_varnum;
+}
+
+
+
+/*
+ * Get a string.
+ */
+static const char * get_string( const char * pnt, char ** label )
+{
+ const char * word;
+
+ word = pnt;
+ for ( ; ; )
+ {
+ if ( *pnt == '\0' || *pnt == ' ' || *pnt == '\t' )
+ break;
+ pnt++;
+ }
+
+ *label = malloc( pnt - word + 1 );
+ memcpy( *label, word, pnt - word );
+ (*label)[pnt - word] = '\0';
+
+ if ( *pnt != '\0' )
+ pnt++;
+ return pnt;
+}
+
+
+
+/*
+ * Get a quoted string.
+ * Insert a '\' before any characters that need quoting.
+ */
+static const char * get_qstring( const char * pnt, char ** label )
+{
+ char quote_char;
+ char newlabel [2048];
+ char * pnt1;
+
+ /* advance to the open quote */
+ for ( ; ; )
+ {
+ if ( *pnt == '\0' )
+ return pnt;
+ quote_char = *pnt++;
+ if ( quote_char == '"' || quote_char == '\'' )
+ break;
+ }
+
+ /* copy into an intermediate buffer */
+ pnt1 = newlabel;
+ for ( ; ; )
+ {
+ if ( *pnt == '\0' )
+ syntax_error( "unterminated quoted string" );
+ if ( *pnt == quote_char && pnt[-1] != '\\' )
+ break;
+
+ /* copy the character, quoting if needed */
+ if ( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']' )
+ *pnt1++ = '\\';
+ *pnt1++ = *pnt++;
+ }
+
+ /* copy the label into a permanent location */
+ *pnt1++ = '\0';
+ *label = (char *) malloc( pnt1 - newlabel );
+ memcpy( *label, newlabel, pnt1 - newlabel );
+
+ /* skip over last quote and next whitespace */
+ pnt++;
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ return pnt;
+}
+
+
+
+/*
+ * Get a quoted or unquoted string. It is recognized by the first
+ * non-white character. '"' and '"' are not allowed inside the string.
+ */
+static const char * get_qnqstring( const char * pnt, char ** label )
+{
+ char quote_char;
+
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+
+ if ( *pnt == '\0' )
+ return pnt;
+ quote_char = *pnt;
+ if ( quote_char == '"' || quote_char == '\'' )
+ return get_qstring( pnt, label );
+ else
+ return get_string( pnt, label );
+}
+
+
+
+/*
+ * Tokenize an 'if' statement condition.
+ */
+static struct condition * tokenize_if( const char * pnt )
+{
+ struct condition * list;
+ struct condition * last;
+ struct condition * prev;
+
+ /* eat the open bracket */
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ if ( *pnt != '[' )
+ syntax_error( "bad 'if' condition" );
+ pnt++;
+
+ list = last = NULL;
+ for ( ; ; )
+ {
+ struct condition * cond;
+
+ /* advance to the next token */
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ if ( *pnt == '\0' )
+ syntax_error( "unterminated 'if' condition" );
+ if ( *pnt == ']' )
+ return list;
+
+ /* allocate a new token */
+ cond = malloc( sizeof(*cond) );
+ memset( cond, 0, sizeof(*cond) );
+ if ( last == NULL )
+ { list = last = cond; prev = NULL; }
+ else
+ { prev = last; last->next = cond; last = cond; }
+
+ /* determine the token value */
+ if ( *pnt == '-' && pnt[1] == 'a' )
+ {
+ if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
+ syntax_error( "incorrect argument" );
+ cond->op = op_and; pnt += 2; continue;
+ }
+
+ if ( *pnt == '-' && pnt[1] == 'o' )
+ {
+ if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
+ syntax_error( "incorrect argument" );
+ cond->op = op_or; pnt += 2; continue;
+ }
+
+ if ( *pnt == '!' && pnt[1] == '=' )
+ {
+ if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
+ syntax_error( "incorrect argument" );
+ cond->op = op_neq; pnt += 2; continue;
+ }
+
+ if ( *pnt == '=' )
+ {
+ if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) )
+ syntax_error( "incorrect argument" );
+ cond->op = op_eq; pnt += 1; continue;
+ }
+
+ if ( *pnt == '!' )
+ {
+ if ( prev && ( prev->op != op_and && prev->op != op_or
+ && prev->op != op_bang ) )
+ syntax_error( "incorrect argument" );
+ cond->op = op_bang; pnt += 1; continue;
+ }
+
+ if ( *pnt == '"' )
+ {
+ const char * word;
+
+ if ( prev && ( prev->op == op_variable || prev->op == op_constant ) )
+ syntax_error( "incorrect argument" );
+ /* advance to the word */
+ pnt++;
+ if ( *pnt == '$' )
+ { cond->op = op_variable; pnt++; }
+ else
+ { cond->op = op_constant; }
+
+ /* find the end of the word */
+ word = pnt;
+ for ( ; ; )
+ {
+ if ( *pnt == '\0' )
+ syntax_error( "unterminated double quote" );
+ if ( *pnt == '"' )
+ break;
+ pnt++;
+ }
+
+ /* store a copy of this word */
+ {
+ char * str = malloc( pnt - word + 1 );
+ memcpy( str, word, pnt - word );
+ str [pnt - word] = '\0';
+ if ( cond->op == op_variable )
+ {
+ cond->nameindex = get_varnum( str );
+ free( str );
+ }
+ else /* op_constant */
+ {
+ cond->str = str;
+ }
+ }
+
+ pnt++;
+ continue;
+ }
+
+ /* unknown token */
+ syntax_error( "bad if condition" );
+ }
+}
+
+
+
+/*
+ * Tokenize a choice list. Choices appear as pairs of strings;
+ * note that I am parsing *inside* the double quotes. Ugh.
+ */
+static const char * tokenize_choices( struct kconfig * cfg_choose,
+ const char * pnt )
+{
+ int default_checked = 0;
+ for ( ; ; )
+ {
+ struct kconfig * cfg;
+ char * buffer = malloc( 64 );
+
+ /* skip whitespace */
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ if ( *pnt == '\0' )
+ return pnt;
+
+ /* allocate a new kconfig line */
+ cfg = malloc( sizeof(*cfg) );
+ memset( cfg, 0, sizeof(*cfg) );
+ if ( config_last == NULL )
+ { config_last = config_list = cfg; }
+ else
+ { config_last->next = cfg; config_last = cfg; }
+
+ /* fill out the line */
+ cfg->token = token_choice_item;
+ cfg->cfg_parent = cfg_choose;
+ pnt = get_string( pnt, &cfg->label );
+ if ( ! default_checked &&
+ ! strncmp( cfg->label, cfg_choose->value, strlen( cfg_choose->value ) ) )
+ {
+ default_checked = 1;
+ free( cfg_choose->value );
+ cfg_choose->value = cfg->label;
+ }
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ pnt = get_string( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ }
+ if ( ! default_checked )
+ syntax_error( "bad 'choice' default value" );
+ return pnt;
+}
+
+
+
+/*
+ * Tokenize one line.
+ */
+static void tokenize_line( const char * pnt )
+{
+ static struct kconfig * last_menuoption = NULL;
+ enum e_token token;
+ struct kconfig * cfg;
+ struct dependency ** dep_ptr;
+ char * buffer = malloc( 64 );
+
+ /* skip white space */
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+
+ /*
+ * categorize the next token
+ */
+
+#define match_token(t, s) \
+ if (strncmp(pnt, s, strlen(s)) == 0) { token = t; pnt += strlen(s); break; }
+
+ token = token_UNKNOWN;
+ switch ( *pnt )
+ {
+ default:
+ break;
+
+ case '#':
+ case '\0':
+ return;
+
+ case 'b':
+ match_token( token_bool, "bool" );
+ break;
+
+ case 'c':
+ match_token( token_choice_header, "choice" );
+ match_token( token_comment, "comment" );
+ break;
+
+ case 'd':
+ match_token( token_define_bool, "define_bool" );
+ match_token( token_define_hex, "define_hex" );
+ match_token( token_define_int, "define_int" );
+ match_token( token_define_string, "define_string" );
+ match_token( token_define_tristate, "define_tristate" );
+ match_token( token_dep_bool, "dep_bool" );
+ match_token( token_dep_mbool, "dep_mbool" );
+ match_token( token_dep_tristate, "dep_tristate" );
+ break;
+
+ case 'e':
+ match_token( token_else, "else" );
+ match_token( token_endmenu, "endmenu" );
+ break;
+
+ case 'f':
+ match_token( token_fi, "fi" );
+ break;
+
+ case 'h':
+ match_token( token_hex, "hex" );
+ break;
+
+ case 'i':
+ match_token( token_if, "if" );
+ match_token( token_int, "int" );
+ break;
+
+ case 'm':
+ match_token( token_mainmenu_name, "mainmenu_name" );
+ match_token( token_mainmenu_option, "mainmenu_option" );
+ break;
+
+ case 's':
+ match_token( token_source, "source" );
+ match_token( token_string, "string" );
+ break;
+
+ case 't':
+ match_token( token_then, "then" );
+ match_token( token_tristate, "tristate" );
+ break;
+
+ case 'u':
+ match_token( token_unset, "unset" );
+ break;
+ }
+
+#undef match_token
+
+ if ( token == token_source )
+ {
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ do_source( pnt );
+ return;
+ }
+
+ if ( token == token_then )
+ {
+ if ( config_last != NULL && config_last->token == token_if )
+ return;
+ syntax_error( "bogus 'then'" );
+ }
+
+#if 0
+ if ( token == token_unset )
+ {
+ fprintf( stderr, "Ignoring 'unset' command\n" );
+ return;
+ }
+#endif
+
+ if ( token == token_UNKNOWN )
+ syntax_error( "unknown command" );
+
+ /*
+ * Allocate an item.
+ */
+ cfg = malloc( sizeof(*cfg) );
+ memset( cfg, 0, sizeof(*cfg) );
+ if ( config_last == NULL )
+ { config_last = config_list = cfg; }
+ else
+ { config_last->next = cfg; config_last = cfg; }
+
+ /*
+ * Tokenize the arguments.
+ */
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+
+ cfg->token = token;
+ switch ( token )
+ {
+ default:
+ syntax_error( "unknown token" );
+
+ case token_bool:
+ case token_tristate:
+ pnt = get_qstring ( pnt, &cfg->label );
+ pnt = get_string ( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ break;
+
+ case token_choice_header:
+ {
+ static int choose_number = 0;
+ char * choice_list;
+
+ pnt = get_qstring ( pnt, &cfg->label );
+ pnt = get_qstring ( pnt, &choice_list );
+ pnt = get_string ( pnt, &cfg->value );
+ cfg->nameindex = -(choose_number++);
+ tokenize_choices( cfg, choice_list );
+ free( choice_list );
+ }
+ break;
+
+ case token_comment:
+ pnt = get_qstring(pnt, &cfg->label);
+ if ( last_menuoption != NULL )
+ {
+ pnt = get_qstring(pnt, &cfg->label);
+ if (cfg->label == NULL)
+ syntax_error( "missing comment text" );
+ last_menuoption->label = cfg->label;
+ last_menuoption = NULL;
+ }
+ break;
+
+ case token_define_bool:
+ case token_define_tristate:
+ pnt = get_string( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N'
+ || pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' )
+ && ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) )
+ {
+ if ( *pnt == 'n' || *pnt == 'N' ) cfg->value = strdup( "CONSTANT_N" );
+ else if ( *pnt == 'y' || *pnt == 'Y' ) cfg->value = strdup( "CONSTANT_Y" );
+ else if ( *pnt == 'm' || *pnt == 'M' ) cfg->value = strdup( "CONSTANT_M" );
+ }
+ else if ( *pnt == '$' )
+ {
+ pnt++;
+ pnt = get_string( pnt, &cfg->value );
+ }
+ else
+ {
+ syntax_error( "unknown define_bool value" );
+ }
+ get_varnum( cfg->value );
+ break;
+
+ case token_define_hex:
+ case token_define_int:
+ pnt = get_string( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ pnt = get_string( pnt, &cfg->value );
+ break;
+
+ case token_define_string:
+ pnt = get_string( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ pnt = get_qnqstring( pnt, &cfg->value );
+ if (cfg->value == NULL)
+ syntax_error( "missing value" );
+ break;
+
+ case token_dep_bool:
+ case token_dep_mbool:
+ case token_dep_tristate:
+ pnt = get_qstring ( pnt, &cfg->label );
+ pnt = get_string ( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+
+ dep_ptr = &(cfg->depend);
+
+ do {
+ *dep_ptr = (struct dependency *) malloc( sizeof( struct dependency ) );
+ (*dep_ptr)->next = NULL;
+
+ if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N'
+ || pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' )
+ && ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) )
+ {
+ /* dep_tristate 'foo' CONFIG_FOO m */
+ if ( pnt[0] == 'Y' || pnt[0] == 'y' )
+ (*dep_ptr)->name = strdup( "CONSTANT_Y" );
+ else if ( pnt[0] == 'N' || pnt[0] == 'n' )
+ (*dep_ptr)->name = strdup( "CONSTANT_N" );
+ else
+ (*dep_ptr)->name = strdup( "CONSTANT_M" );
+ pnt++;
+ get_varnum( (*dep_ptr)->name );
+ }
+ else if ( *pnt == '$' )
+ {
+ pnt++;
+ pnt = get_string( pnt, &(*dep_ptr)->name );
+ get_varnum( (*dep_ptr)->name );
+ }
+ else
+ {
+ syntax_error( "can't handle dep_bool/dep_mbool/dep_tristate condition" );
+ }
+ dep_ptr = &(*dep_ptr)->next;
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ } while ( *pnt );
+
+ /*
+ * Create a conditional for this object's dependencies.
+ */
+ {
+ char fake_if [1024];
+ struct dependency * dep;
+ struct condition ** cond_ptr;
+ int first = 1;
+
+ cond_ptr = &(cfg->cond);
+ for ( dep = cfg->depend; dep; dep = dep->next )
+ {
+ if ( token == token_dep_tristate
+ && ! strcmp( dep->name, "CONSTANT_M" ) )
+ {
+ continue;
+ }
+ if ( first )
+ {
+ first = 0;
+ }
+ else
+ {
+ *cond_ptr = malloc( sizeof(struct condition) );
+ memset( *cond_ptr, 0, sizeof(struct condition) );
+ (*cond_ptr)->op = op_and;
+ cond_ptr = &(*cond_ptr)->next;
+ }
+ *cond_ptr = malloc( sizeof(struct condition) );
+ memset( *cond_ptr, 0, sizeof(struct condition) );
+ (*cond_ptr)->op = op_lparen;
+ if ( token == token_dep_bool )
+ sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"\" ]; then",
+ dep->name, dep->name );
+ else
+ sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" -o \"$%s\" = \"\" ]; then",
+ dep->name, dep->name, dep->name );
+ (*cond_ptr)->next = tokenize_if( fake_if );
+ while ( *cond_ptr )
+ cond_ptr = &(*cond_ptr)->next;
+ *cond_ptr = malloc( sizeof(struct condition) );
+ memset( *cond_ptr, 0, sizeof(struct condition) );
+ (*cond_ptr)->op = op_rparen;
+ cond_ptr = &(*cond_ptr)->next;
+ }
+ }
+ break;
+
+ case token_else:
+ case token_endmenu:
+ case token_fi:
+ break;
+
+ case token_hex:
+ case token_int:
+ pnt = get_qstring ( pnt, &cfg->label );
+ pnt = get_string ( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ pnt = get_string ( pnt, &cfg->value );
+ break;
+
+ case token_string:
+ pnt = get_qstring ( pnt, &cfg->label );
+ pnt = get_string ( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ pnt = get_qnqstring ( pnt, &cfg->value );
+ if (cfg->value == NULL)
+ syntax_error( "missing initial value" );
+ break;
+
+ case token_if:
+ cfg->cond = tokenize_if( pnt );
+ break;
+
+ case token_mainmenu_name:
+ pnt = get_qstring( pnt, &cfg->label );
+ break;
+
+ case token_mainmenu_option:
+ if ( strncmp( pnt, "next_comment", 12 ) == 0 )
+ last_menuoption = cfg;
+ else
+ pnt = get_qstring( pnt, &cfg->label );
+ break;
+
+ case token_unset:
+ pnt = get_string( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ while (*pnt)
+ {
+ cfg->next = (struct kconfig *) malloc( sizeof(struct kconfig) );
+ memset( cfg->next, 0, sizeof(struct kconfig) );
+ cfg = cfg->next;
+ cfg->token = token_unset;
+ pnt = get_string( pnt, &buffer );
+ cfg->nameindex = get_varnum( buffer );
+ while ( *pnt == ' ' || *pnt == '\t' )
+ pnt++;
+ }
+ break;
+ }
+ return;
+}
+
+
+
+/*
+ * Implement the "source" command.
+ */
+static void do_source( const char * filename )
+{
+ char buffer [2048];
+ FILE * infile;
+ const char * old_file;
+ int old_lineno;
+ int offset;
+
+ /* open the file */
+ if ( strcmp( filename, "-" ) == 0 )
+ infile = stdin;
+ else
+ infile = fopen( filename, "r" );
+
+ /* if that failed, try ../filename */
+ if ( infile == NULL )
+ {
+ sprintf( buffer, "../%s", filename );
+ infile = fopen( buffer, "r" );
+ }
+
+ if ( infile == NULL )
+ {
+ sprintf( buffer, "unable to open %s", filename );
+ syntax_error( buffer );
+ }
+
+ /* push the new file name and line number */
+ old_file = current_file;
+ old_lineno = lineno;
+ current_file = filename;
+ lineno = 0;
+
+ /* read and process lines */
+ for ( offset = 0; ; )
+ {
+ char * pnt;
+
+ /* read a line */
+ fgets( buffer + offset, sizeof(buffer) - offset, infile );
+ if ( feof( infile ) )
+ break;
+ lineno++;
+
+ /* strip the trailing return character */
+ pnt = buffer + strlen(buffer) - 1;
+ if ( *pnt == '\n' )
+ *pnt-- = '\0';
+
+ /* eat \ NL pairs */
+ if ( *pnt == '\\' )
+ {
+ offset = pnt - buffer;
+ continue;
+ }
+
+ /* tokenize this line */
+ tokenize_line( buffer );
+ offset = 0;
+ }
+
+ /* that's all, folks */
+ if ( infile != stdin )
+ fclose( infile );
+ current_file = old_file;
+ lineno = old_lineno;
+ return;
+}
+
+
+
+/*
+ * Main program.
+ */
+int main( int argc, const char * argv [] )
+{
+ do_source ( "-" );
+ fix_conditionals ( config_list );
+ dump_tk_script ( config_list );
+ return 0;
+}
diff --git a/scripts/tkparse.h b/scripts/tkparse.h
new file mode 100644
index 000000000000..1ca16b1852e7
--- /dev/null
+++ b/scripts/tkparse.h
@@ -0,0 +1,127 @@
+/*
+ * tkparse.h
+ */
+
+/*
+ * Token types (mostly statement types).
+ */
+
+enum e_token
+{
+ token_UNKNOWN,
+ token_bool,
+ token_choice_header,
+ token_choice_item,
+ token_comment,
+ token_define_bool,
+ token_define_hex,
+ token_define_int,
+ token_define_string,
+ token_define_tristate,
+ token_dep_bool,
+ token_dep_mbool,
+ token_dep_tristate,
+ token_else,
+ token_endmenu,
+ token_fi,
+ token_hex,
+ token_if,
+ token_int,
+ token_mainmenu_name,
+ token_mainmenu_option,
+ token_source,
+ token_string,
+ token_then,
+ token_tristate,
+ token_unset,
+};
+
+/*
+ * Operator types for conditionals.
+ */
+
+enum operator
+{
+ op_eq,
+ op_neq,
+ op_and,
+ op_and1,
+ op_or,
+ op_bang,
+ op_lparen,
+ op_rparen,
+ op_constant,
+ op_variable,
+ op_true,
+ op_false,
+ op_nuked
+};
+
+/*
+ * Conditions come in linked lists.
+ * Some operators take strings:
+ *
+ * op_constant "foo"
+ * op_variable "$ARCH", "$CONFIG_PMAC", "$CONFIG_EXPERIMENTAL"
+ *
+ * Most "$..." constructs refer to a variable which is defined somewhere
+ * in the script. Note that it is legal to test variables which are never
+ * defined, such as variables that are meaningful only on other architectures.
+ */
+
+struct condition
+{
+ struct condition * next;
+ enum operator op;
+ const char * str; /* op_constant */
+ int nameindex; /* op_variable */
+};
+
+/*
+ * Dependency list for dep_bool, dep_mbool, dep_tristate
+ */
+
+struct dependency
+{
+ char * name;
+ struct dependency * next;
+};
+
+/*
+ * A statement from a config.in file
+ */
+
+struct kconfig
+{
+ struct kconfig * next;
+ enum e_token token;
+ int nameindex;
+ char * label;
+ char * value;
+ struct condition * cond;
+ struct dependency * depend; /* token_dep_tristate */
+ struct kconfig * cfg_parent; /* token_choice_item */
+
+ /* used only in tkgen.c */
+ int menu_number;
+ int menu_line;
+ struct kconfig * menu_next;
+};
+
+struct variable
+{
+ char * name;
+ char defined;
+ char global_written;
+};
+
+extern struct variable vartable[];
+extern int max_varnum;
+
+/*
+ * Prototypes
+ */
+
+extern void fix_conditionals ( struct kconfig * scfg ); /* tkcond.c */
+extern void dump_tk_script ( struct kconfig * scfg ); /* tkgen.c */
+extern int get_varnum ( char * name ); /* tkparse.c */
diff --git a/scripts/ver_linux b/scripts/ver_linux
new file mode 100644
index 000000000000..4682d0c7eb50
--- /dev/null
+++ b/scripts/ver_linux
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Before running this script please ensure that your PATH is
+# typical as you use for compilation/istallation. I use
+# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may
+# differ on your system.
+#
+PATH=/sbin:/usr/sbin:/bin:/usr/bin:$PATH
+echo '-- Versions installed: (if some fields are empty or look'
+echo '-- unusual then possibly you have very old versions)'
+uname -a
+insmod -V 2>&1 | awk 'NR==1 {print "Kernel modules ",$NF}'
+echo "Gnu C " `gcc --version`
+make --version 2>&1 | awk -F, '{print $1}' | awk \
+ '/GNU Make/{print "Gnu Make ",$NF}'
+ld -v 2>&1 | awk -F\) '{print $1}' | awk \
+ '/BFD/{print "Binutils ",$NF}'
+ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed -e 's/\.so$//' \
+ | awk -F'[.-]' '{print "Linux C Library " $(NF-2)"."$(NF-1)"."$NF}'
+echo -n "Dynamic linker "
+ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -1
+ls -l /usr/lib/lib{g,stdc}++.so 2>/dev/null | awk -F. \
+ '{print "Linux C++ Library " $4"."$5"."$6}'
+ps --version 2>&1 | awk 'NR==1{print "Procps ", $NF}'
+mount --version | awk -F\- '{print "Mount ", $NF}'
+hostname -V 2>&1 | awk 'NR==1{print "Net-tools ", $NF}'
+# Kbd needs 'loadkeys -h',
+loadkeys -h 2>&1 | awk \
+'(NR==1 && ($3 !~ /option/)) {print "Kbd ", $3}'
+# while console-tools needs 'loadkeys -V'.
+loadkeys -V 2>&1 | awk \
+'(NR==1 && ($2 ~ /console-tools/)) {print "Console-tools ", $3}'
+expr --v 2>&1 | awk 'NR==1{print "Sh-utils ", $NF}'
+X=`cat /proc/modules | sed -e "s/ .*$//"`
+echo "Modules Loaded "$X