]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
small changes to some error messages; greatly expanded builtins tests
authorChet Ramey <chet.ramey@case.edu>
Thu, 28 Sep 2023 14:47:17 +0000 (10:47 -0400)
committerChet Ramey <chet.ramey@case.edu>
Thu, 28 Sep 2023 14:47:17 +0000 (10:47 -0400)
71 files changed:
CWRU/CWRU.chlog
MANIFEST
builtins/break.def
builtins/shift.def
subst.c
tests/RUN-ONE-TEST
tests/alias.right
tests/alias.tests
tests/arith-for.right
tests/arith-for.tests
tests/array.right
tests/array.tests
tests/builtins.right
tests/builtins.tests
tests/builtins10.sub [new file with mode: 0644]
tests/builtins8.sub
tests/builtins9.sub
tests/complete.right
tests/complete.tests
tests/comsub.right
tests/comsub.tests
tests/dynvar.right
tests/dynvar.tests
tests/errors.right
tests/errors.tests
tests/errors1.sub
tests/errors7.sub
tests/exec.right
tests/execscript
tests/exp.right
tests/exp.tests
tests/func.right
tests/func5.sub
tests/getopts.right
tests/getopts10.sub
tests/glob-bracket.tests
tests/glob10.sub
tests/glob8.sub
tests/history.right
tests/history.tests
tests/history1.sub
tests/history8.sub [new file with mode: 0644]
tests/invocation.right
tests/invocation.tests
tests/invocation1.sub [new file with mode: 0644]
tests/invocation2.sub [new file with mode: 0644]
tests/jobs.right
tests/jobs.tests
tests/jobs5.sub
tests/jobs8.sub [new file with mode: 0644]
tests/new-exp.right
tests/new-exp.tests
tests/printf.right
tests/printf.tests
tests/printf1.sub
tests/read.right
tests/read.tests
tests/redir.right
tests/redir8.sub
tests/set-x.right
tests/set-x.tests
tests/test.right
tests/test.tests
tests/trap.right
tests/trap.tests
tests/trap2.sub
tests/trap9.sub [new file with mode: 0644]
tests/type.right
tests/type.tests
tests/type5.sub [new file with mode: 0644]
tests/varenv7.sub

index e34b4179930bc9781b460655a6bec1af36a13e27..7c204a1abcde979fc88543c56d7fae83bb21abb7 100644 (file)
@@ -7677,3 +7677,19 @@ execute_cmd.c
          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 `--'
index 85b0040380b96502c362d8b261b1585de868b244..16eac82ffe96aa73c7252bf12d868990a02958ac 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1025,6 +1025,7 @@ tests/builtins6.sub       f
 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
@@ -1262,6 +1263,7 @@ tests/history4.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
@@ -1278,6 +1280,7 @@ tests/intl4.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
@@ -1291,6 +1294,7 @@ tests/jobs4.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
@@ -1568,12 +1572,14 @@ tests/trap5.sub         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
index 820377e1b50e994da80bc2e8c6917e3ac4c7357a..3a2fb851ed23f10eadba97e04875683cbc4b7300 100644 (file)
@@ -73,6 +73,9 @@ break_builtin (WORD_LIST *list)
 
   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);
@@ -114,6 +117,9 @@ continue_builtin (WORD_LIST *list)
 
   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);
index d6519c16b6b7a3fbea675982a0465d4a51bcdba5..b8a4d8ff03b5e3cb798e8ba101c90a705ab279eb 100644 (file)
@@ -68,6 +68,9 @@ shift_builtin (WORD_LIST *list)
     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);
     }
@@ -75,7 +78,13 @@ shift_builtin (WORD_LIST *list)
   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)
diff --git a/subst.c b/subst.c
index 855ff745087ff9342963a99a9137c7d9bc4e2d82..9f4c4e54c7796561b9d09eee743c859b60b583ab 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -8139,6 +8139,7 @@ parameter_brace_expand_length (char *name)
   SHELL_VAR *var;
 
   var = (SHELL_VAR *)NULL;
+  number = 0;
 
   if (name[1] == '\0')                 /* ${#} */
     number = number_of_args ();
@@ -8175,20 +8176,19 @@ parameter_brace_expand_length (char *name)
   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");
@@ -8198,14 +8198,13 @@ parameter_brace_expand_length (char *name)
            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))
        {
index c8bef8dd12533217b1b65fc20d00f3d1cc1b81e7..34b7f66bbea12620512eb77c9626eaf588f09978 100755 (executable)
@@ -10,4 +10,4 @@ export TMPDIR
 export BASH_TSTOUT=/tmp/xx
 rm -f ${BASH_TSTOUT}
 
-/bin/sh "$@"
+${THIS_SH} "$@"
index d5c53f41c93ad9a37217104657cc7c2a14095eef..b6cc7ea6a30fed2f8cb3b2cc67daf22a7d2704ae 100644 (file)
@@ -5,6 +5,8 @@ alias: 0
 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
index 14d3c63f47bebfef49fc6d94cf3de5b482c911d3..437378b09ecb922583347d78b859a094cdd9fa27 100644 (file)
@@ -62,6 +62,10 @@ alias L='m=("x")'
 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
index 06127be890ed3646a134da37bcf583524d1366c3..542abeaf734b60a22c2b1cffefa5e4b0c4e99de7 100644 (file)
@@ -84,3 +84,9 @@ bash: -c: line 1: syntax error: `(( i=0; i < 3; i++; 7 ))'
 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 ")
index db913da5dde8388f0405b7f9cba92468f784b369..47e7e5c52c5b21475fe95410e7a08f78c3ee3a35 100644 (file)
@@ -126,3 +126,12 @@ echo
 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
index b16870dc644cdee5ddb2ccd5a5630966880ea27b..846e05f74de41e4735573ff05ebf7a2b55f36a6f 100644 (file)
@@ -129,7 +129,9 @@ grep [ 123 ] *
 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
@@ -156,10 +158,10 @@ for case if then else
 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
index 714966abf62696d98c26b6bba963b2306c9075e3..10f605559f7dd63edda2d75073dd0dadcc432ba2 100644 (file)
@@ -252,6 +252,9 @@ barray=(new1 new2 new3)
 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]} )
index e0b11ac4c4773beb5cdcb487e5a8e4932defe6cf..94185909952b2bf0233e5901215fe5f04b0de670 100644 (file)
@@ -91,6 +91,7 @@ FOO=BAR
 FOO=BAR
 hash: hash table empty
 0
+no-newline
 AVAR
 foo
 in source.sub2, calling return
@@ -145,11 +146,11 @@ AVAR
 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
@@ -291,6 +292,10 @@ u=rwx,g=rwx,o=rwx
 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
@@ -308,4 +313,136 @@ builtin hash -p /nosuchdir/nosuchfile cat
 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
index a09248692d431bb0b0e64414ee693954c2a5bc15..781c021c9cca63b28a26d12471325ad3e28c5a61 100644 (file)
@@ -71,6 +71,10 @@ for i in a b c; do
 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
@@ -145,11 +149,18 @@ command -p hash rm
 # 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
 
@@ -262,6 +273,13 @@ kill -l 4096
 # 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
 
@@ -286,6 +304,14 @@ ${THIS_SH} ./builtins8.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
 
diff --git a/tests/builtins10.sub b/tests/builtins10.sub
new file mode 100644 (file)
index 0000000..4b9e665
--- /dev/null
@@ -0,0 +1,32 @@
+#   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
index 8b049c09a3f1836fbe28d4c5ac751837bb346deb..ffe9869b080eed7207948061fedb8e6a499b899e 100644 (file)
@@ -63,3 +63,19 @@ umask -S
 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
index d8f6c97c05c4776c5a70e47bcbc173f14769a402..d1fcbec95a91fb943d6565e270b53c20d30e7be4 100644 (file)
@@ -50,3 +50,10 @@ echo $?
 
 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
index c8bf1dc0cca77c5dbad9a2721df38c9a9f241bb0..500ec8f71f8754b4eb02828d23752de5c1d09fce 100644 (file)
@@ -61,3 +61,230 @@ complete -d rmdir
 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
index 36a39833643e2b8c18349bed9953a508fe1c728d..e4c655ce344559605d1df1ea16a20d51a57c0231 100644 (file)
@@ -124,3 +124,17 @@ complete -r notthere
 
 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
index 4a5039d6790fd46c47c1c7df4c426c4c4b19735b..5c856400ddd561034c17ff549cb75649c018507c 100644 (file)
@@ -24,6 +24,7 @@ blank ----
 blank ----
 blank ----
 blank ----
+func: v = comsub
 #esac
 a
 ok 1
index 5969f6ca6da616ac34ba85d96a1ac7eabe0a9d5a..b4ae69b2fd13c38c3d78595e935b76aa9e957d0d 100644 (file)
@@ -91,6 +91,15 @@ read << EOC
 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
index e1344c60db87cb8c3a2dc71ea7c391e153ca115c..fe79552591d34de0c5d10581712473d10173e02e 100644 (file)
@@ -5,3 +5,11 @@ SECONDS ok
 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
index ddf69ed1c3ae64ff44d5550b57958e931836bc91..690f1cc763f1707104e832d5465138457de676fb 100644 (file)
@@ -47,6 +47,11 @@ after=$SECONDS
 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
@@ -99,4 +104,23 @@ ${THIS_SH} -c 'echo $BASH_COMMAND'
 
 # 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
index a95d00807995302cfa962b502d198fe212faba94..76bfbf3209716877dfbcd3845ba753da3b21441b 100644 (file)
@@ -13,110 +13,137 @@ unalias: usage: unalias [-a] name [name ...]
 ./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
@@ -200,6 +227,7 @@ after non-special builtin: 0
 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
@@ -207,6 +235,7 @@ after non-special builtin: 1
 ./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
@@ -238,4 +267,4 @@ sh: line 1: unset: `a-b': not a valid identifier
 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
index 17354dc9185cfef0cccb94908ff6b5c776705df2..5f45cfd35c9e9e748f1dff0feaf180f6689baa71 100644 (file)
@@ -50,6 +50,14 @@ select invalid-name in a b c; do echo $REPLY; done
 (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()
 {
@@ -141,6 +149,10 @@ hash -p ${THIS_SH} ${THIS_SH##*/}
 # 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]
@@ -165,6 +177,7 @@ shift -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
@@ -208,6 +221,10 @@ cd -
 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
 .
@@ -225,15 +242,32 @@ enable sh bash
 # 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
 
@@ -283,6 +317,15 @@ kill -S
 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
index 52a9e342295f407d7d88cd3985d98d8b926d3ad8..840d24e45eb8a90807ac5a4766e19560cd93cee3 100644 (file)
@@ -20,13 +20,14 @@ f()
 
 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()
 {
index 544e3e4c1a254ba519a9e9cc2f54e2e88ea5e632..a564ed5c34a03a7b0cb26c3f473de0677c6eaa0d 100644 (file)
@@ -28,3 +28,6 @@ echo after special builtin: $? )
 echo after assignment error: $? )
 ( x=8
 echo after assignment statement error: $? )
+
+( readonly v; : ${v:=val}
+  echo variable assignment error )
index f9ebaf5ae66618115836addec69dabc956fe7088..3a2469999a038cf390ebfec4e56a3ab1f647cac1 100644 (file)
@@ -15,7 +15,11 @@ after exec1.sub: one two three
 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
@@ -31,17 +35,17 @@ trap -- '' SIGTERM
 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
index f8ecf1edf2d4a8bc4347ca05189a4f462efa07f2..e797c9fc90717a66bac72f4a67dc21fe080ab698 100644 (file)
@@ -43,6 +43,14 @@ echo $?
 ${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 $?
index c1a992900d4b79ab489e4ceb86ff6d7d32b2cb79..6ec11598a69d15dec36630671cf8903bf11cb219 100644 (file)
@@ -88,6 +88,8 @@ argv[1] = <abc>
 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>
index 61a39d3b4c02a22c70e31ece3b4cd073432bfbff..8dc0a601b2684e6fab016fe101d98f0fbd168253 100644 (file)
@@ -237,6 +237,15 @@ POSIX=/usr/posix
 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>'
index b5d6f3425b8cfde953bb656c5bb80684bbb9fb3b..f5341351f29c9caa7af73ab3911c2e8083b187a0 100644 (file)
@@ -166,6 +166,7 @@ after FUNCNEST unset: f = 201
 ./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
@@ -189,4 +190,5 @@ break ()
     echo FUNCNAME: $FUNCNAME
 }
 FUNCNAME: break
+./func5.sub: line 54: `break': is a special builtin
 5
index 7ec19396c26672423402701145844fb65abfa8d0..ef43de21f22abe236b6d96ca5af89a65d45351d2 100644 (file)
@@ -12,6 +12,8 @@
 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+# these are ok
+
 function a=2
 {
        printf "FUNCNAME: %s\n" $FUNCNAME
@@ -22,6 +24,12 @@ function 11111
        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
@@ -36,3 +44,11 @@ break()
 
 type break
 \break
+unset -f break
+
+# but in posix mode, declaring such a function is an error
+set -o posix
+break()
+{
+        echo FUNCNAME: $FUNCNAME
+}
index 599d830a32c49eda4de980bded07b0dbadf7dc97..f5a5262a73625fba66acd5c8559e5c2bdfa66091 100644 (file)
@@ -66,3 +66,5 @@ OPTARG = x = ?
 unset x = ?
 declare -r RO="foo"
 declare -r RO="foo"
+./getopts10.sub: line 33: V: readonly variable
+1
index 49b2bfe9c62bd19fb66f19c6b7814ad3a9b4dfc5..a761bd34dd0e263c64b2f5d4e1a265483cd0dc65 100644 (file)
@@ -28,3 +28,9 @@ typeset -p RO
 
 getopts x x
 typeset -p RO
+
+readonly V
+getopts x V
+echo $?
+
+
index 34580ebba06701d5ed96e0736e5f9715d342d9fc..057ffeb20fdb98b79531b558d0888463f6aad784 100644 (file)
@@ -305,4 +305,5 @@ check 'a\'               'a\'          "$yes"
 
 cd $ORIG_DIR
 
+enable -d strmatch     # just testing
 exit 0
index 7c14c0d24e490d582dd8d924f1f165d048ab80b3..1ee8046ed9dc24533e9cd1a01458b82dba7d20e4 100644 (file)
@@ -15,7 +15,7 @@
 # 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
 
index dca54fcc6c57c0c527d15c86bd6d2d667a1411be..877c8bd100d7ac188ff0456719b4b840ddb8992e 100644 (file)
@@ -15,7 +15,7 @@
 
 TESTDIR=${TMPDIR}/glob-test-$$
 mkdir ${TESTDIR}
-cd $TESTDIR ||  {
+cd -L $TESTDIR ||  {
         echo "$TESTDIR: cannot cd" >&2
         exit 1
 }
index 2f55d330588d4b5d8caeed3fd9f0c7e594f0dcc5..7402bacde47c346f97a97b26bc00fcf43149d866 100644 (file)
@@ -140,6 +140,8 @@ three
 one
 two
 three
+(exit 42)
+42
 5.3
 echo ${BASH_VERSION%\.*}
 5.3
@@ -341,3 +343,14 @@ $ 1
 $ 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
index 2bff8811fcd9818e63f5feb0c999d3e62f57bb11..4cc078ddb1d9920ea68ea34552329fff954b4484 100644 (file)
@@ -132,3 +132,4 @@ ${THIS_SH} ./history4.sub
 ${THIS_SH} ./history5.sub
 ${THIS_SH} ./history6.sub
 ${THIS_SH} ./history7.sub
+${THIS_SH} ./history8.sub
index b67a0efa4ab52974958e764be469eb39ddbbcb87..eb8b4f59f488b8950b6a23eb3bd81b594958d228 100644 (file)
@@ -26,3 +26,8 @@ three
 
 history
 fc -s cat
+
+# try re-executing a failed command, check the exit status
+(exit 42)
+fc -s -1
+echo $?
diff --git a/tests/history8.sub b/tests/history8.sub
new file mode 100644 (file)
index 0000000..77659fc
--- /dev/null
@@ -0,0 +1,16 @@
+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
index 99a82c45a181bce5c865cc596968485b32d7abfd..885a4df141254144bb099c5f8fe6cb78f7d2b168 100644 (file)
@@ -69,8 +69,20 @@ GNU long options:
 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
index f3952892399e3c6b5f37b58f90111feda96e8c6b..84c908ea37e0e3f881262848dde19a19c9ca069b 100644 (file)
@@ -16,8 +16,6 @@
 
 # invocation modes and errors
 
-export BASH_ARGV0=this-bash
-
 ${THIS_SH} .
 
 #${THIS_SH} --version -c 'exit 0' bash
@@ -29,10 +27,17 @@ ${THIS_SH} --badopt |& sed 's|^.*/bash|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
diff --git a/tests/invocation1.sub b/tests/invocation1.sub
new file mode 100644 (file)
index 0000000..ea3d68c
--- /dev/null
@@ -0,0 +1,40 @@
+#   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
diff --git a/tests/invocation2.sub b/tests/invocation2.sub
new file mode 100644 (file)
index 0000000..05de401
--- /dev/null
@@ -0,0 +1,50 @@
+#   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
index 0510e044a0d96faa976702f744679320d5cff47e..9a12a88456673e9b9cdbd035e3dff77d8f47b172 100644 (file)
@@ -33,17 +33,19 @@ i killed it
 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
@@ -52,7 +54,7 @@ wait-when-no-children
 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
@@ -65,19 +67,20 @@ sleep 2
 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 &
@@ -87,8 +90,8 @@ running jobs:
 [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:
index dacdc15d008b98b33735df1a1a87cc567fe1a301..605449aad7b1cc1ad47b6f5ea1331276cc15bd8b 100644 (file)
@@ -32,6 +32,8 @@ ${THIS_SH} ./jobs5.sub
 ${THIS_SH} ./jobs6.sub
 
 ${THIS_SH} ./jobs7.sub
+# more disown -h tests
+${THIS_SH} ./jobs8.sub
 
 jobs
 echo $?
@@ -131,6 +133,9 @@ disown %1
 # this, however, is an error
 disown %2
 
+# this is definitely an error
+disown -h @12
+
 echo wait-for-non-child
 wait 1
 echo $?
index e348f2e2f793ca18344ee1f2eb175a2aab65d63b..23e1b1db9ca2d15b1967cec889b4827645e02558 100644 (file)
@@ -69,3 +69,8 @@ echo $wpid $?
 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
diff --git a/tests/jobs8.sub b/tests/jobs8.sub
new file mode 100644 (file)
index 0000000..8bb21bd
--- /dev/null
@@ -0,0 +1,29 @@
+#   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
index 355abc4b739487f7b544d27bc911824bac608b7f..8aa4b32489cf4fabf66d552ab10218cd97b91192 100644 (file)
@@ -59,6 +59,7 @@ argv[1] = <4>
 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>
@@ -66,8 +67,8 @@ argv[4] = <d>
 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>
@@ -176,7 +177,7 @@ a
 ./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">
@@ -411,13 +412,13 @@ argv[6] = <w>
 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] = <#>
@@ -464,7 +465,7 @@ Case05---3---A:B:C---
 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>
@@ -481,8 +482,8 @@ argv[1] = <a>
 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>
index c542313f12d3c8e54585a84f3a57c8f7e45098bf..cabaf7b0f82ab1a49e2fed3f2a994c9831b3cef2 100644 (file)
@@ -184,6 +184,11 @@ recho ${a-$z}
 expect nothing
 recho ${!1-$z}
 
+expect an error
+v=bad-var
+echo ${!v}
+unset -v v
+
 set -- a 'b c' d
 unset foo
 foo=@
index e99d04a769c1275d5978d98773f60830fef3a970..b5765c918a81535da085dc1189752ee2cb9f2178 100644 (file)
@@ -13,6 +13,9 @@ unquoted
 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
@@ -30,7 +33,7 @@ A7
 --\"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--
 ----
 ----
@@ -91,12 +94,12 @@ A7
 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 )
@@ -149,6 +152,10 @@ b
 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
@@ -161,6 +168,8 @@ unquoted
 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
@@ -174,7 +183,7 @@ A7
 --\"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--
 ----
 ----
@@ -235,12 +244,12 @@ A7
 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 )
index 04a1e481c07ea03e3c417acd6d57ddece70899bb..ee668cc9455dfcdab1df039462b9bc06d2d58984 100644 (file)
@@ -60,6 +60,16 @@ printf "%s%10q\n" unquoted quoted
 
 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"
 
@@ -324,6 +334,13 @@ printf -v var "%b" @(hugo); echo "x${var}x"
 # 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
index 2cbbc6a6a6c55d80f7bd61af3dd2028103b4fd62..7a18a5c6c84296b0eb830a8fe2819e4c6a554d15 100644 (file)
@@ -60,6 +60,10 @@ printf "%s"  "$vv"
 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"
index e21fcb5f2d9e2b810befc85922a9f652edaf550b..5f672679452d0d69ffa70f73f3d5724f814fe241 100644 (file)
@@ -9,6 +9,8 @@ a.
 -\ a  b\-
 -\-a  b\-
 -\ a  b\-
+argv[1] = <abc>
+argv[1] = <abc\>
 argv[1] = <^A>
 argv[1] = <^A>
 argv[1] = <^?>
index e5c9bc5a69d0b6c7c9e190f90091351c55b024f7..f05acbf7b74d95e3595cca26228e4af80d125b7d 100644 (file)
@@ -26,6 +26,10 @@ echo "\ a  b\ " | ( read -r x ; echo -"$x"- )
 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" )
index 458befdd723ce8540879756baef39341719ae1fb..d836f0850929d489f17a33f7a72c3994cb3561d4 100644 (file)
@@ -118,6 +118,8 @@ c4 is 4
 fd 10
 fd 8
 fd 10
+next fd
+fd 10
 fd 8
 1
 2
index d2d700cbaabe733a0b606b9db5b7bb269fb3aa62..314cb1c0fec1cb5c7360e505410456546c2e6d51 100644 (file)
@@ -22,6 +22,11 @@ ${THIS_SH} -c 'exec 8>&1; echo fd 8 >&8' 8>u
 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
index 259602e5ec35f741a4b07dab75b5aeda231a0a23..230b1df118d09171e8d2c7bf025112f34af91709 100644 (file)
@@ -30,6 +30,9 @@
 + foo+=two
 + echo onetwo
 onetwo
++ foo=one
++ echo onetwo
+onetwo
 + set +x
 1
 2
index 3723552dc9a18d9531becb164921319b95a3d031..74523bd48c5a106319be142ed4e16c5c70c77ce8 100644 (file)
@@ -32,6 +32,8 @@ foo=one
 foo+=two
 echo $foo
 
+foo=one echo $foo
+
 set +x
 
 # test BASH_XTRACEFD
index 0927ad086c5f3959f626437bf4d3806e75ba1469..cb3f94dd307ce48ea1c07202d89887ef9103a59b 100644 (file)
@@ -1,3 +1,5 @@
+t
+1
 t -a noexist
 1
 t -a run-all
@@ -136,6 +138,8 @@ t 700 -le 1000 -a -n "1" -a "20" = "20"
 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
@@ -148,6 +152,18 @@ t /tmp/abc -ef /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
@@ -186,6 +202,8 @@ t -v set
 0
 t -v set
 0
+t -R UID
+1
 t xx -a yy
 0
 t xx -o ""
@@ -216,6 +234,8 @@ t ( -E )
 0
 t ( "" )
 1
+t ( -n xx )
+0
 t ! -z "$z"
 0
 t ! -n "$z"
@@ -274,7 +294,13 @@ b ( 1 = 2
 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
index a30ae036663f40155d36605b7bbd9ef6d754665c..117918d88ee22cd7690822f31cb418f5c10b2261 100644 (file)
@@ -27,6 +27,9 @@ t()
        echo $?
 }
 
+echo 't'
+t
+
 echo 't -a noexist'
 t -a noexist
 echo 't -a run-all'
@@ -244,6 +247,10 @@ t 700 -le 1000 -a -n "1" -a "20" = "20"
 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
@@ -265,6 +272,29 @@ t /tmp/abc -ef /tmp/ghi
 
 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'
@@ -317,6 +347,9 @@ set=set
 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 ""'
@@ -349,6 +382,8 @@ echo 't ( -E )'
 t \( -E \)
 echo 't ( "" )'
 t \( "" \)
+echo 't ( -n xx )'
+t \( -n xx \)
 
 z=42
 
@@ -430,9 +465,15 @@ t -A v
 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 \( \)
 
index 58d868368940022af8a043b0816b6045e9a63cfd..7eab47520a4e7b5322adfd42bc46b05f4ea9d656 100644 (file)
@@ -111,10 +111,24 @@ CHLD
 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
index 902de24db1a069169348944ad12f65cab4e9366c..8f4a09559da36e725eb6e929da7d82ce55284f72 100644 (file)
@@ -96,6 +96,8 @@ ${THIS_SH} ./trap7.sub
 # 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.
@@ -110,6 +112,13 @@ sleep 7 & sleep 6 & sleep 5 &
 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)
index bd9a76be84c774e950ccd3a4450f9962e75b8eab..f5567db0a2a2cd415c9dcdce72135ca6fd2d4009 100755 (executable)
@@ -54,6 +54,8 @@ if [ -x /bin/false ]; then
         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
diff --git a/tests/trap9.sub b/tests/trap9.sub
new file mode 100644 (file)
index 0000000..484f03b
--- /dev/null
@@ -0,0 +1,84 @@
+#   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
index 6cfa14edcebbe619b7d8f671cd8867ea81536bcb..a3fd4b9b552f0b278f09dbd6870db6e433a0601f 100644 (file)
@@ -1,6 +1,7 @@
 ./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
@@ -24,7 +25,7 @@ func ()
 }
 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'
@@ -37,8 +38,8 @@ builtin
 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)
@@ -133,3 +134,8 @@ EOF
  );
     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
index fd39c18a310474d2f7d95ce56f14b94b3a28dae5..13e6cc46397ede751a7874392762cafe89be8650 100644 (file)
@@ -21,10 +21,13 @@ type
 # 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
@@ -102,9 +105,7 @@ f() {
 type f | cat -v
 
 ${THIS_SH} type1.sub
-
 ${THIS_SH} type2.sub
-
 ${THIS_SH} type3.sub
-
 ${THIS_SH} type4.sub
+${THIS_SH} type5.sub
diff --git a/tests/type5.sub b/tests/type5.sub
new file mode 100644 (file)
index 0000000..1bd879e
--- /dev/null
@@ -0,0 +1,41 @@
+#   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"
index 4b25960612aedf4cde622750960e34fd271a8c92..078d2db8e2050b1f710e87ba27bfb35a1d971c38 100644 (file)
@@ -17,7 +17,7 @@ foo()
        local -r myvar=0
 
        echo "${myvar[@]}"
-       declare -p myvar
+       local -p myvar
 }
 
 foo2()
@@ -26,7 +26,7 @@ foo2()
        local -r myvar=1
 
        echo "${myvar}"
-       declare -p myvar
+       local -p myvar
 }
 
 declare -a outside=()