[I wrote]
> Mutating the language, long-term, so that it looks less like sh and
> more like a specialised language, is IMO a worthy goal. And I think
> it can be done. The main thing to deal with is adding an
> alternative syntax for 'if' statements which doesn't look like
> test(1). More about that in a separate message.
I've come up with syntax I think I'm happy with. It supports most of
the current [ ] based if statement semantics, can be implemented in
shell, and (most importantly for me) drops those $ signs. This lays
the groundwork for stuff like better error checking and auto
(EXPERIMENTAL) tags.
I made a proof-of-concept patch for Menuconfig. The Configure patch
would be very similar; God only knows what xconfig or mconfig would
require.
I've reused the syntax for a dependency line (the tail end of a
dep_bool / dep_mbool / dep_tristate), like so:
if_dep <i>dependency line</i>
...
endif
If the dependency line evaluates to 'm' or 'y', the body is executed.
Now with our current dep_* syntax, this isn't very powerful. I've
made a few extensions which are, I believe, almost enough[*] to
displace the current use of test(1)-based 'if' statements. Some of
this syntax is not really needed for dep_* lines, but I *really* like
having a single backend function for all of dep_bool, dep_tristate and
if_dep.
[*] "almost enough" because I haven't implemented an 'else'
directive. It would be trivial, but I'm not sure what to call it.
'else' itself is a shell primitive, so the shell-based parsers
(Configure, Menuconfig) wouldn't like it.
* '$CONFIG_FOO' can and should be replaced with 'CONFIG_FOO' without
the $. My current patch accepts both; eventually we might drop
backwards compatibility.
* !CONFIG_FOO negates sense: !y==n, !n==y, !==y, !m==m. The last
!m==m is due to Roman's observation that it is useful to exclude two
things from both being Y while allowing them to both be M.
* 'or' placed between dependencies functions as a logical OR, and
takes very low precedence. This complements the implicit AND
performed between every pair of dependencies.
x or x -> x, for any x
n or m == m or n -> m
n or y == y or n -> y
m or y == y or m -> y
* A=B evaluates to either Y or N, depending on whether A is logically
equivalent to B. It has higher precedence than the ! operator.
Thus:
CONFIG_FOO=m evaluates to 'y' if CONFIG_FOO is m, 'n' otherwise
CONFIG_BAR=n evaluates to 'y' if CONFIG_BAR is n or empty, 'n' otherwise
!CONFIG_BAZ=y evaluates to 'n' if CONFIG_BAZ is y, 'y' otherwise
This syntax is fully backward-compatible. Examples of use:
if_dep CONFIG_X86 or CONFIG_X86_64 or CONFIG_IA64
bool 'ACPI support' CONFIG_ACPI
endif
if_dep CONFIG_SOUND !CONFIG_SOUND_ALSA
source sound/oss/Config.in
endif
dep_tristate 'Adaptec (new driver)' CONFIG_AIC7XXX_NEW !CONFIG_AIC7XXX_OLD
dep_tristate 'Adaptec (old driver)' CONFIG_AIC7XXX_OLD !CONFIG_AIC7XXX_NEW
The one thing I wanted to specify but didn't is an 'else' statement.
The problem is that I can't think what to call it - can't use 'else'
because the shell-based parsers (Configure, Menuconfig) will choke on
it. Any ideas?
Any other comments? Am I going in totally the wrong direction?
Peter
--- 2.5.31/scripts/Menuconfig 2002-06-09 00:27:32.000000000 -0500
+++ 2.5.31w/scripts/Menuconfig 2002-08-14 21:00:27.000000000 -0500
@@ -73,7 +73,10 @@
# - Support for multiple conditions in dep_tristate().
# - Implemented new functions: define_tristate(), define_int(), define_hex(),
# define_string(), dep_bool().
-#
+#
+# 14 Aug 2002, Peter Samuelson <[EMAIL PROTECTED]>
+# - add lots of new syntax for dependencies in 'dep_*' functions
+# - also use this syntax for a new 'if_dep' / 'endif' primitive
#
@@ -112,6 +115,67 @@
eval info="\$INFO_$1"
}
+
+# Reduce a dependency line down to a single char [ymn].
+# Terms are implicitly ANDed together: 'y m' = 'm y' = m, '... n' = 'n ...' = n
+# Each term can be:
+# 'y', 'm', 'n' interpreted as-is
+# 'CONFIG_FOO' reduces to value of CONFIG_FOO, or 'n' if unset
+# 'or' OR operator, lower precedence than the implicit AND
+# specifics: 'y or ...' = '... or y' = y
+# if no 'y': 'm or ...' = '... or m' = m
+# term=value tested for equality, replaced with 'y' or 'n'
+# !term "negate" value of term: y->n, n->y, m->m, ''->y
+# Note that there is no grouping construct.
+# Use boolean transforms, or nest conditionals.
+function dep_calc () {
+ local neg arg ordep
+ if [ "$nest_ifdep" = n ]; then
+ cur_dep=n;
+ return 1;
+ fi
+ ordep=n
+ cur_dep=y # return value
+ for arg; do
+ neg=;
+ case "$arg" in
+ or)
+ case $ordep in
+ n) ordep=$cur_dep ;;
+ m) [ $cur_dep = y ] && ordep=y ;;
+ esac
+ cur_dep=y; continue ;;
+ !*)
+ neg=N; arg=${arg#?} ;;
+ esac
+ case "$arg" in
+ 'CONFIG_'*) eval arg=\$$arg ;;
+ esac
+ case "$arg" in
+ y=y | m=m | n=n | n= | =n) arg=y ;;
+ *=*) arg=n ;;
+ esac
+ case "$cur_dep/$neg/$arg" in
+ y//m | y/N/m) cur_dep=m ;;
+ *//n | */N/y) cur_dep=n ;;
+ esac
+ done
+ case "$cur_dep/$ordep" in
+ n/* | m/y) cur_dep=$ordep ;;
+ esac
+}
+
+function if_dep () {
+ dep_calc "$@"
+ nest_stack="$nest_ifdep $nest_stack"
+ nest_ifdep=$cur_dep
+}
+
+function endif () {
+ nest_ifdep=${nest_stack%%' '*}
+ nest_stack=${nest_stack#*' '}
+}
+
#
# Load the functions used by the config.in files.
#
@@ -127,6 +191,7 @@
# Additional comments
#
function comment () {
+ dep_calc || return
comment_ctr=$[ comment_ctr + 1 ]
echo -ne "': $comment_ctr' '--- $1' " >>MCmenu
}
@@ -135,22 +200,27 @@
# Define a boolean to a specific value.
#
function define_bool () {
+ dep_calc || return
eval $1=$2
}
function define_tristate () {
+ dep_calc || return
eval $1=$2
}
function define_hex () {
+ dep_calc || return
eval $1=$2
}
function define_int () {
+ dep_calc || return
eval $1=$2
}
function define_string () {
+ dep_calc || return
eval $1="$2"
}
@@ -159,6 +229,7 @@
# which calls our local bool function.
#
function bool () {
+ dep_calc || return
set_x_info "$2" "n"
case $x in
@@ -178,6 +249,7 @@
# Collapses to a boolean (Yes/No) if module support is disabled.
#
function tristate () {
+ dep_calc || return
if [ "$CONFIG_MODULES" != "y" ]
then
bool "$1" "$2"
@@ -210,28 +282,13 @@
# 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
+ ques=$1 var=$2; shift 2
+ dep_calc "$@" || return
+ case $cur_dep in
+ y) tristate "$ques" "$var" ;;
+ m) mod_bool "$ques" "$var" ;;
+ n) define_tristate "$var" n ;;
+ esac
}
#
@@ -239,49 +296,28 @@
# (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
+ ques=$1 var=$2; shift 2
+ dep_calc "$@" || return
+ case $cur_dep in
+ y) bool "$ques" "$var" ;;
+ *) define_bool "$var" n ;;
+ esac
}
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
+ ques=$1 var=$2; shift 2
+ dep_calc "$@" || return
+ case $cur_dep in
+ y|m) bool "$ques" "$var" ;;
+ n) define_bool "$var" n ;;
+ esac
}
#
# Add a menu item which will call our local int function.
#
function int () {
+ dep_calc || return
set_x_info "$2" "$3"
echo -ne "'$2' '($x) $1$info' " >>MCmenu
@@ -293,6 +329,7 @@
# Add a menu item which will call our local hex function.
#
function hex () {
+ dep_calc || return
set_x_info "$2" "$3"
x=${x##*[x,X]}
@@ -305,6 +342,7 @@
# Add a menu item which will call our local string function.
#
function string () {
+ dep_calc || return
set_x_info "$2" "$3"
echo -ne "'$2' ' $1: \"$x\"$info' " >>MCmenu
@@ -316,6 +354,7 @@
# Add a menu item which will call our local One-of-Many choice list.
#
function choice () {
+ dep_calc || return
#
# Need to remember params cause they're gonna get reset.
#
@@ -1066,90 +1105,81 @@
# Nested function definitions, YIPEE!
#
function bool () {
+ dep_calc || return
set_x_info "$2" "n"
eval define_bool "$2" "$x"
}
function tristate () {
+ dep_calc || return
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
+ var=$2; shift 2
+ dep_calc "$@" || return
+ set_x_info "$var" "n"
+ case $cur_dep$x in
+ my) x=m ;;
+ n*) x=n ;;
+ esac
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
+ var=$2; shift 2
+ dep_calc "$@" || return
+ set_x_info "$var" "n"
+ [ $cur_dep = y ] || x=n
define_bool "$var" "$x"
}
function dep_mbool () {
+ var=$2; shift 2
+ dep_calc "$@" || return
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
+ [ $cur_dep = n ] && x=n
define_bool "$var" "$x"
}
function int () {
+ dep_calc || return
set_x_info "$2" "$3"
echo "$2=$x" >>$CONFIG
echo "#define $2 ($x)" >>$CONFIG_H
}
function hex () {
+ dep_calc || return
set_x_info "$2" "$3"
echo "$2=$x" >>$CONFIG
echo "#define $2 0x${x##*[x,X]}" >>$CONFIG_H
}
function string () {
+ dep_calc || return
set_x_info "$2" "$3"
echo "$2=\"$x\"" >>$CONFIG
echo "#define $2 \"$x\"" >>$CONFIG_H
}
function define_hex () {
+ dep_calc || return
eval $1="$2"
echo "$1=$2" >>$CONFIG
echo "#define $1 0x${2##*[x,X]}" >>$CONFIG_H
}
function define_int () {
+ dep_calc || return
eval $1="$2"
echo "$1=$2" >>$CONFIG
echo "#define $1 ($2)" >>$CONFIG_H
}
function define_string () {
+ dep_calc || return
eval $1="$2"
echo "$1=\"$2\"" >>$CONFIG
echo "#define $1 \"$2\"" >>$CONFIG_H
@@ -1160,6 +1190,7 @@
}
function define_tristate () {
+ dep_calc || return
eval $1="$2"
case "$2" in
@@ -1188,6 +1219,7 @@
}
function choice () {
+ dep_calc || return
#
# Find the first choice that's already set to 'y'
#
@@ -1236,6 +1268,7 @@
}
function mainmenu_option () {
+ dep_calc || return
comment_is_option=TRUE
}
@@ -1244,6 +1277,7 @@
}
function comment () {
+ dep_calc || return
if [ "$comment_is_option" ]
then
comment_is_option=
-------------------------------------------------------
This sf.net email is sponsored by: Dice - The leading online job board
for high-tech professionals. Search and apply for tech jobs today!
http://seeker.dice.com/seeker.epl?rel_code=31
_______________________________________________
kbuild-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/kbuild-devel