name is a fatal error, just like with `for'. This is compatible with
ksh93 and mksh
+ 9/25
+ ----
+subst.c
+ - parameter_brace_expand_length: rearrange the code slightly to reduce
+ the number of find_variable calls. This matters if the variable is
+ dynamic and produces a new value each time (e.g., RANDOM).
+
+ 9/26
+ ----
+builtins/shift.def
+ - shift_builtin: if get_numeric_arg returns a number out of range and
+ we're going to print an error message, make sure to skip over an
+ argument of `--' so we can print the right argument
+
+builtins/break.def
+ - break_builtin,continue_builtin: ditto with get_numeric_arg and `--'
tests/builtins7.sub f
tests/builtins8.sub f
tests/builtins9.sub f
+tests/builtins10.sub f
tests/source1.sub f
tests/source2.sub f
tests/source3.sub f
tests/history5.sub f
tests/history6.sub f
tests/history7.sub f
+tests/history8.sub f
tests/ifs.tests f
tests/ifs.right f
tests/ifs1.sub f
tests/intl.right f
tests/invocation.tests f
tests/invocation.right f
+tests/invocation1.sub f
tests/iquote.tests f
tests/iquote.right f
tests/iquote1.sub f
tests/jobs5.sub f
tests/jobs6.sub f
tests/jobs7.sub f
+tests/jobs8.sub f
tests/jobs.right f
tests/lastpipe.right f
tests/lastpipe.tests f
tests/trap6.sub f
tests/trap7.sub f
tests/trap8.sub f
+tests/trap9.sub f
tests/type.tests f
tests/type.right f
tests/type1.sub f
tests/type2.sub f
tests/type3.sub f
tests/type4.sub f
+tests/type5.sub f
tests/unicode1.sub f
tests/unicode2.sub f
tests/unicode3.sub f
if (newbreak <= 0)
{
+ /* skip over `--' option to get the right error message */
+ if (list && list->word && ISOPTION (list->word->word, '-'))
+ list = list->next;
sh_erange (list->word->word, _("loop count"));
breaking = loop_level;
return (EXECUTION_FAILURE);
if (newcont <= 0)
{
+ /* skip over `--' option to get the right error message */
+ if (list && list->word && ISOPTION (list->word->word, '-'))
+ list = list->next;
sh_erange (list->word->word, _("loop count"));
breaking = loop_level;
return (EXECUTION_FAILURE);
return (EXECUTION_SUCCESS);
else if (times < 0)
{
+ /* skip over `--' option to get the right error message */
+ if (list && list->word && ISOPTION (list->word->word, '-'))
+ list = list->next;
sh_erange (list ? list->word->word : NULL, _("shift count"));
return (EXECUTION_FAILURE);
}
if (times > nargs)
{
if (print_shift_error)
- sh_erange (list ? list->word->word : NULL, _("shift count"));
+ {
+ /* skip over `--' option to get the right error message */
+ if (list && list->word && ISOPTION (list->word->word, '-'))
+ list = list->next;
+
+ sh_erange (list ? list->word->word : NULL, _("shift count"));
+ }
return (EXECUTION_FAILURE);
}
else if (times == nargs)
SHELL_VAR *var;
var = (SHELL_VAR *)NULL;
+ number = 0;
if (name[1] == '\0') /* ${#} */
number = number_of_args ();
else if (valid_array_reference (name + 1, 0))
number = array_length_reference (name + 1);
#endif /* ARRAY_VARS */
+ else if (legal_number (name + 1, &arg_index)) /* ${#1} */
+ {
+ t = get_dollar_var_value (arg_index);
+ if (t == 0 && unbound_vars_is_error)
+ return INTMAX_MIN;
+ number = MB_STRLEN (t);
+ FREE (t);
+ }
else
{
- number = 0;
-
- if (legal_number (name + 1, &arg_index)) /* ${#1} */
- {
- t = get_dollar_var_value (arg_index);
- if (t == 0 && unbound_vars_is_error)
- return INTMAX_MIN;
- number = MB_STRLEN (t);
- FREE (t);
- }
+ var = find_variable (name + 1);
#if defined (ARRAY_VARS)
- else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
+ if (var && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
{
if (assoc_p (var))
t = assoc_reference (assoc_cell (var), "0");
return INTMAX_MIN;
number = MB_STRLEN (t);
}
+ else
#endif
- /* Fast path for the common case of taking the length of a non-dynamic
- scalar variable value. */
- else if ((var || (var = find_variable (name + 1))) &&
- invisible_p (var) == 0 &&
- array_p (var) == 0 && assoc_p (var) == 0 &&
- nameref_p (var) == 0 &&
- var->dynamic_value == 0)
+ /* Fast path for the common case of taking the length of a scalar
+ variable value. */
+ if (var && invisible_p (var) == 0 &&
+ array_p (var) == 0 && assoc_p (var) == 0 &&
+ nameref_p (var) == 0)
number = value_cell (var) ? MB_STRLEN (value_cell (var)) : 0;
else if ((var = find_variable_last_nameref (name + 1, 0)) && nameref_p (var))
{
export BASH_TSTOUT=/tmp/xx
rm -f ${BASH_TSTOUT}
-/bin/sh "$@"
+${THIS_SH} "$@"
quux
hi
declare -a m=([0]="x")
+./alias.tests: line 66: alias: `\$': invalid alias name
+./alias.tests: line 67: `\$': invalid alias name
bar
value
bar
L
declare -p m
+# invalid alias names generate errors
+alias '\$'=xx
+BASH_ALIASES['\$']=xx
+
${THIS_SH} ./alias1.sub
${THIS_SH} ./alias2.sub
${THIS_SH} ./alias3.sub
2
1
0
+43210
+ok1
+./arith-for.tests: line 133: ((: 7++ : arithmetic syntax error: operand expected (error token is "+ ")
+./arith-for.tests: line 134: ((: i < 4/0: division by 0 (error token is "0")
+./arith-for.tests: line 135: ((: i=2/0: division by 0 (error token is "0")
+./arith-for.tests: line 137: ((: 7=4 : attempted assignment to non-variable (error token is "=4 ")
for (( i = 4; ;i--)) ; do echo $i; if (( $i == 0 )); then break; fi; done
for (( i = 4;;i--)) ; do echo $i; if (( $i == 0 )); then break; fi; done
+i=4 ; for (( ;;i--)) ; do echo -n $i; if (( i == 0 )); then break; fi; done; echo
+
+# arithmetic for commands with expression errors
+
+for (( i=1; i < 4; 7++ )); do echo ok$i ; done
+for (( i=2; i < 4/0; 7++ )); do echo whoops1 ; done
+for (( i=2/0; i < 4; 7++ )); do echo whoops2 ; done
+
+for (( 7=4 ; 7 > 7; )); do echo whoops3; done
6 7 9 5
length = 3
value = new1 new2 new3
-./array.tests: line 257: narray: unbound variable
+./array.tests: line 256: syntax error near unexpected token `&'
+./array.tests: line 256: `badarray=( metacharacters like & need to be quoted in compound assignments)'
+./array.tests: line 260: narray: unbound variable
./array1.sub: line 1: syntax error near unexpected token `('
./array1.sub: line 1: `printf "%s\n" -a a=(a 'b c')'
./array2.sub: line 1: declare: `[]=asdf': not a valid identifier
12 14 16 18 20
4414758999202
aaa bbb
-./array.tests: line 307: syntax error near unexpected token `<>'
-./array.tests: line 307: `metas=( <> < > ! )'
-./array.tests: line 308: syntax error near unexpected token `<>'
-./array.tests: line 308: `metas=( [1]=<> [2]=< [3]=> [4]=! )'
+./array.tests: line 310: syntax error near unexpected token `<>'
+./array.tests: line 310: `metas=( <> < > ! )'
+./array.tests: line 311: syntax error near unexpected token `<>'
+./array.tests: line 311: `metas=( [1]=<> [2]=< [3]=> [4]=! )'
abc 3
case 4
abc case if then else 5
echo "length = ${#barray[@]}"
echo "value = ${barray[*]}"
+# the compound assignment syntax inherited from ksh93 has some quirks
+badarray=( metacharacters like & need to be quoted in compound assignments)
+
# make sure the array code behaves correctly with respect to unset variables
set -u
( echo ${#narray[4]} )
FOO=BAR
hash: hash table empty
0
+no-newline
AVAR
foo
in source.sub2, calling return
foo
declare -x foo=""
declare -x FOO="\$\$"
-./builtins.tests: line 228: declare: FOO: not found
+./builtins.tests: line 239: declare: FOO: not found
declare -x FOO="\$\$"
ok
ok
-./builtins.tests: line 260: kill: 4096: invalid signal specification
+./builtins.tests: line 271: kill: 4096: invalid signal specification
1
a\n\n\nb
a
u=rwx,g=rwx,o=rwx
u=rwx,g=rx,o=rx
u=rwx,g=rx,o=rx
+u=rwx,g=rx,o=rx
+u=rwx,g=rx,o=rx
+u=rwx,g=rx,o=rx
+u=rwx,g=rx,o=rx
hash: hash table empty
./builtins9.sub: line 19: hash: notthere: not found
1
0
found
./builtins9.sub: line 52: hash: /: Is a directory
-./builtins.tests: line 290: exit: status: numeric argument required
+builtin hash -p /nosuchfile cat
+./builtins10.sub: line 17: help: -x: invalid option
+help: usage: help [-dms] [pattern ...]
+These shell commands are defined internally. Type `help' to see this list.
+Type `help name' to find out more about the function `name'.
+Use `info bash' to find out more about the shell in general.
+Use `man -k' or `info' to find out more about commands not in this list.
+
+A star (*) next to a name means that the command is disabled.
+
+ ! PIPELINE history [-c] [-d offset] [n] or hist>
+ job_spec [&] if COMMANDS; then COMMANDS; [ elif C>
+ (( expression )) jobs [-lnprs] [jobspec ...] or jobs >
+ . filename [arguments] kill [-s sigspec | -n signum | -sigs>
+ : let arg [arg ...]
+ [ arg... ] local [option] name[=value] ...
+ [[ expression ]] logout [n]
+ alias [-p] [name[=value] ... ] mapfile [-d delim] [-n count] [-O or>
+ bg [job_spec ...] popd [-n] [+N | -N]
+ bind [-lpsvPSVX] [-m keymap] [-f file> printf [-v var] format [arguments]
+ break [n] pushd [-n] [+N | -N | dir]
+ builtin [shell-builtin [arg ...]] pwd [-LP]
+ caller [expr] read [-Eers] [-a array] [-d delim] [>
+ case WORD in [PATTERN [| PATTERN]...)> readarray [-d delim] [-n count] [-O >
+ cd [-L|[-P [-e]]] [-@] [dir] readonly [-aAf] [name[=value] ...] o>
+ command [-pVv] command [arg ...] return [n]
+ compgen [-V varname] [-abcdefgjksuv] > select NAME [in WORDS ... ;] do COMM>
+ complete [-abcdefgjksuv] [-pr] [-DEI]> set [-abefhkmnptuvxBCEHPT] [-o optio>
+ compopt [-o|+o option] [-DEI] [name .> shift [n]
+ continue [n] shopt [-pqsu] [-o] [optname ...]
+ coproc [NAME] command [redirections] source filename [arguments]
+ declare [-aAfFgiIlnrtux] [name[=value> suspend [-f]
+ dirs [-clpv] [+N] [-N] test [expr]
+ disown [-h] [-ar] [jobspec ... | pid > time [-p] pipeline
+ echo [-neE] [arg ...] times
+ enable [-a] [-dnps] [-f filename] [na> trap [-Plp] [[action] signal_spec ..>
+ eval [arg ...] true
+ exec [-cl] [-a name] [command [argume> type [-afptP] name [name ...]
+ exit [n] typeset [-aAfFgiIlnrtux] name[=value>
+ export [-fn] [name[=value] ...] or ex> ulimit [-SHabcdefiklmnpqrstuvxPRT] [>
+ false umask [-p] [-S] [mode]
+ fc [-e ename] [-lnr] [first] [last] o> unalias [-a] name [name ...]
+ fg [job_spec] unset [-f] [-v] [-n] [name ...]
+ for NAME [in WORDS ... ] ; do COMMAND> until COMMANDS; do COMMANDS-2; done
+ for (( exp1; exp2; exp3 )); do COMMAN> variables - Names and meanings of so>
+ function name { COMMANDS ; } or name > wait [-fn] [-p var] [id ...]
+ getopts optstring name [arg ...] while COMMANDS; do COMMANDS-2; done
+ hash [-lr] [-p pathname] [-dt] [name > { COMMANDS ; }
+ help [-dms] [pattern ...]
+help: help [-dms] [pattern ...]
+shift - Shift positional parameters.
+shift: shift [n]
+ Shift positional parameters.
+
+ Rename the positional parameters $N+1,$N+2 ... to $1,$2 ... If N is
+ not given, it is assumed to be 1.
+
+ Exit Status:
+ Returns success unless N is negative or greater than $#.
+builtin: builtin [shell-builtin [arg ...]]
+shift: shift [n]
+Shell commands matching keyword `read*'
+
+read: read [-Eers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
+readarray: readarray [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
+readonly: readonly [-aAf] [name[=value] ...] or readonly -p
+NAME
+ : - Null command.
+
+SYNOPSIS
+ :
+
+DESCRIPTION
+ Null command.
+
+ No effect; the command does nothing.
+
+ Exit Status:
+ Always succeeds.
+
+SEE ALSO
+ bash(1)
+
+IMPLEMENTATION
+ Copyright (C) 2022 Free Software Foundation, Inc.
+
+These shell commands are defined internally. Type `help' to see this list.
+Type `help name' to find out more about the function `name'.
+Use `info bash' to find out more about the shell in general.
+Use `man -k' or `info' to find out more about commands not in this list.
+
+A star (*) next to a name means that the command is disabled.
+
+ ! PIPELINE history [-c] [-d offset] [n] or hist>
+ job_spec [&] if COMMANDS; then COMMANDS; [ elif C>
+ (( expression )) jobs [-lnprs] [jobspec ...] or jobs >
+ . filename [arguments] kill [-s sigspec | -n signum | -sigs>
+ : let arg [arg ...]
+ [ arg... ] local [option] name[=value] ...
+ [[ expression ]] logout [n]
+ alias [-p] [name[=value] ... ] mapfile [-d delim] [-n count] [-O or>
+ bg [job_spec ...] popd [-n] [+N | -N]
+ bind [-lpsvPSVX] [-m keymap] [-f file> printf [-v var] format [arguments]
+ break [n] pushd [-n] [+N | -N | dir]
+ builtin [shell-builtin [arg ...]] pwd [-LP]
+ caller [expr] read [-Eers] [-a array] [-d delim] [>
+ case WORD in [PATTERN [| PATTERN]...)> readarray [-d delim] [-n count] [-O >
+ cd [-L|[-P [-e]]] [-@] [dir] readonly [-aAf] [name[=value] ...] o>
+ command [-pVv] command [arg ...] return [n]
+ compgen [-V varname] [-abcdefgjksuv] > select NAME [in WORDS ... ;] do COMM>
+ complete [-abcdefgjksuv] [-pr] [-DEI]> set [-abefhkmnptuvxBCEHPT] [-o optio>
+ compopt [-o|+o option] [-DEI] [name .> shift [n]
+ continue [n] shopt [-pqsu] [-o] [optname ...]
+ coproc [NAME] command [redirections] source filename [arguments]
+ declare [-aAfFgiIlnrtux] [name[=value> suspend [-f]
+ dirs [-clpv] [+N] [-N] test [expr]
+ disown [-h] [-ar] [jobspec ... | pid > time [-p] pipeline
+ echo [-neE] [arg ...] times
+ enable [-a] [-dnps] [-f filename] [na> trap [-Plp] [[action] signal_spec ..>
+ eval [arg ...] true
+ exec [-cl] [-a name] [command [argume> type [-afptP] name [name ...]
+ exit [n] typeset [-aAfFgiIlnrtux] name[=value>
+ export [-fn] [name[=value] ...] or ex> ulimit [-SHabcdefiklmnpqrstuvxPRT] [>
+ false umask [-p] [-S] [mode]
+ fc [-e ename] [-lnr] [first] [last] o> unalias [-a] name [name ...]
+ fg [job_spec] unset [-f] [-v] [-n] [name ...]
+ for NAME [in WORDS ... ] ; do COMMAND> until COMMANDS; do COMMANDS-2; done
+ for (( exp1; exp2; exp3 )); do COMMAN> variables - Names and meanings of so>
+ function name { COMMANDS ; } or name > wait [-fn] [-p var] [id ...]
+ getopts optstring name [arg ...] while COMMANDS; do COMMANDS-2; done
+ hash [-lr] [-p pathname] [-dt] [name > { COMMANDS ; }
+ help [-dms] [pattern ...]
+./builtins.tests: line 316: exit: status: numeric argument required
done
echo end
+# check arguments to break and continue that exceed the loop level
+for f in 1 2 3; do break -- 5; done
+for f in 1 2 3; do continue -- 5; done
+
# check that `eval' re-evaluates arguments, but `builtin' and `command' do not
AVAR='$BVAR'
BVAR=foo
# check out source/.
# sourcing a zero-length-file had better not be an error
-rm -f /tmp/zero-length-file
-cp /dev/null /tmp/zero-length-file
-. /tmp/zero-length-file
+rm -f $TMPDIR/zero-length-file-$$
+cp /dev/null $TMPDIR/zero-length-file-$$
+. $TMPDIR/zero-length-file-$$
echo $?
-rm /tmp/zero-length-file
+rm $TMPDIR/zero-length-file-$$
+
+# and sourcing a file that doesn't end in a newline had better work too
+SFILE=$TMPDIR/sourced-file-$$
+printf 'echo no-newline' > $SFILE
+. $SFILE
+rm -f $SFILE
+unset -v SFILE
AVAR=AVAR
# kill -l NAME should return the signal number
kill -l ${sigone/SIG/}
+# kill -l NAME should work with and without the SIG prefix
+x=$(kill -l INT)
+y=$(kill -l SIGINT)
+
+[[ $x == $y ]] || echo kill -l error with SIG prefix
+unset -v x y
+
# test behavior of shopt xpg_echo
${THIS_SH} ./builtins2.sub
# hash tests
${THIS_SH} ./builtins9.sub
+# help tests
+${THIS_SH} ./builtins10.sub
+
+shift 0 # succeeds silently
+
+options=$(set -o -B 2>&1 | wc -l)
+[[ $options -gt 3 ]] || echo 'set: bad -o option name parsing'
+
# this must be last -- it is a fatal error
exit status
--- /dev/null
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# have to run through sed or grep to filter out version information
+
+# let's exercise print-help
+help -x
+
+help -- | sed 1d
+
+command help -s help
+builtin help -d shift
+shift --help
+help -s builtin shift
+
+# this hasn't ever been very useful
+help -s 'read*'
+
+help -m : | grep -v version
+
+LC_ALL=en_US.UTF-8
+help -- | sed 1d
umask 022
umask a+xr
umask -S
+
+umask 022
+umask g+X
+umask -S
+
+umask 022
+umask o+X
+umask -S
+
+umask 022
+umask +X
+umask -S
+
+umask 022
+umask g+x,o+x
+umask -S
hash -r
hash -p / root
+
+hash -r
+
+# assignment to BASH_CMDS[x] should be like hash -p
+BASH_CMDS[cat]=/nosuchfile
+hash -lt cat
+hash -d cat
complete -f more
complete -f -X '!*.+(gz|tgz)' gzcat
./complete.tests: line 123: complete: notthere: no completion specification
+!
+%
+(( ... ))
+.
+:
+[
+[[ ... ]]
+alias
+bg
+bind
+break
+builtin
+caller
+case
+cd
+command
+compgen
+complete
+compopt
+continue
+coproc
+declare
+dirs
+disown
+echo
+enable
+eval
+exec
+exit
+export
+false
+fc
+fg
+for
+for ((
+function
+getopts
+hash
+help
+history
+if
+jobs
+kill
+let
+local
+logout
+mapfile
+popd
+printf
+pushd
+pwd
+read
+readarray
+readonly
+return
+select
+set
+shift
+shopt
+source
+suspend
+test
+time
+times
+trap
+true
+type
+typeset
+ulimit
+umask
+unalias
+unset
+until
+variables
+wait
+while
+{ ... }
+.
+:
+[
+alias
+bg
+bind
+break
+builtin
+caller
+cd
+command
+compgen
+complete
+compopt
+continue
+declare
+dirs
+disown
+echo
+enable
+eval
+exec
+exit
+export
+false
+fc
+fg
+getopts
+hash
+help
+history
+jobs
+kill
+let
+local
+logout
+mapfile
+popd
+printf
+pushd
+pwd
+read
+readarray
+readonly
+return
+set
+shift
+shopt
+source
+suspend
+test
+times
+trap
+true
+type
+typeset
+ulimit
+umask
+unalias
+unset
+wait
+.
+:
+[
+alias
+bg
+bind
+break
+builtin
+caller
+cd
+command
+compgen
+complete
+compopt
+continue
+declare
+dirs
+disown
+echo
+enable
+eval
+exec
+exit
+export
+false
+fc
+fg
+getopts
+hash
+help
+history
+jobs
+kill
+let
+local
+logout
+mapfile
+popd
+printf
+pushd
+pwd
+read
+readarray
+readonly
+return
+set
+shift
+shopt
+source
+suspend
+test
+times
+trap
+true
+type
+typeset
+ulimit
+umask
+unalias
+unset
+wait
+if
+then
+else
+elif
+fi
+case
+esac
+for
+select
+while
+until
+do
+done
+in
+function
+time
+{
+}
+!
+[[
+]]
+coproc
+./complete.tests: line 136: compgen: -r: invalid option
+compgen: usage: compgen [-V varname] [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
+./complete.tests: line 137: compgen: noaction: invalid action name
+./complete.tests: line 138: compgen: -D: invalid option
+compgen: usage: compgen [-V varname] [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
+./complete.tests: line 140: compopt: nooption: invalid option name
complete -r
complete
+
+# some random compgen topics
+
+compgen -A helptopic
+command compgen -b
+compgen -A enabled
+compgen -k
+
+# and some errors
+compgen -r
+compgen -A noaction
+compgen -D
+
+compopt -o nooption
blank ----
blank ----
blank ----
+func: v = comsub
#esac
a
ok 1
Dir: ${BUILDDIR#<(echo a)/}
EOC
+# return in a comsub inside a shell function should abort the comsub
+func()
+{
+ local v
+ v=$( echo comsub ; return ; echo after)
+ echo $FUNCNAME: v = $v
+}
+func
+
${THIS_SH} ./comsub1.sub
${THIS_SH} ./comsub2.sub
${THIS_SH} ./comsub3.sub
EPOCHSECONDS ok
EPOCHREALTIME ok
echo $BASH_COMMAND
+110
+111
+112
+113
+114
+./dynvar.tests: line 115: ((: LINENO / 0 : division by 0 (error token is "0 ")
+0
+0
if (( $after > $before )); then echo SECONDS ok; fi
unset before after
+# do the best we can to test assignment to SECONDS
+SECONDS=2
+sleep 1
+[[ $SECONDS -ge 10 ]] && echo 'SECONDS: bad value assignment'
+
# EPOCHSECONDS
# not exact, but should work
# FUNCNAME tested in func.tests
# RANDOM tested in varenv.sh
-# LINENO tested in dbg-support
+# LINENO tested in dbg-support, misc additional tests here
+arith_lineno()
+{
+ echo $LINENO
+ for f in 1 ; do echo $LINENO; done
+ for (( f=1 ; f < 2; f++ )); do echo $LINENO; done
+ echo $(( $LINENO ))
+ (( 1 == 1 )) && echo $LINENO
+ (( LINENO / 0 ))
+}
+arith_lineno
+
+# assignments to noassign variables are ignored
+FUNCNAME=42
+echo $? $FUNCNAME
+
+GROUPS[0]=-1
+echo $?
+
+[[ ${GROUPS[0]} != -1 ]] || echo GROUPS noassign error
./errors.tests: line 48: `invalid-name': not a valid identifier
./errors.tests: line 50: `1': not a valid identifier
./errors.tests: line 51: `f\1': not a valid identifier
+./errors.tests: line 55: `$1': not a valid identifier
declare -fr func
-./errors.tests: line 64: func: readonly function
-./errors.tests: line 67: unset: -x: invalid option
+./errors.tests: line 72: func: readonly function
+./errors.tests: line 75: unset: -x: invalid option
unset: usage: unset [-f] [-v] [-n] [name ...]
-./errors.tests: line 70: unset: func: cannot unset: readonly function
-./errors.tests: line 73: declare: func: readonly function
-./errors.tests: line 77: declare: -a: invalid option
-./errors.tests: line 78: declare: -i: invalid option
-./errors.tests: line 82: unset: XPATH: cannot unset: readonly variable
-./errors.tests: line 88: unset: cannot simultaneously unset a function and a variable
-./errors.tests: line 91: declare: -z: invalid option
+./errors.tests: line 78: unset: func: cannot unset: readonly function
+./errors.tests: line 81: declare: func: readonly function
+./errors.tests: line 85: declare: -a: invalid option
+./errors.tests: line 86: declare: -i: invalid option
+./errors.tests: line 90: unset: XPATH: cannot unset: readonly variable
+./errors.tests: line 96: unset: cannot simultaneously unset a function and a variable
+./errors.tests: line 99: declare: -z: invalid option
declare: usage: declare [-aAfFgiIlnrtux] [name[=value] ...] or declare -p [-aAfFilnrtux] [name ...]
-./errors.tests: line 93: declare: `-z': not a valid identifier
-./errors.tests: line 94: declare: `/bin/sh': not a valid identifier
-./errors.tests: line 98: declare: cannot use `-f' to make functions
-./errors.tests: line 101: exec: -i: invalid option
+./errors.tests: line 101: declare: `-z': not a valid identifier
+./errors.tests: line 102: declare: `/bin/sh': not a valid identifier
+./errors.tests: line 106: declare: cannot use `-f' to make functions
+./errors.tests: line 109: exec: -i: invalid option
exec: usage: exec [-cl] [-a name] [command [argument ...]] [redirection ...]
-./errors.tests: line 105: export: XPATH: not a function
-./errors.tests: line 108: break: only meaningful in a `for', `while', or `until' loop
-./errors.tests: line 109: continue: only meaningful in a `for', `while', or `until' loop
-./errors.tests: line 112: shift: label: numeric argument required
-./errors.tests: line 117: shift: too many arguments
-./errors.tests: line 123: let: expression expected
-./errors.tests: line 126: local: can only be used in a function
-./errors.tests: line 129: logout: not login shell: use `exit'
-./errors.tests: line 132: hash: notthere: not found
-./errors.tests: line 135: hash: -v: invalid option
+./errors.tests: line 113: export: XPATH: not a function
+./errors.tests: line 116: break: only meaningful in a `for', `while', or `until' loop
+./errors.tests: line 117: continue: only meaningful in a `for', `while', or `until' loop
+./errors.tests: line 120: shift: label: numeric argument required
+./errors.tests: line 125: shift: too many arguments
+./errors.tests: line 131: let: expression expected
+./errors.tests: line 134: local: can only be used in a function
+./errors.tests: line 137: logout: not login shell: use `exit'
+./errors.tests: line 140: hash: notthere: not found
+./errors.tests: line 143: hash: -v: invalid option
hash: usage: hash [-lr] [-p pathname] [-dt] [name ...]
-./errors.tests: line 139: hash: hashing disabled
-./errors.tests: line 142: export: `AA[4]': not a valid identifier
-./errors.tests: line 143: readonly: `AA[4]': not a valid identifier
-./errors.tests: line 146: unset: [-2]: bad array subscript
-./errors.tests: line 150: AA: readonly variable
-./errors.tests: line 154: AA: readonly variable
-./errors.tests: line 162: shift: 5: shift count out of range
-./errors.tests: line 163: shift: -2: shift count out of range
-./errors.tests: line 166: shopt: no_such_option: invalid shell option name
-./errors.tests: line 167: shopt: no_such_option: invalid shell option name
-./errors.tests: line 170: umask: 09: octal number out of range
-./errors.tests: line 171: umask: `:': invalid symbolic mode character
-./errors.tests: line 172: umask: `:': invalid symbolic mode operator
-./errors.tests: line 175: umask: -i: invalid option
+./errors.tests: line 147: hash: hashing disabled
+./errors.tests: line 150: export: `AA[4]': not a valid identifier
+./errors.tests: line 151: readonly: `AA[4]': not a valid identifier
+./errors.tests: line 152: export: `invalid-var=4': not a valid identifier
+./errors.tests: line 153: readonly: `invalid-var=4': not a valid identifier
+./errors.tests: line 154: export: `invalid-var': not a valid identifier
+./errors.tests: line 155: readonly: `invalid-var': not a valid identifier
+./errors.tests: line 158: unset: [-2]: bad array subscript
+./errors.tests: line 162: AA: readonly variable
+./errors.tests: line 166: AA: readonly variable
+./errors.tests: line 174: shift: 5: shift count out of range
+./errors.tests: line 175: shift: -2: shift count out of range
+./errors.tests: line 178: shopt: no_such_option: invalid shell option name
+./errors.tests: line 179: shopt: no_such_option: invalid shell option name
+./errors.tests: line 180: shopt: no_such_option: invalid option name
+./errors.tests: line 183: umask: 09: octal number out of range
+./errors.tests: line 184: umask: `:': invalid symbolic mode character
+./errors.tests: line 185: umask: `:': invalid symbolic mode operator
+./errors.tests: line 188: umask: -i: invalid option
umask: usage: umask [-p] [-S] [mode]
-./errors.tests: line 179: umask: `p': invalid symbolic mode character
-./errors.tests: line 188: VAR: readonly variable
-./errors.tests: line 191: declare: VAR: readonly variable
-./errors.tests: line 192: declare: VAR: readonly variable
-./errors.tests: line 194: declare: unset: not found
-./errors.tests: line 197: VAR: readonly variable
+./errors.tests: line 192: umask: `p': invalid symbolic mode character
+./errors.tests: line 201: VAR: readonly variable
+./errors.tests: line 204: declare: VAR: readonly variable
+./errors.tests: line 205: declare: VAR: readonly variable
+./errors.tests: line 207: declare: unset: not found
+./errors.tests: line 210: VAR: readonly variable
comsub: -c: line 1: syntax error near unexpected token `)'
comsub: -c: line 1: `: $( for z in 1 2 3; do )'
comsub: -c: line 1: syntax error near unexpected token `done'
comsub: -c: line 1: `: $( for z in 1 2 3; done )'
-./errors.tests: line 204: cd: HOME not set
-./errors.tests: line 205: cd: /tmp/xyz.bash: No such file or directory
-./errors.tests: line 207: cd: OLDPWD not set
-./errors.tests: line 208: cd: /bin/sh: Not a directory
-./errors.tests: line 210: cd: /tmp/cd-notthere: No such file or directory
-./errors.tests: line 213: .: filename argument required
+./errors.tests: line 217: cd: HOME not set
+./errors.tests: line 218: cd: /tmp/xyz.bash: No such file or directory
+./errors.tests: line 220: cd: OLDPWD not set
+./errors.tests: line 221: cd: /bin/sh: Not a directory
+./errors.tests: line 223: cd: /tmp/cd-notthere: No such file or directory
+./errors.tests: line 225: cd: too many arguments
+bash: line 1: PWD: readonly variable
+1
+./errors.tests: line 230: .: filename argument required
.: usage: . filename [arguments]
-./errors.tests: line 214: source: filename argument required
+./errors.tests: line 231: source: filename argument required
source: usage: source filename [arguments]
-./errors.tests: line 217: .: -i: invalid option
+./errors.tests: line 234: .: -i: invalid option
.: usage: . filename [arguments]
-./errors.tests: line 220: set: -q: invalid option
+./errors.tests: line 237: set: -q: invalid option
set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
-./errors.tests: line 223: enable: sh: not a shell builtin
-./errors.tests: line 223: enable: bash: not a shell builtin
-./errors.tests: line 226: shopt: cannot set and unset shell options simultaneously
-./errors.tests: line 229: read: var: invalid timeout specification
-./errors.tests: line 232: read: `/bin/sh': not a valid identifier
-./errors.tests: line 235: VAR: readonly variable
-./errors.tests: line 238: readonly: -x: invalid option
+./errors.tests: line 240: enable: sh: not a shell builtin
+./errors.tests: line 240: enable: bash: not a shell builtin
+./errors.tests: line 243: shopt: cannot set and unset shell options simultaneously
+./errors.tests: line 246: read: -x: invalid option
+read: usage: read [-Eers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
+./errors.tests: line 249: read: var: invalid timeout specification
+./errors.tests: line 252: read: `/bin/sh': not a valid identifier
+./errors.tests: line 253: read: `/bin/sh': not a valid identifier
+./errors.tests: line 256: VAR: readonly variable
+./errors.tests: line 259: read: XX: invalid file descriptor specification
+./errors.tests: line 260: read: 42: invalid file descriptor: Bad file descriptor
+./errors.tests: line 263: mapfile: XX: invalid file descriptor specification
+./errors.tests: line 264: mapfile: 42: invalid file descriptor: Bad file descriptor
+./errors.tests: line 268: mapfile: empty array variable name
+./errors.tests: line 269: mapfile: `invalid-var': not a valid identifier
+./errors.tests: line 272: readonly: -x: invalid option
readonly: usage: readonly [-aAf] [name[=value] ...] or readonly -p
-./errors.tests: line 241: eval: -i: invalid option
+./errors.tests: line 275: eval: -i: invalid option
eval: usage: eval [arg ...]
-./errors.tests: line 242: command: -i: invalid option
+./errors.tests: line 276: command: -i: invalid option
command: usage: command [-pVv] command [arg ...]
-./errors.tests: line 245: /bin/sh + 0: arithmetic syntax error: operand expected (error token is "/bin/sh + 0")
-./errors.tests: line 246: /bin/sh + 0: arithmetic syntax error: operand expected (error token is "/bin/sh + 0")
-./errors.tests: line 249: trap: NOSIG: invalid signal specification
-./errors.tests: line 252: trap: -s: invalid option
+./errors.tests: line 279: /bin/sh + 0: arithmetic syntax error: operand expected (error token is "/bin/sh + 0")
+./errors.tests: line 280: /bin/sh + 0: arithmetic syntax error: operand expected (error token is "/bin/sh + 0")
+./errors.tests: line 283: trap: NOSIG: invalid signal specification
+./errors.tests: line 286: trap: -s: invalid option
trap: usage: trap [-Plp] [[action] signal_spec ...]
-./errors.tests: line 258: return: can only `return' from a function or sourced script
-./errors.tests: line 262: break: 0: loop count out of range
-./errors.tests: line 266: continue: 0: loop count out of range
-./errors.tests: line 271: builtin: bash: not a shell builtin
-./errors.tests: line 275: bg: no job control
-./errors.tests: line 276: fg: no job control
-./errors.tests: line 279: kill: -s: option requires an argument
-./errors.tests: line 281: kill: S: invalid signal specification
-./errors.tests: line 283: kill: `': not a pid or valid job spec
+./errors.tests: line 292: return: can only `return' from a function or sourced script
+./errors.tests: line 296: break: 0: loop count out of range
+./errors.tests: line 300: continue: 0: loop count out of range
+./errors.tests: line 305: builtin: bash: not a shell builtin
+./errors.tests: line 309: bg: no job control
+./errors.tests: line 310: fg: no job control
+./errors.tests: line 313: kill: -s: option requires an argument
+./errors.tests: line 315: kill: S: invalid signal specification
+./errors.tests: line 317: kill: `': not a pid or valid job spec
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
-./errors.tests: line 288: set: trackall: invalid option name
-./errors.tests: line 289: set: -q: invalid option
+./errors.tests: line 321: kill: SIGBAD: invalid signal specification
+./errors.tests: line 323: kill: BAD: invalid signal specification
+./errors.tests: line 325: kill: @12: arguments must be process or job IDs
+./errors.tests: line 328: unset: BASH_LINENO: cannot unset
+./errors.tests: line 328: unset: BASH_SOURCE: cannot unset
+./errors.tests: line 331: set: trackall: invalid option name
+./errors.tests: line 332: set: -q: invalid option
set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
-./errors.tests: line 290: set: -i: invalid option
+./errors.tests: line 333: set: -i: invalid option
set: usage: set [-abefhkmnptuvxBCEHPT] [-o option-name] [--] [-] [arg ...]
-./errors.tests: line 294: xx: readonly variable
+./errors.tests: line 337: xx: readonly variable
1
./errors1.sub: line 14: .: -i: invalid option
.: usage: . filename [arguments]
./errors1.sub: line 22: shift: -4: shift count out of range
+./errors1.sub: line 23: shift: -4: shift count out of range
./errors1.sub: line 27: break: -1: loop count out of range
+./errors1.sub: line 28: continue: -1: loop count out of range
+./errors1.sub: line 29: break: -5: loop count out of range
+./errors1.sub: line 30: continue: -5: loop count out of range
after f
./errors2.sub: line 3: ${$NO_SUCH_VAR}: bad substitution
1
after special builtin: 0
./errors7.sub: line 27: x: readonly variable
./errors7.sub: line 29: x: readonly variable
+./errors7.sub: line 32: v: readonly variable
./errors7.sub: line 21: x: readonly variable
after no such command: 1
./errors7.sub: line 23: x: readonly variable
./errors7.sub: line 25: x: readonly variable
./errors7.sub: line 27: x: readonly variable
./errors7.sub: line 29: x: readonly variable
+./errors7.sub: line 32: v: readonly variable
./errors8.sub: eval: line 7: syntax error: unexpected end of file
ok 1
./errors8.sub: line 8: v: readonly variable
sh: line 1: /nosuchfile: No such file or directory
sh: line 1: trap: SIGNOSIG: invalid signal specification
after trap
-./errors.tests: line 333: `!!': not a valid identifier
+./errors.tests: line 376: `!!': not a valid identifier
(set -o posix ; select 1 in a b c; do echo $REPLY; done; echo after posix select)
(set -o posix ; select f\1 in a b c ; do echo $REPLY ; done ; echo after posix select 2)
+# even in functions
+bad-select()
+{
+ select $1 in a b c ; do echo $REPLY ; done
+}
+bad-select 'a b'
+unset -f bad-select
+
# try to rebind a read-only function
func()
{
# bad identifiers to declare/readonly/export
export AA[4]
readonly AA[4]
+export invalid-var=4
+readonly invalid-var=4
+export invalid-var
+readonly invalid-var
declare -a AA
unset AA[-2]
# bad shell options
shopt -s no_such_option
shopt no_such_option
+shopt -s -o no_such_option
# non-octal digits for umask and other errors
umask 09
cd /bin/sh # error - not a directory
OLDPWD=/tmp/cd-notthere
cd -
+# too many arguments
+cd one two three
+# cd doesn't like it if PWD is readonly
+${THIS_SH} -c 'readonly PWD ; cd / ; echo $?' bash
# various `source/.' errors
.
# try to set and unset shell options simultaneously
shopt -s -u checkhash
+# error
+read -x
+
# this is an error -- bad timeout spec
read -t var < /dev/null
# try to read into an invalid identifier
read /bin/sh < /dev/null
+read A /bin/sh < /dev/null
# try to read into a readonly variable
read VAR < /dev/null
+# invalid file descriptor
+read -u XX < /dev/null
+read -u 42 < /dev/null
+
+# same with mapfile
+mapfile -u XX A < /dev/null
+mapfile -u 42 A < /dev/null
+unset -v A
+
+# invalid identifier arguments to mapfile
+mapfile '' </dev/null
+mapfile invalid-var < /dev/null
+
# bad option to readonly/export
readonly -x foo
kill -INT ''
# argument required
kill -INT
+# bad signal specification
+kill -l SIGBAD
+# bad signal specification
+kill -l BAD
+# bad process specification
+kill -HUP @12
+
+# cannot unset non-unsettable variables
+unset -v BASH_LINENO BASH_SOURCE
# bad shell option names
set -o trackall # bash is not ksh
set -- a b c
shift -4
+shift -- -4
f
-for f in 1 2 3; do
- break -1
-done
-
+for f in 1 2 3; do break -1; done
+for f in 1 2 3; do continue -1; done
+for f in 1 2 3; do break -- -5; done
+for f in 1 2 3; do continue -- -5; done
f()
{
echo after assignment error: $? )
( x=8
echo after assignment statement error: $? )
+
+( readonly v; : ${v:=val}
+ echo variable assignment error )
126
/: /: Is a directory
126
-./execscript: line 47: .: /: is a directory
+bash: line 1: exec: .: cannot execute: Is a directory
+posix-bash: line 1: exec: .: cannot execute: Is a directory
+bash: line 1: exec: .: cannot execute: Is a directory
+posix-bash: line 1: exec: .: cannot execute: Is a directory
+./execscript: line 55: .: /: is a directory
1
126
0
trap -- 'echo USR1' SIGUSR1
USR1
EXIT
-./execscript: line 71: notthere: command not found
-127
-./execscript: line 73: notthere: command not found
-127
-./execscript: line 75: notthere: command not found
+./execscript: line 79: notthere: command not found
127
./execscript: line 81: notthere: command not found
127
./execscript: line 83: notthere: command not found
127
-./execscript: line 85: notthere: command not found
+./execscript: line 89: notthere: command not found
+127
+./execscript: line 91: notthere: command not found
+127
+./execscript: line 93: notthere: command not found
127
this is sh
this is sh
${THIS_SH} /
echo $?
+# trying to exec a directory is a fatal error
+${THIS_SH} -c 'exec . ; default: after exec directory' bash
+POSIXLY_CORRECT=1 ${THIS_SH} -c 'exec . ; posix: after exec directory' posix-bash
+
+# even if preceded by `command'
+${THIS_SH} -c 'command exec . ; default: after command exec directory 2' bash
+POSIXLY_CORRECT=1 ${THIS_SH} -c 'command exec . ; posix: after command exec directory 2' posix-bash
+
# try sourcing a directory
. /
echo $?
argv[1] = <abc>
argv[1] = <posix>
argv[1] = <10>
+argv[1] = <5>
+argv[1] = <5>
argv[1] = <file.o>
argv[1] = <posix>
argv[1] = </src/cmd>
expect '<10>'
recho ${#POSIX}
+# this was a problem through bash-5.2 -- it would skip random numbers because
+# of multiple calls to find_variable
+RANDOM=42
+expect '<5>'
+recho ${#RANDOM} # 17772
+declare -i RANDOM=42
+expect '<5>'
+recho ${#RANDOM} # 17772
+
# remove shortest trailing match
x=file.c
expect '<file.o>'
./func4.sub: line 23: foo: maximum function nesting level exceeded (20)
1
after FUNCNEST assign: f = 38
+./func5.sub: line 31: `sys$read': not a valid identifier
11111 ()
{
printf "FUNCNAME: %s\n" $FUNCNAME
echo FUNCNAME: $FUNCNAME
}
FUNCNAME: break
+./func5.sub: line 54: `break': is a special builtin
5
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+# these are ok
+
function a=2
{
printf "FUNCNAME: %s\n" $FUNCNAME
printf "FUNCNAME: %s\n" $FUNCNAME
}
+# but this is still not
+function sys$read
+{
+ printf "FUNCNAME: %s\n" $FUNCNAME
+}
+
declare -f
set -o posix
declare -f
type break
\break
+unset -f break
+
+# but in posix mode, declaring such a function is an error
+set -o posix
+break()
+{
+ echo FUNCNAME: $FUNCNAME
+}
unset x = ?
declare -r RO="foo"
declare -r RO="foo"
+./getopts10.sub: line 33: V: readonly variable
+1
getopts x x
typeset -p RO
+
+readonly V
+getopts x V
+echo $?
+
+
cd $ORIG_DIR
+enable -d strmatch # just testing
exit 0
# test basic behavior of globskipdots
TDIR=/tmp/dotglob-$$
-{ mkdir $TDIR && cd $TDIR; } || exit 1
+{ mkdir $TDIR && cd -L $TDIR; } || exit 1
touch a b aa bb .a .b .aa .bb
TESTDIR=${TMPDIR}/glob-test-$$
mkdir ${TESTDIR}
-cd $TESTDIR || {
+cd -L $TESTDIR || {
echo "$TESTDIR: cannot cd" >&2
exit 1
}
one
two
three
+(exit 42)
+42
5.3
echo ${BASH_VERSION%\.*}
5.3
$ 2
$ exit
0
+a
+b
+c
+d
+ 1 echo a
+ 2 echo c
+ 3 echo d
+ 4 history -d 2
+ 5 history
+./history8.sub: line 15: history: 72: history position out of range
+./history8.sub: line 16: history: -72: history position out of range
${THIS_SH} ./history5.sub
${THIS_SH} ./history6.sub
${THIS_SH} ./history7.sub
+${THIS_SH} ./history8.sub
history
fc -s cat
+
+# try re-executing a failed command, check the exit status
+(exit 42)
+fc -s -1
+echo $?
--- /dev/null
+trap 'rm -f "$OUT"' 0 1 2 3 6 15
+
+HISTFILE=$TMPDIR/fchist-$$ ; OUT=$HISTFILE
+unset HISTIGNORE HISTCONTROL
+set -o history
+
+echo a
+echo b
+echo c
+echo d
+
+history -d 2
+history
+
+history -d 72
+history -d -72
Shell options:
-ilrsD or -c command or -O shopt_option (invocation only)
-abefhkmnptuvxBCEHPT or -o option
-this-bash
+this-bash this-bash
$- for -c includes c
+bash: line 0: badopt: invalid shell option name
+checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
+checkhash:checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
+cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath
+./invocation1.sub: line 40: BASHOPTS: readonly variable
+braceexpand:hashall:interactive-comments
+braceexpand:hashall:interactive-comments
+hashall:interactive-comments
+hashall:interactive-comments
+braceexpand:hashall:interactive-comments:noglob
+braceexpand:hashall:interactive-comments:noglob
+./invocation2.sub: line 50: SHELLOPTS: readonly variable
a
a
bad-interp
# invocation modes and errors
-export BASH_ARGV0=this-bash
-
${THIS_SH} .
#${THIS_SH} --version -c 'exit 0' bash
${THIS_SH} --initfile |& sed 's|^.*/bash|bash|'
${THIS_SH} -q |& sed 's|^.*/bash|bash|'
-${THIS_SH} -c 'echo $0'
+export BASH_ARGV0=this-bash
+${THIS_SH} -c 'echo $0 $BASH_ARGV0'
+unset BASH_ARGV0
{ ${THIS_SH} -c 'echo $-' bash | grep c >/dev/null; } && echo '$- for -c includes c'
+# BASHOPTS
+${THIS_SH} ./invocation1.sub
+# SHELLOPTS
+${THIS_SH} ./invocation2.sub
+
: ${TMPDIR:=/tmp}
TDIR=$TMPDIR/invocation-$$
mkdir $TDIR || exit 1
--- /dev/null
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+set +o posix
+shopt -u xpg_echo
+
+# check $BASHOPTS inheritance
+# the first should be an error
+${THIS_SH} -O checkhash -O badopt -c 'echo $BASHOPTS' bash 2>&1 | sed 's|^.*/bash|bash|'
+# this should reflect the default set of options
+${THIS_SH} -c 'echo $BASHOPTS'
+# now let's turn one of them on (checkhash is not enabled by default)
+${THIS_SH} -O checkhash -c 'echo $BASHOPTS' bash
+# let's turn one of them off
+${THIS_SH} +O checkwinsize -c 'echo $BASHOPTS' bash
+
+# turn on a non-default option
+shopt -s checkhash
+export BASHOPTS
+# and make sure the child shell sees it enabled
+if ${THIS_SH} -c 'echo $BASHOPTS' | grep checkhash >/dev/null 2>&1; then
+ :
+else
+ echo 'BASHOPTS: checkhash not inherited correctly'
+fi
+shopt -u checkhash
+export -n BASHOPTS
+
+# but assigning to BASHOPTS is an error
+BASHOPTS=$BASHOPTS
--- /dev/null
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+set +o posix
+shopt -u xpg_echo
+
+echo $SHELLOPTS
+set +B # on by default
+# shouldn't appear
+echo $SHELLOPTS | grep braceexpand
+export SHELLOPTS
+# but it will appear here because it's enabled by default
+${THIS_SH} -c 'echo $SHELLOPTS'
+
+# turn off an option that's on by default
+${THIS_SH} +B -c 'echo $SHELLOPTS'
+${THIS_SH} +o braceexpand -c 'echo $SHELLOPTS'
+
+# turn on an option that's off by default
+if ${THIS_SH} -f -c 'echo $SHELLOPTS' | grep noglob 2>&1; then
+ :
+else
+ echo 'SHELLOPTS: noglob not inherited correctly'
+fi
+
+# in a different way
+set -o noglob
+if ${THIS_SH} -c 'echo $SHELLOPTS' | grep noglob 2>&1; then
+ :
+else
+ echo 'SHELLOPTS: noglob not inherited correctly'
+fi
+
+# restore default state
+set -o braceexpand
+set +o noglob
+
+# but assigning to SHELLOPTS is an error; have to use set -o/+o
+SHELLOPTS=$SHELLOPTS
2: ok 3
127
./jobs5.sub: line 71: declare: wpid: not found
+./jobs5.sub: line 74: wait: `invalid-varname': not a valid identifier
+./jobs5.sub: line 76: wait: WV: cannot unset: readonly variable
child1 exit status 0
[1]+ Running sleep 20 &
./jobs7.sub: line 5: fg: no current jobs
[1]+ Running sleep 20 &
0
-./jobs.tests: line 40: wait: %1: no such job
-./jobs.tests: line 45: fg: no job control
+./jobs.tests: line 42: wait: %1: no such job
+./jobs.tests: line 47: fg: no job control
wait-for-pid
wait-errors
-./jobs.tests: line 58: wait: `1-1': not a pid or valid job spec
-./jobs.tests: line 59: wait: `-4': not a pid or valid job spec
+./jobs.tests: line 60: wait: `1-1': not a pid or valid job spec
+./jobs.tests: line 61: wait: `-4': not a pid or valid job spec
wait-for-background-pids
async list wait-for-background-pids
async list wait for child
posix jobs output
[1]+ Done sleep 1
wait-for-job
-./jobs.tests: line 84: wait: %2: no such job
+./jobs.tests: line 86: wait: %2: no such job
127
async list wait-for-job
forked
fg-bg 4
sleep 2
fg-bg 5
-./jobs.tests: line 111: fg: %2: no such job
-./jobs.tests: line 112: bg: job 1 already in background
+./jobs.tests: line 113: fg: %2: no such job
+./jobs.tests: line 114: bg: job 1 already in background
fg-bg 6
-./jobs.tests: line 119: fg: -s: invalid option
+./jobs.tests: line 121: fg: -s: invalid option
fg: usage: fg [job_spec]
-./jobs.tests: line 120: bg: -s: invalid option
+./jobs.tests: line 122: bg: -s: invalid option
bg: usage: bg [job_spec ...]
-./jobs.tests: line 125: disown: -s: invalid option
+./jobs.tests: line 127: disown: -s: invalid option
disown: usage: disown [-h] [-ar] [jobspec ... | pid ...]
-./jobs.tests: line 129: disown: %1: no such job
-./jobs.tests: line 132: disown: %2: no such job
+./jobs.tests: line 131: disown: %1: no such job
+./jobs.tests: line 134: disown: %2: no such job
+./jobs.tests: line 137: disown: @12: no such job
wait-for-non-child
-./jobs.tests: line 135: wait: pid 1 is not a child of this shell
+./jobs.tests: line 140: wait: pid 1 is not a child of this shell
127
3 -- 1 2 3 -- 1 - 2 - 3
[1] Running sleep 300 &
[1] Running sleep 300 &
[2]- Running sleep 350 &
[3]+ Running sleep 400 &
-./jobs.tests: line 152: kill: %4: no such job
-./jobs.tests: line 154: jobs: %4: no such job
+./jobs.tests: line 157: kill: %4: no such job
+./jobs.tests: line 159: jobs: %4: no such job
current job:
[3]+ Running sleep 400 &
previous job:
${THIS_SH} ./jobs6.sub
${THIS_SH} ./jobs7.sub
+# more disown -h tests
+${THIS_SH} ./jobs8.sub
jobs
echo $?
# this, however, is an error
disown %2
+# this is definitely an error
+disown -h @12
+
echo wait-for-non-child
wait 1
echo $?
jobs
wait -p wpid
declare -p wpid
+
+# let's check errors like with other builtins that take variable names
+wait -p invalid-varname
+readonly WV
+wait -p WV
--- /dev/null
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# tests of disown -h
+
+set -m
+
+sleep 1&
+sleep 1&
+sleep 1&
+
+disown -ah
+
+sleep 1&
+sleep 1&
+sleep 1&
+
+disown -rh
argv[1] = <op>
argv[1] = <abcdefghijklmnop>
argv[1] = <abcdefghijklmnop>
+./new-exp.tests: line 189: bad-var: invalid variable name
argv[1] = <a>
argv[2] = <b>
argv[3] = <c>
argv[1] = <a>
argv[2] = <b c>
argv[3] = <d>
-./new-exp.tests: line 197: ABX: unbound variable
-./new-exp.tests: line 201: $6: cannot assign in this way
+./new-exp.tests: line 202: ABX: unbound variable
+./new-exp.tests: line 206: $6: cannot assign in this way
argv[1] = <xxcde>
argv[1] = <axxde>
argv[1] = <abxyz>
./new-exp2.sub: line 62: 1111111111111111111111: command not found
argv[1] = <6>
-./new-exp.tests: line 302: ${#:}: bad substitution
+./new-exp.tests: line 307: ${#:}: bad substitution
argv[1] = <'>
argv[1] = <">
argv[1] = <"hello">
argv[7] = <x>
argv[8] = <y>
argv[9] = <z>
-./new-exp.tests: line 520: $9: unbound variable
-./new-exp.tests: line 521: 9: unbound variable
-./new-exp.tests: line 522: UNSET: unbound variable
-./new-exp.tests: line 523: UNSET: unbound variable
-./new-exp.tests: line 524: UNSET: unbound variable
-./new-exp.tests: line 525: UNSET: unbound variable
-./new-exp.tests: line 526: UNSET: unbound variable
+./new-exp.tests: line 525: $9: unbound variable
+./new-exp.tests: line 526: 9: unbound variable
+./new-exp.tests: line 527: UNSET: unbound variable
+./new-exp.tests: line 528: UNSET: unbound variable
+./new-exp.tests: line 529: UNSET: unbound variable
+./new-exp.tests: line 530: UNSET: unbound variable
+./new-exp.tests: line 531: UNSET: unbound variable
argv[1] = <5>
argv[1] = <#>
argv[1] = <#>
Case06---1---A B C::---
Case07---3---A:B:C---
Case08---3---A:B:C---
-./new-exp.tests: line 546: ${$(($#-1))}: bad substitution
+./new-exp.tests: line 551: ${$(($#-1))}: bad substitution
argv[1] = <a>
argv[2] = <b>
argv[3] = <c>
argv[1] = <a>
argv[2] = <b>
argv[1] = <>
-./new-exp.tests: line 565: $(($# - 2)): substring expression < 0
-./new-exp.tests: line 567: -2: substring expression < 0
+./new-exp.tests: line 570: $(($# - 2)): substring expression < 0
+./new-exp.tests: line 572: -2: substring expression < 0
argv[1] = <bin>
argv[2] = <bin>
argv[3] = <ucb>
expect nothing
recho ${!1-$z}
+expect an error
+v=bad-var
+echo ${!v}
+unset -v v
+
set -- a 'b c' d
unset foo
foo=@
unquoted quoted
unquoted quoted
this\&that
+echo a\\;ls
+echo a\'\;ls
+echo 'a'\''b'\;ls
1 2 3 4 5
onestring 0 0 0
onestring 0 0 0.00
--\"abcd\"--
--\'abcd\'--
--a\x--
-./printf.tests: line 95: printf: missing hex digit for \x
+./printf.tests: line 105: printf: missing hex digit for \x
--\x--
----
----
26
26
26
-./printf.tests: line 219: printf: `%10': missing format character
-./printf.tests: line 220: printf: `M': invalid format character
-ab./printf.tests: line 223: printf: `y': invalid format character
-./printf.tests: line 226: printf: GNU: invalid number
+./printf.tests: line 229: printf: `%10': missing format character
+./printf.tests: line 230: printf: `M': invalid format character
+ab./printf.tests: line 233: printf: `y': invalid format character
+./printf.tests: line 236: printf: GNU: invalid number
0
-./printf.tests: line 227: printf: GNU: invalid number
+./printf.tests: line 237: printf: GNU: invalid number
0
-
(foo )(bar )
xx
xx
< >< >
+./printf.tests: line 341: printf: 9223372036854775825: Result too large
+9223372036854775807
+./printf.tests: line 342: printf: -9223372036854775815: Result too large
+-9223372036854775808
one
one\ctwo
4\.2
unquoted quoted
unquoted quoted
this\&that
+'no-quotes-needed'
+'quotes;needed'
1 2 3 4 5
onestring 0 0 0
onestring 0 0 0.00
--\"abcd\"--
--\'abcd\'--
--a\x--
-./printf1.sub: line 107: printf: missing hex digit for \x
+./printf1.sub: line 111: printf: missing hex digit for \x
--\x--
----
----
26
26
26
-./printf1.sub: line 293: printf: `%10': missing format character
-./printf1.sub: line 294: printf: `M': invalid format character
-./printf1.sub: line 297: printf: `y': invalid format character
-./printf1.sub: line 300: printf: GNU: invalid number
+./printf1.sub: line 297: printf: `%10': missing format character
+./printf1.sub: line 298: printf: `M': invalid format character
+./printf1.sub: line 301: printf: `y': invalid format character
+./printf1.sub: line 304: printf: GNU: invalid number
0
-./printf1.sub: line 302: printf: GNU: invalid number
+./printf1.sub: line 306: printf: GNU: invalid number
0
-
(foo )(bar )
printf "%q\n" 'this&that'
+# %Q is like %q but treats the precision differently
+S="a'b"
+S1="${S@Q}"
+T=';ls'
+
+printf 'echo %.2q%q\n' "$S" "$T"
+printf 'echo %.2Q%Q\n' "$S" "$T" # note the difference
+# a different way to do it
+printf 'echo %.*s%q\n' ${#S1} "$S1" "$T"
+
# make sure the format string is reused to use up arguments
printf "%d " 1 2 3 4 5; printf "\n"
# make sure that missing arguments are always handled like the empty string
printf "<%3s><%3b>\n"
+# let's test some out-of-range integer errors for POSIX-specified behavior
+TOOBIG=9223372036854775825
+TOOSMALL=-9223372036854775815
+
+printf '%d\n' "$TOOBIG"
+printf '%d\n' "$TOOSMALL"
+
# tests variable assignment with -v
${THIS_SH} ./printf1.sub
${THIS_SH} ./printf2.sub
printf -v vv "%q\n" 'this&that'
printf "%s" "$vv"
+# altform with %q will force single-quoting
+printf -v vv '%#q\n' no-quotes-needed 'quotes;needed'
+printf "%s" "$vv"
+
# make sure the format string is reused to use up arguments
printf -v vv "%d " 1 2 3 4 5
printf "%s" "$vv"
-\ a b\-
-\-a b\-
-\ a b\-
+argv[1] = <abc>
+argv[1] = <abc\>
argv[1] = <^A>
argv[1] = <^A>
argv[1] = <^?>
echo " \ a b\ " | ( read -r x y ; echo -"$x"-"$y"- )
echo " \ a b\ " | ( read -r x ; echo -"$x"- )
+# input ending in backslash
+printf 'abc\' | { read var ; recho "$var"; }
+printf 'abc\' | { read -r var ; recho "$var"; }
+
# make sure that CTLESC and CTLNUL are passed through correctly
echo $'\001' | ( read var ; recho "$var" )
echo $'\001' | ( read ; recho "$REPLY" )
fd 10
fd 8
fd 10
+next fd
+fd 10
fd 8
1
2
cat u
rm -f u
+# command preceding exec acts as if `command' isn't there
+${THIS_SH} -c 'command exec 10>&1; echo fd 10 >&10; echo next fd' 10>u
+cat u
+rm -f u
+
exec 10>u
exec 10>&1; echo 'fd 10' >&10
cat u
+ foo+=two
+ echo onetwo
onetwo
++ foo=one
++ echo onetwo
+onetwo
+ set +x
1
2
foo+=two
echo $foo
+foo=one echo $foo
+
set +x
# test BASH_XTRACEFD
+t
+1
t -a noexist
1
t -a run-all
0
t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)
1
+t -n xx -a -z "" -a -t 0 -a -t
+0
t /tmp/abc -nt /tmp/def
1
t /tmp/abc -ot /tmp/def
1
t /tmp/abc -ef /tmp/ghi
0
+t noexist -ot /tmp/abc
+0
+t /tmp/abc -ot noexist
+1
+t noexist -nt /tmp/abc
+1
+t noexist -ef /tmp/abc
+1
+t -N noexist
+1
+t -N /tmp/abc
+1
t -r /dev/fd/0
0
t -w /dev/fd/1
0
t -v set
0
+t -R UID
+1
t xx -a yy
0
t xx -o ""
0
t ( "" )
1
+t ( -n xx )
+0
t ! -z "$z"
0
t ! -n "$z"
2
./test.tests: line 26: test: too many arguments
2
-./test.tests: line 434: [: missing `]'
+./test.tests: line 26: test: syntax error: `-t' unexpected
+2
+./test.tests: line 26: test: argument expected
+2
+./test.tests: line 473: [: missing `]'
+2
+./test.tests: line 475: [: missing `]'
2
./test.tests: line 26: test: (: unary operator expected
2
echo $?
}
+echo 't'
+t
+
echo 't -a noexist'
t -a noexist
echo 't -a run-all'
echo 't ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)'
t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)
+# more traditional parsing algorithm
+echo 't -n xx -a -z "" -a -t 0 -a -t'
+t -n xx -a -z "" -a -t 0 -a -t
+
touch /tmp/abc
sleep 2
touch /tmp/def
rm /tmp/abc /tmp/def /tmp/ghi
+touch /tmp/abc
+
+echo 't noexist -ot /tmp/abc'
+t noexist -ot /tmp/abc
+
+echo 't /tmp/abc -ot noexist'
+t /tmp/abc -ot noexist
+
+echo 't noexist -nt /tmp/abc'
+t noexist -nt /tmp/abc
+
+echo 't noexist -ef /tmp/abc'
+t noexist -ef /tmp/abc
+
+echo 't -N noexist'
+t -N noexist
+
+# false; it's been read since modified
+echo 't -N /tmp/abc'
+t -N /tmp/abc
+
+rm -f /tmp/abc
+
echo 't -r /dev/fd/0'
t -r /dev/fd/0
echo 't -w /dev/fd/1'
echo 't -v set'
t -v set
+echo 't -R UID'
+t -R UID
+
echo 't xx -a yy'
t xx -a yy
echo 't xx -o ""'
t \( -E \)
echo 't ( "" )'
t \( "" \)
+echo 't ( -n xx )'
+t \( -n xx \)
z=42
t 4 -eq 4 -a 2 -ne 5 -a 4 -ne
# too many arguments
t 4 -eq 4 -a 3 4
+# syntax error
+t -n xx -a -z "" -a -t 0 -t
+# argument expected
+t -n xx -a -z "" -a -t 0 -a
[
echo $?
+[ -n xx
+echo $?
t \( \)
CHLD
CHLD
CHLD
+BASH_TRAPSIG = USR1
+func=7
+222
+exit=0
+exit=0
+A
+In trap-argument: last command preceding the trap action
+In a function call: last command in the trap action
caught a child death
caught a child death
caught a child death
trap -- 'echo caught a child death' SIGCHLD
+echo caught a child death
+./trap.tests: line 118: trap: cannot specify both -p and -P
+./trap.tests: line 119: trap: -P requires at least one signal name
+trap: usage: trap [-Plp] [[action] signal_spec ...]
+./trap.tests: line 121: trap: -x: invalid option
+trap: usage: trap [-Plp] [[action] signal_spec ...]
trap -- 'echo exiting' EXIT
trap -- 'echo aborting' SIGABRT
trap -- 'echo caught a child death' SIGCHLD
# SIGCHLD traps
${THIS_SH} ./trap8.sub
+# return without argument in trap string
+${THIS_SH} ./trap9.sub
#
# show that setting a trap on SIGCHLD is not disastrous.
wait
trap -p SIGCHLD
+trap -P SIGCHLD
+
+# all errors
+trap -p -P
+trap -P
+trap ''
+trap -x
# Now reset some of the signals the shell handles specially back to
# their default values (with or without the SIG prefix)
FALSE=/bin/false
elif [ -x /usr/bin/false ]; then
FALSE=/usr/bin/false
+elif [ -x /usr/local/bin/false ]; then
+ FALSE=/usr/local/bin/false
else
FALSE='command false'
fi
--- /dev/null
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# return with argument in trap string while function is executing
+trap 'echo BASH_TRAPSIG = $(kill -l $BASH_TRAPSIG); return 7' USR1
+func() { kill -USR1 $$; }
+func
+echo func=$?
+
+# test where return with no argument in a trap string gets its exit status
+# when a function is executing (posix interp 1602)
+
+setexit() { return "$1"; }
+
+# function called in trap string to set $?
+# posix interp 1602: the return in the trap string causees the end of
+# execution of the trap action
+trap 'setexit 222; echo $? ; return' USR1
+process() { kill -USR1 $$; }
+process
+echo exit=$?
+unset -f process
+
+# posix interp 1602; the return in the trap string interrupts loop and causes
+# the end of execution of the trap action
+trap 'setexit 123; return' USR1
+loop() { while :; do :; done; }
+get_loop_exit() { loop; echo "exit=$?"; }
+{ sleep 1; kill -USR1 $$; } &
+get_loop_exit
+unset -f loop get_loop_exit
+
+# posix interp 1602; the return in `check' does not cause the end of execution
+# of the trap action
+check() { false; return; }
+handle() { check && echo B || echo A; }
+trap handle USR1
+kill -USR1 $$
+unset -f check handle
+
+# posix interp 1602: show where we get the value of $? for trap actions
+# return in trap string causes end of execution of trap action
+invoke() { kill -USR1 $$; return 222; }
+trap 'setexit 111; return' USR1
+invoke
+case $? in
+(0) echo 'In trap-argument: last command preceding the trap action' ;;
+(111) echo 'In trap-argument: last command in the trap action' ;;
+(222) echo 'In trap-argument: (failed to exit the function)' ;;
+(*) echo 'In trap-argument: (unexpected)' ;;
+esac
+
+# return in `handler' does not cause the end of execution of the trap action
+stat=99
+handler() { setexit 111; return; }
+trap 'handler; stat=$?; return' USR1
+invoke
+case $stat in
+(0) echo 'In a function call: last command preceding the trap action' ;;
+(111) echo 'In a function call: last command in the trap action' ;;
+(*) echo 'In a function call: (unexpected)' ;;
+esac
+unset -f invoke handler
+unset -f setexit
+
+# posix interp 1602: return in function does not cause end of trap action
+ReturnFalse()
+{
+ false ; return
+}
+
+trap 'ReturnFalse && echo "woops"' EXIT
+(exit 0) # set exit status
./type.tests: line 22: type: -r: invalid option
type: usage: type [-afptP] name [name ...]
./type.tests: line 25: type: notthere: not found
+./type.tests: line 29: command: notthere: not found
function
keyword
builtin
}
while
while is a shell keyword
-./type.tests: line 56: type: m: not found
+./type.tests: line 59: type: m: not found
alias m='more'
alias m='more'
m is aliased to `more'
builtin is a shell builtin
/bin/sh
/bin/sh is /bin/sh
-./type.tests: line 78: type: func: not found
-./type.tests: line 80: type: m: not found
+./type.tests: line 81: type: func: not found
+./type.tests: line 83: type: m: not found
/bin/sh
/tmp/bash
bash is hashed (/tmp/bash)
);
echo "coprocs created"
}
+cat is /bin/cat
+cat is aliased to `echo cat'
+/bin/cat
+break is a shell builtin
+break is a special shell builtin
# this should be a usage error
type -r ${THIS_SH}
-# these should behave identically
+# these should behave identically, but POSIX says command -v is silent if the name is not found
type notthere
command -v notthere
+# but this will produce an error message
+command -V notthere
+
alias m=more
unset -f func 2>/dev/null
type f | cat -v
${THIS_SH} type1.sub
-
${THIS_SH} type2.sub
-
${THIS_SH} type3.sub
-
${THIS_SH} type4.sub
+${THIS_SH} type5.sub
--- /dev/null
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# make sure . is not in $PATH
+PATH=/bin:/usr/bin:/usr/local/bin
+
+# test type -P
+
+# executable in current directory
+TDIR=$TMPDIR/type-$$
+[ -d "$TDIR" ] || mkdir "$TDIR"
+cd -P "$TDIR" || exit 1
+
+touch e ; chmod +x e; type -P e; rm -f e
+
+shopt -s expand_aliases
+
+type cat
+alias cat='echo cat'
+type -f cat
+type -P cat
+
+# some random tests
+
+# the difference between posix and default modes
+type break
+set -o posix; type break; set +o posix
+
+cd "$OLDPWD"
+rm -rf "$TDIR"
local -r myvar=0
echo "${myvar[@]}"
- declare -p myvar
+ local -p myvar
}
foo2()
local -r myvar=1
echo "${myvar}"
- declare -p myvar
+ local -p myvar
}
declare -a outside=()