mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-24 23:14:14 +00:00
Many compile-time options were broken so that they could not be turned off without causing compile errors and/or regression test failures. This commit now allows the following to be disabled: SHOPT_2DMATCH # two dimensional ${.sh.match} for ${var//pat/str} SHOPT_BGX # one SIGCHLD trap per completed job SHOPT_BRACEPAT # C-shell {...,...} expansions (, required) SHOPT_ESH # emacs/gmacs edit mode SHOPT_HISTEXPAND # csh-style history file expansions SHOPT_MULTIBYTE # multibyte character handling SHOPT_NAMESPACE # allow namespaces SHOPT_STATS # add .sh.stats variable SHOPT_VSH # vi edit mode The following still break ksh when disabled: SHOPT_FIXEDARRAY # fixed dimension indexed array SHOPT_RAWONLY # make viraw the only vi mode SHOPT_TYPEDEF # enable typeset type definitions Compiling without SHOPT_RAWONLY just gives four regression test failures in pty.sh, but turning off SHOPT_FIXEDARRAY and SHOPT_TYPEDEF causes compilation to fail. I've managed to tweak the code to make it compile without those two options, but then dozens of regression test failures occur, often in things nothing directly to do with those options. It looks like the separation between the code for these options and the rest was never properly maintained. Making it possible to disable SHOPT_FIXEDARRAY and SHOPT_TYPEDEF may involve major refactoring and testing and may not be worth it. This commit has far too many tweaks to list. Notables fixes are: src/cmd/ksh93/data/builtins.c, src/cmd/ksh93/data/options.c: - Do not compile in the shell options and documentation for disabled features (braceexpand, emacs/gmacs, vi/viraw), so the shell is not left with no-op options and inaccurate self-doc. src/cmd/ksh93/data/lexstates.c: - Comment the state tables to associte them with their IDs. - In the ST_MACRO table (sh_lexstate9[]), do not make the S_BRACE state for position 123 (ASCII for '{') conditional upon SHOPT_BRACEPAT (brace expansion), otherwise disabling this causes glob patterns of the form {3}(x) (matching 3 x'es) to stop working as well -- and that is ksh globbing, not brace expansion. src/cmd/ksh93/edit/edit.c: ed_read(): - Fixed a bug: SIGWINCH was not handled by the gmacs edit mode. src/cmd/ksh93/sh/name.c: nv_putval(): - The -L/-R left/right adjustment options to typeset do not count zero-width characters. This is the behaviour with SHOPT_MULTIBYTE enabled, regardless of locale. Of course, what a zero-width character is depends on the locale, but control characters are always considered zero-width. So, to avoid a regression, add some fallback code for non-SHOPT_MULTIBYTE builds that skips ASCII control characters (as per iscntrl(3)) so they are still considered to have zero width. src/cmd/ksh93/tests/shtests: - Export the SHOPT_* macros from SHOPT.sh to the tests as environment variables, so the tests can check for them and decide whether or how to run tests based on the compile-time options that the tested binary was presumably compiled with. - Do not run the C.UTF-8 tests if SHOPT_MULTIBYTE is not enabled. src/cmd/ksh93/tests/*.sh: - Add a bunch of checks for SHOPT_* env vars. Since most should have a value 0 (off) or 1 (on), the form ((SHOPT_FOO)) is a convenient way to use them as arithmetic booleans. .github/workflows/ci.yml: - Make GitHub do more testing: run two locale tests (Dutch and Japanese UTF-8 locales), then disable all the SHOPTs that we can currently disable, recompile ksh, and run the tests again.
380 lines
11 KiB
Bash
Executable file
380 lines
11 KiB
Bash
Executable file
########################################################################
|
|
# #
|
|
# This software is part of the ast package #
|
|
# Copyright (c) 1982-2012 AT&T Intellectual Property #
|
|
# and is licensed under the #
|
|
# Eclipse Public License, Version 1.0 #
|
|
# by AT&T Intellectual Property #
|
|
# #
|
|
# A copy of the License is available at #
|
|
# http://www.eclipse.org/org/documents/epl-v10.html #
|
|
# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
|
|
# #
|
|
# Information and Software Systems Research #
|
|
# AT&T Research #
|
|
# Florham Park NJ #
|
|
# #
|
|
# David Korn <dgk@research.att.com> #
|
|
# #
|
|
########################################################################
|
|
function err_exit
|
|
{
|
|
print -u2 -r $'\t'"${Command}[$1] ${@:2}"
|
|
((Errors++))
|
|
}
|
|
alias err_exit='err_exit $LINENO'
|
|
|
|
Command=${0##*/}
|
|
integer aware=0 contrary=0 Errors=0 ignorant=0
|
|
|
|
[[ -d $tmp && -w $tmp && $tmp == "$PWD" ]] || { err\_exit "$LINENO" '$tmp not set; run this from shtests. Aborting.'; exit 1; }
|
|
|
|
function test_glob
|
|
{
|
|
typeset lineno expected drop arg got sep op val add del
|
|
lineno=$1
|
|
shift
|
|
if [[ $1 == --* ]]
|
|
then del=${1#--}
|
|
shift
|
|
fi
|
|
if [[ $1 == ++* ]]
|
|
then add=${1#++}
|
|
shift
|
|
fi
|
|
expected=$1
|
|
shift
|
|
if (( contrary ))
|
|
then if [[ $expected == "<Beware> "* ]]
|
|
then expected=${expected#"<Beware> "}
|
|
expected="$expected <Beware>"
|
|
fi
|
|
if [[ $expected == *"<aXb> <abd>"* ]]
|
|
then expected=${expected/"<aXb> <abd>"/"<abd> <aXb>"}
|
|
fi
|
|
fi
|
|
for arg
|
|
do got="$got$sep<$arg>"
|
|
sep=" "
|
|
done
|
|
if (( ignorant && aware ))
|
|
then if [[ $del ]]
|
|
then got="<$del> $got"
|
|
fi
|
|
if [[ $add ]]
|
|
then expected="<$add> $expected"
|
|
fi
|
|
fi
|
|
if [[ $got != "$expected" ]]
|
|
then 'err_exit' $lineno "glob -- expected '$expected', got '$got'"
|
|
fi
|
|
}
|
|
alias test_glob='test_glob $LINENO'
|
|
|
|
function test_case
|
|
{
|
|
typeset lineno expected subject pattern got
|
|
lineno=$1 expected=$2 subject=$3 pattern=$4
|
|
eval "
|
|
case $subject in
|
|
$pattern) got='<match>' ;;
|
|
*) got='<nomatch>' ;;
|
|
esac
|
|
"
|
|
if [[ $got != "$expected" ]]
|
|
then 'err_exit' $lineno "case $subject in $pattern) -- expected '$expected', got '$got'"
|
|
fi
|
|
}
|
|
alias test_case='test_case $LINENO'
|
|
|
|
unset undefined
|
|
|
|
export LC_COLLATE=C
|
|
touch B b
|
|
set -- *
|
|
case $* in
|
|
'b B') contrary=1 ;;
|
|
b|B) ignorant=1 ;;
|
|
esac
|
|
set -- $(LC_ALL=C sh -c 'echo [a-c]')
|
|
case $* in
|
|
B) aware=1 ;;
|
|
esac
|
|
rm -rf *
|
|
|
|
touch a b c d abc abd abe bb bcd ca cb dd de Beware
|
|
mkdir bdir
|
|
|
|
test_glob '<a> <abc> <abd> <abe> <X*>' a* X*
|
|
test_glob '<a> <abc> <abd> <abe>' \a*
|
|
|
|
if ( set --nullglob ) 2>/dev/null
|
|
then
|
|
set --nullglob
|
|
|
|
test_glob '<a> <abc> <abd> <abe>' a* X*
|
|
|
|
set --nonullglob
|
|
fi
|
|
|
|
if ( set --failglob ) 2>/dev/null
|
|
then
|
|
set --failglob
|
|
mkdir tmp
|
|
touch tmp/l1 tmp/l2 tmp/l3
|
|
|
|
test_glob '' tmp/l[12] tmp/*4 tmp/*3
|
|
test_glob '' tmp/l[12] tmp/*4 tmp/*3
|
|
|
|
rm -r tmp
|
|
set --nofailglob
|
|
fi
|
|
|
|
test_glob '<bdir/>' b*/
|
|
test_glob '<*>' \*
|
|
test_glob '<a*>' 'a*'
|
|
test_glob '<a*>' a\*
|
|
test_glob '<c> <ca> <cb> <a*> <*q*>' c* a\* *q*
|
|
test_glob '<**>' "*"*
|
|
test_glob '<**>' \**
|
|
test_glob '<\.\./*/>' "\.\./*/"
|
|
test_glob '<s/\..*//>' 's/\..*//'
|
|
test_glob '</^root:/{s/^[!:]*:[!:]*:\([!:]*\).*$/\1/>' "/^root:/{s/^[!:]*:[!:]*:\([!:]*\).*"'$'"/\1/"
|
|
test_glob '<abc> <abd> <abe> <bb> <cb>' [a-c]b*
|
|
test_glob ++Beware '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>' [a-y]*[!c]
|
|
test_glob '<abd> <abe>' a*[!c]
|
|
|
|
touch a-b aXb
|
|
|
|
test_glob '<a-b> <aXb>' a[X-]b
|
|
|
|
touch .x .y
|
|
|
|
test_glob --Beware '<Beware> <d> <dd> <de>' [!a-c]*
|
|
|
|
if mkdir a\*b 2>/dev/null
|
|
then
|
|
touch a\*b/ooo
|
|
|
|
test_glob '<a*b/ooo>' a\*b/*
|
|
test_glob '<a*b/ooo>' a\*?/*
|
|
test_case '<match>' '!7' '*\!*'
|
|
test_case '<match>' 'r.*' '*.\*'
|
|
test_glob '<abc>' a[b]c
|
|
test_glob '<abc>' a["b"]c
|
|
test_glob '<abc>' a[\b]c
|
|
test_glob '<abc>' a?c
|
|
test_case '<match>' 'abc' 'a"b"c'
|
|
test_case '<match>' 'abc' 'a*c'
|
|
test_case '<nomatch>' 'abc' '"a?c"'
|
|
test_case '<nomatch>' 'abc' 'a\*c'
|
|
test_case '<nomatch>' 'abc' 'a\[b]c'
|
|
test_case '<match>' '"$undefined"' '""'
|
|
test_case '<match>' 'abc' 'a["\b"]c'
|
|
|
|
rm -rf mkdir a\*b
|
|
fi
|
|
|
|
mkdir man
|
|
mkdir man/man1
|
|
touch man/man1/sh.1
|
|
|
|
test_glob '<man/man1/sh.1>' */man*/sh.*
|
|
test_glob '<man/man1/sh.1>' $(echo */man*/sh.*)
|
|
test_glob '<man/man1/sh.1>' "$(echo */man*/sh.*)"
|
|
|
|
test_case '<match>' 'abc' 'a***c'
|
|
test_case '<match>' 'abc' 'a*****?c'
|
|
test_case '<match>' 'abc' '?*****??'
|
|
test_case '<match>' 'abc' '*****??'
|
|
test_case '<match>' 'abc' '*****??c'
|
|
test_case '<match>' 'abc' '?*****?c'
|
|
test_case '<match>' 'abc' '?***?****c'
|
|
test_case '<match>' 'abc' '?***?****?'
|
|
test_case '<match>' 'abc' '?***?****'
|
|
test_case '<match>' 'abc' '*******c'
|
|
test_case '<match>' 'abc' '*******?'
|
|
test_case '<match>' 'abcdecdhjk' 'a*cd**?**??k'
|
|
test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k'
|
|
test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??k***'
|
|
test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k'
|
|
test_case '<match>' 'abcdecdhjk' 'a**?**cd**?**??***k**'
|
|
test_case '<match>' 'abcdecdhjk' 'a****c**?**??*****'
|
|
test_case '<match>' "'-'" '[-abc]'
|
|
test_case '<match>' "'-'" '[abc-]'
|
|
test_case '<match>' "'\\'" '\\'
|
|
test_case '<match>' "'\\'" '[\\]'
|
|
test_case '<match>' "'\\'" "'\\'"
|
|
test_case '<match>' "'['" '[[]'
|
|
test_case '<match>' '[' '[[]'
|
|
test_case '<match>' "'['" '['
|
|
test_case '<match>' '[' '['
|
|
test_case '<match>' "'[abc'" "'['*"
|
|
test_case '<nomatch>' "'[abc'" '[*'
|
|
test_case '<match>' '[abc' "'['*"
|
|
test_case '<nomatch>' '[abc' '[*'
|
|
test_case '<match>' 'abd' "a[b/c]d"
|
|
test_case '<match>' 'a/d' "a[b/c]d"
|
|
test_case '<match>' 'acd' "a[b/c]d"
|
|
test_case '<match>' "']'" '[]]'
|
|
test_case '<match>' "'-'" '[]-]'
|
|
test_case '<match>' 'p' '[a-\z]'
|
|
test_case '<match>' '"/tmp"' '[/\\]*'
|
|
test_case '<nomatch>' 'abc' '??**********?****?'
|
|
test_case '<nomatch>' 'abc' '??**********?****c'
|
|
test_case '<nomatch>' 'abc' '?************c****?****'
|
|
test_case '<nomatch>' 'abc' '*c*?**'
|
|
test_case '<nomatch>' 'abc' 'a*****c*?**'
|
|
test_case '<nomatch>' 'abc' 'a********???*******'
|
|
test_case '<nomatch>' "'a'" '[]'
|
|
test_case '<nomatch>' 'a' '[]'
|
|
test_case '<nomatch>' "'['" '[abc'
|
|
test_case '<nomatch>' '[' '[abc'
|
|
|
|
test_glob ++Beware '<b> <bb> <bcd> <bdir>' b*
|
|
test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
|
|
|
|
if ( set --nocaseglob ) 2>/dev/null
|
|
then
|
|
set --nocaseglob
|
|
|
|
test_glob '<Beware> <b> <bb> <bcd> <bdir>' b*
|
|
test_glob '<Beware> <b> <bb> <bcd> <bdir>' [b]*
|
|
test_glob '<Beware> <b> <bb> <bcd> <bdir>' [bB]*
|
|
|
|
set --nonocaseglob
|
|
fi
|
|
|
|
if ( set -f ) 2>/dev/null
|
|
then
|
|
set -f
|
|
|
|
test_glob '<*>' *
|
|
|
|
set +f
|
|
fi
|
|
|
|
if ( set --noglob ) 2>/dev/null
|
|
then
|
|
set --noglob
|
|
|
|
test_glob '<*>' *
|
|
|
|
set --glob
|
|
fi
|
|
|
|
FIGNORE='@(.*|*)'
|
|
test_glob '<*>' *
|
|
|
|
FIGNORE='@(.*|*c|*e|?)'
|
|
test_glob '<a-b> <aXb> <abd> <bb> <bcd> <bdir> <ca> <cb> <dd> <man>' *
|
|
|
|
FIGNORE='@(.*|*b|*d|?)'
|
|
test_glob '<Beware> <abc> <abe> <bdir> <ca> <de> <man>' *
|
|
|
|
FIGNORE=
|
|
test_glob '<man/man1/sh.1>' */man*/sh.*
|
|
test_glob '<.x> <.y> <Beware> <a> <a-b> <aXb> <abc> <abd> <abe> <b> <bb> <bcd> <bdir> <c> <ca> <cb> <d> <dd> <de> <man>' *
|
|
test_glob '<.x> <.y>' .*
|
|
|
|
FIGNORE='@(*[abcd]*)'
|
|
test_glob '<.x> <.y>' *
|
|
test_glob '<.x> <.y>' .*
|
|
|
|
unset FIGNORE
|
|
test_glob '<bb> <ca> <cb> <dd> <de>' ??
|
|
test_glob '<man/man1/sh.1>' */man*/sh.*
|
|
test_glob '<Beware> <a> <a-b> <aXb> <abc> <abd> <abe> <b> <bb> <bcd> <bdir> <c> <ca> <cb> <d> <dd> <de> <man>' *
|
|
test_glob '<.x> <.y>' .*
|
|
|
|
GLOBIGNORE='.*:*'
|
|
set -- *
|
|
if [[ $1 == '*' ]]
|
|
then
|
|
GLOBIGNORE='.*:*c:*e:?'
|
|
test_glob '<>' *
|
|
|
|
GLOBIGNORE='.*:*b:*d:?'
|
|
test_glob '<>' *
|
|
|
|
unset GLOBIGNORE
|
|
test_glob '<>' *
|
|
test_glob '<man/man1/sh.1>' */man*/sh.*
|
|
|
|
GLOBIGNORE=
|
|
test_glob '<man/man1/sh.1>' */man*/sh.*
|
|
fi
|
|
unset GLOBIGNORE
|
|
|
|
function test_sub
|
|
{
|
|
x='${subject'$2'}'
|
|
eval g=$x
|
|
if [[ "$g" != "$3" ]]
|
|
then 'err_exit' $1 subject="'$subject' $x failed, expected '$3', got '$g'"
|
|
fi
|
|
}
|
|
alias test_sub='test_sub $LINENO'
|
|
|
|
set --noglob
|
|
((SHOPT_BRACEPAT)) && set --nobraceexpand
|
|
|
|
subject='A regular expressions test'
|
|
|
|
test_sub '/e/#' 'A r#gular expressions test'
|
|
test_sub '//e/#' 'A r#gular #xpr#ssions t#st'
|
|
test_sub '/[^e]/#' '# regular expressions test'
|
|
test_sub '//[^e]/#' '###e######e###e########e##'
|
|
test_sub '/+(e)/#' 'A r#gular expressions test'
|
|
test_sub '//+(e)/#' 'A r#gular #xpr#ssions t#st'
|
|
test_sub '/@-(e)/#' 'A r#gular expressions test'
|
|
test_sub '//@-(e)/#' 'A r#gular #xpr#ssions t#st'
|
|
test_sub '/?(e)/#' '#A regular expressions test'
|
|
test_sub '//?(e)/#' '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
|
|
test_sub '/*(e)/#' '#A regular expressions test'
|
|
test_sub '//*(e)/#' '#A# #r#g#u#l#a#r# #x#p#r#s#s#i#o#n#s# #t#s#t#'
|
|
test_sub '//@(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
|
|
test_sub '//@-(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
|
|
test_sub '//+(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
|
|
test_sub '//+-(e)/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
|
|
test_sub '//@(+(e))/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
|
|
test_sub '//@(+-(e))/[\1]' 'A r[e]gular [e]xpr[e]ssions t[e]st'
|
|
test_sub '//-(e)/#' 'A regular expressions test'
|
|
test_sub '//--(e)/#' 'A regular expressions test'
|
|
test_sub '//?(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
|
|
test_sub '//{0,1}(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
|
|
test_sub '//*(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
|
|
test_sub '//{0,}(e)/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
|
|
test_sub '//@(?(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
|
|
test_sub '//@({0,1}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
|
|
test_sub '//@(*(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
|
|
test_sub '//@({0,}(e))/[\1]' '[]A[] []r[e]g[]u[]l[]a[]r[] [e]x[]p[]r[e]s[]s[]i[]o[]n[]s[] []t[e]s[]t[]'
|
|
test_sub '/?-(e)/#' '#A regular expressions test'
|
|
test_sub '/@(?-(e))/[\1]' '[]A regular expressions test'
|
|
test_sub '/!(e)/#' '#'
|
|
test_sub '//!(e)/#' '#'
|
|
test_sub '/@(!(e))/[\1]' '[A regular expressions test]'
|
|
test_sub '//@(!(e))/[\1]' '[A regular expressions test]'
|
|
|
|
subject='e'
|
|
|
|
test_sub '/!(e)/#' '#e'
|
|
test_sub '//!(e)/#' '#e#'
|
|
test_sub '/!(e)/[\1]' '[]e'
|
|
test_sub '//!(e)/[\1]' '[]e[]'
|
|
test_sub '/@(!(e))/[\1]' '[]e'
|
|
test_sub '//@(!(e))/[\1]' '[]e[]'
|
|
|
|
subject='a'
|
|
|
|
test_sub '/@(!(a))/[\1]' '[]a'
|
|
test_sub '//@(!(a))/[\1]' '[]a[]'
|
|
|
|
subject='aha'
|
|
|
|
test_sub '/@(!(a))/[\1]' '[aha]'
|
|
test_sub '//@(!(a))/[\1]' '[aha]'
|
|
test_sub '/@(!(aha))/[\1]' '[ah]a'
|
|
test_sub '//@(!(aha))/[\1]' '[ah][a]'
|
|
|
|
exit $((Errors<125?Errors:125))
|