[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