mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
test/[: binary operators: fix '<' and add '=~'; some more cleanups
In ksh88, the test/[ built-in supported both the '<' and '>'
lexical sorting comparison operators, same as in [[. However, in
every version of ksh93, '<' does not work though '>' still does!
Still, the code for both is present in test_binop():
src/cmd/ksh93/bltins/test.c
548: case TEST_SGT:
549: return(strcoll(left, right)>0);
550: case TEST_SLT:
551: return(strcoll(left, right)<0);
Analysis: The binary operators are looked up in shtab_testops[] in
data/testops.c using a macro called sh_lookup, which expands to a
sh_locate() call. If we examine that function in sh/string.c, it's
easy to see that on systems using ASCII (i.e. all except IBM
mainframes), it assumes the table is sorted in ASCII order.
src/cmd/ksh93/sh/string.c
64: while((c= *tp->sh_name) && (CC_NATIVE!=CC_ASCII || c <= first))
The problem was that the '<' operator was not correctly sorted in
shtab_testops[]; it was sorted immediately before '>', but after
'='. The ASCII order is: < (60), = (61), > (62). This caused '<' to
never be found in the table.
The test_binop() function is also used by [[, yet '<' always worked
in that. This is because the parser has code that directly checks
for '<' and '>' within [[ (in sh/parse.c, lines 1949-1952).
This commit also adds '=~' to 'test', which took three lines of
code and allowed eliminating error handling in test_binop() as
test/[ and [[ now support the same binary ops. (re: fc2d5a60)
src/cmd/ksh93/*/*.[ch]:
- Rename a couple of very misleadingly named macros in test.h:
. For == and !=, the TEST_PATTERN bit is off for pattern compares
and on for literal string compares! Rename to TEST_STRCMP.
. The TEST_BINOP bit does not denote all binary operators, but
only the logical -a/-o ops in test/[. Rename to TEST_ANDOR.
src/cmd/ksh93/bltins/test.c: test_binop():
- Add support for =~. This is only used by test/[. The method is
implemented in two lines that convert the ERE to a shell pattern
by prefixing it with ~(E), then call test_strmatch with that
temporary string to match the ERE and update ${.sh.match}.
- Since all binary ops from shtab_testops[] are now accounted for,
remove unknown op error handling from this function.
src/cmd/ksh93/data/testops.c:
- shtab_testops[]:
. Correctly sort the '<' (TEST_SLT) entry.
. Remove ']]' (TEST_END). It's not an op and doesn't belong here.
- Update sh_opttest[] documentation with =~, \<, \>.
- Remove now-unused e_unsupported_op[] error message.
src/cmd/ksh93/sh/lex.c: sh_lex():
- Check for ']]' directly instead of relying on the removed
TEST_END entry from shtab_testops[].
src/cmd/ksh93/tests/bracket.sh:
- Add relevant tests.
src/cmd/ksh93/tests/builtins.sh:
- Fix an old test that globally deleted the 'test' builtin. Delete
it within the command substitution subshell only.
- Remove the test for non-support of =~ in test/[.
- Update the test for invalid test/[ op to use test directly.
This commit is contained in:
parent
6f5c9fea93
commit
c81473061a
9 changed files with 58 additions and 48 deletions
|
|
@ -434,5 +434,20 @@ then set -o posix -o trackall
|
|||
set +o posix
|
||||
fi
|
||||
|
||||
# =====
|
||||
# test should support '<' as well as '>'; before 2021-11-13, ksh supported
|
||||
# only '>' due to '<' being missorted in shtab_testops[] in data/testops.c
|
||||
[ foo \< bar ] 2>/dev/null
|
||||
(($?==1)) || err_exit '[ foo \< bar ] not working'
|
||||
[ foo \> bar ] 2>/dev/null
|
||||
(($?==1)) || err_exit '[ foo \> bar ] not working'
|
||||
|
||||
# as of 2021-11-13, test also supports =~
|
||||
[ att_ =~ '(att|cus)_.*' ] 2>/dev/null || err_exit 'test/[: =~ ERE not working'
|
||||
[ abc =~ 'a(b)c' ] 2>/dev/null || err_exit "[ abc =~ 'a(b)c' ] fails"
|
||||
[ abc =~ '\babc\b' ] 2>/dev/null || err_exit "[ abc =~ '\\babc\\b' ] fails"
|
||||
[ AATAAT =~ '(AAT){2}' ] 2>/dev/null || err_exit "[ AATAAT =~ '(AAT){2}' ] does not match"
|
||||
[ AATAATCCCAATAAT =~ '(AAT){2}CCC(AAT){2}' ] || err_exit "[ AATAATCCCAATAAT =~ '(AAT){2}CCC(AAT){2}' ] does not match"
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
|
|||
|
|
@ -240,8 +240,7 @@ fi
|
|||
if [[ $(LC_MESSAGES=C type test) != 'test is a shell builtin' ]]
|
||||
then err_exit 'whence -v test not a builtin'
|
||||
fi
|
||||
builtin -d test
|
||||
if [[ $(type test) == *builtin* ]]
|
||||
if [[ $(builtin -d test; type test) == *builtin* ]]
|
||||
then err_exit 'whence -v test after builtin -d incorrect'
|
||||
fi
|
||||
typeset -Z3 percent=$(printf '%o\n' "'%'")
|
||||
|
|
@ -1070,21 +1069,10 @@ then got=$( { "$SHELL" -c '
|
|||
fi
|
||||
|
||||
# ==========
|
||||
# Verify that the POSIX 'test' builtin complains loudly when the '=~' operator is used rather than
|
||||
# failing silently. See https://github.com/att/ast/issues/1152.
|
||||
actual=$($SHELL -c 'test foo =~ foo' 2>&1)
|
||||
actual_status=$?
|
||||
actual=${actual#*: }
|
||||
expect='test: =~: operator not supported; use [[ ... ]]'
|
||||
expect_status=2
|
||||
[[ "$actual" = "$expect" ]] || err_exit "test =~ failed (expected $expect, got $actual)"
|
||||
[[ "$actual_status" = "$expect_status" ]] ||
|
||||
err_exit "test =~ failed with the wrong exit status (expected $expect_status, got $actual_status)"
|
||||
|
||||
# Invalid operators 'test' and '[[ ... ]]' both reject should also cause an error with exit status 2.
|
||||
# Verify that the POSIX 'test' builtin exits with status 2 when given an invalid binary operator.
|
||||
for operator in '===' ']]'
|
||||
do
|
||||
actual="$($SHELL -c "test foo $operator foo" 2>&1)"
|
||||
actual=$(test foo "$operator" foo 2>&1)
|
||||
actual_status=$?
|
||||
actual=${actual#*: }
|
||||
expect="test: $operator: unknown operator"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue