mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
New feature: 'typeset -g' as in bash 4.2+
typeset -g allows directly manipulating the attributes of variables at the global level from any context. This feature already exists on bash 4.2 and later. mksh (R50+), yash and zsh have this flag as well, but it's slightly different: it ignores the current local scope, but a parent local scope from a calling function may still be used -- whereas on bash, '-g' always refers to the global scope. Since ksh93 uses static scoping (see III.Q28 at <http://kornshell.com/doc/faq.html>), only the bash behaviour makes sense here. Note that the implementation needs to be done both in nv_setlist() (name.c) and in b_typeset() (typeset.c) because assignments are executed before the typeset built-in itself. Hence also the pre-parsing of typeset options in sh_exec(). src/cmd/ksh93/include/nval.h: - Add new NV_GLOBAL bit flag, using a previously unused bit that still falls within the 32-bit integer range. src/cmd/ksh93/sh/xec.c: sh_exec(): - When pre-parsing typeset flags, make -g pass the NV_GLOBAL flag to the nv_setlist() call that processes shell assignments prior to running the command. src/cmd/ksh93/sh/name.c: nv_setlist(): - When the NV_GLOBAL bit flag is passed, save the current variable tree pointer (sh.var_tree) as well as the current namespace (sh.namespace) and temporarily set the former to the global variable tree (sh.var_base) and the latter to NULL. This makes assignments global and ignores namesapces. src/cmd/ksh93/bltins/typeset.c: - b_typeset(): - Use NV_GLOBAL bit flag for -g. - Allow combining -n with -g, permitting 'typeset -gn var' or 'nameref -g var' to create a global nameref from a function. - Do not allow a nonsensical use of -g when using nested typeset to define member variables of 'typeset -T' types. (Type method functions can still use it as normal.) - setall(): - If NV_GLOBAL is passed, use sh.var_base and deactivate sh.namespace as in nv_setlist(). This allows attributes to be set correctly for global variables. src/cmd/ksh93/tests/{functions,namespace}.sh: - Add regression tests based on reproducers for problems found by @hyenias in preliminary versions of this feature. Resolves: https://github.com/ksh93/ksh/issues/479
This commit is contained in:
parent
f73b8617dd
commit
ea300089a1
11 changed files with 167 additions and 8 deletions
|
|
@ -1341,5 +1341,44 @@ got=$( { "$SHELL" "$tmp/crash_rhbz1117404.ksh"; } 2>&1)
|
|||
((!(e = $?))) || err_exit 'crash while handling function-local trap' \
|
||||
"(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
|
||||
|
||||
# ======
|
||||
# 'typeset -g' should cause the active function scope to be ignored.
|
||||
# https://github.com/ksh93/ksh/issues/479#issuecomment-1140523291
|
||||
if ! command typeset -g x 2>/dev/null
|
||||
then
|
||||
warning "shell does not have 'typeset -g'; skipping those tests"
|
||||
else
|
||||
unset x arr a b c
|
||||
# must specify the length for -X as the default is -X 24 on 32-bit systems and -X 32 on 64-bit systems
|
||||
typeset -A exp=(
|
||||
['x=123; function f { typeset -g x=456; }; function g { typeset x=789; f; }; g; typeset -p x']='x=456'
|
||||
['x=123; function f { typeset -g -i x; }; f; typeset -p x']='typeset -i x=123'
|
||||
['x=123; function f { typeset -g -F x; }; f; typeset -p x']='typeset -F x=123.0000000000'
|
||||
['x=123; function f { typeset -g -E x; }; f; typeset -p x']='typeset -E x=123'
|
||||
['x=123; function f { typeset -g -X24 x; }; f; typeset -p x']='typeset -X 24 x=0x1.ec0000000000000000000000p+6'
|
||||
['x=aBc; function f { typeset -g -u x; }; f; typeset -p x']='typeset -u x=ABC'
|
||||
['x=aBc; function f { typeset -g -l x; }; f; typeset -p x']='typeset -l x=abc'
|
||||
['x=aBc; function f { typeset -g -L x; }; f; typeset -p x']='typeset -L 3 x=aBc'
|
||||
['x=aBc; function f { typeset -g -R x; }; f; typeset -p x']='typeset -R 3 x=aBc'
|
||||
['x=aBc; function f { typeset -g -Z x; }; f; typeset -p x']='typeset -Z 3 -R 3 x=aBc'
|
||||
['x=aBc; function f { typeset -g -L2 x; }; f; typeset -p x']='typeset -L 2 x=aB'
|
||||
['x=aBc; function f { typeset -g -R2 x; }; f; typeset -p x']='typeset -R 2 x=Bc'
|
||||
['x=aBc; function f { typeset -g -Z2 x; }; f; typeset -p x']='typeset -Z 2 -R 2 x=Bc'
|
||||
['x=8; function f { typeset -g -i2 x; }; f; typeset -p x']='typeset -i 2 x=2#1000'
|
||||
['x=8; function f { typeset -g -i8 x; }; f; typeset -p x']='typeset -i 8 x=8#10'
|
||||
['arr=(a b c); function f { typeset -g -i arr[1]=(1 2 3); }; f; typeset -p arr']='typeset -a -i arr=(0 (1 2 3) 0)'
|
||||
['arr=(a b c); function f { typeset -g -F arr[1]=(1 2 3); }; f; typeset -p arr']='typeset -a -F arr=(0.0000000000 (1.0000000000 2.0000000000 3.0000000000) 0.0000000000)'
|
||||
['arr=(a b c); function f { typeset -g -E arr[1]=(1 2 3); }; f; typeset -p arr']='typeset -a -E arr=(0 (1 2 3) 0)'
|
||||
['arr=(a b c); function f { typeset -g -X24 arr[1]=(1 2 3); }; f; typeset -p arr']='typeset -a -X 24 arr=(0x0.000000000000000000000000p+0 (0x1.000000000000000000000000p+0 0x1.000000000000000000000000p+1 0x1.800000000000000000000000p+1) 0x0.000000000000000000000000p+0)'
|
||||
)
|
||||
for cmd in "${!exp[@]}"
|
||||
do
|
||||
got=$(set +x; eval "$cmd" 2>&1)
|
||||
[[ $got == "${exp[$cmd]}" ]] || err_exit "typeset -g in $(printf %q "$cmd") failed to activate global" \
|
||||
"scope from ksh function (expected $(printf %q "${exp[$cmd]}"), got $(printf %q "$got"))"
|
||||
done
|
||||
unset exp
|
||||
fi
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue