From b93216ce88b2aa54a38013f2dd186fb263c35672 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Fri, 10 Jun 2022 02:57:13 +0100 Subject: [PATCH] typeset -T: fix spurious 2nd error on redef (re: 1fbbeaa1, d309d604) Reproducers: $ ksh -c 'typeset -T foo=(x=1); typeset -T foo=(integer x)' ksh: typeset: foo: type cannot be redefined ksh: foo: type definition requires compound assignment $ ksh -c 'typeset -T foo=(x=1); typeset -T foo=(integer x=2)' ksh: foo: type cannot be redefined ksh: foo: type definition requires compound assignment In both cases, the second error message is spurious, as there is in fact a compound assignment. The first case was introduced in 1fbbeaa1. The 'integer' command no longer resolves to a special built-in but is now a regular built-in so it does not cause the shell to exit on error. The code path continues and nv_mktype() is called which issues the bad error as the compound assignment was not fully processed. The second case was introduced in d309d604. This commit inhibits the exit-on-error for the assignment list of a regular built-in. For type definitions, nv_mktype() is called via this code path too. Since all declaration commands were either special built-ins or aliases to special built-ins in 93u+, they all exited on error and this problem never happened. Now that some regular built-ins are allowed inside 'typeset -T', we need some special-casing to make them exit on error as before. Arguably this is the correct thing to do anyway, as their errors are also an error in the enveloping 'typeset' which is a special built-in. This regression is cosmetic and the case is rare, so this is probably not worth a NEWS item. src/cmd/ksh93/sh/xec.c: sh_exec(): - Fix the second case by adding a test for non-NULL 'sh.mktype' to the conditions where the assignments list is processed with exit on error. This pointer is set while executing a type definition. - Fix the first case by saving the sh.mktype state before executing a built-in and then checking the saved value if a built-in exits on error. Saving is needed as sh.mktype has been reset by then. --- src/cmd/ksh93/sh/xec.c | 9 +++++---- src/cmd/ksh93/tests/pointtype.sh | 8 ++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index 3c21e62f6..b998617ed 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -1099,9 +1099,10 @@ int sh_exec(register const Shnode_t *t, int flags) else flgs |= NV_VARNAME; /* execute the list of assignments */ - if((!np || nv_isattr(np,BLT_SPC)) && !command) + if((!np || nv_isattr(np,BLT_SPC)) && !command || sh.mktype) { - /* bare assignment(s) or special builtin, and no 'command' prefix: exit on error */ + /* (bare assignment(s) or special builtin) and no 'command' prefix, + * or we're inside a type definition: exit on error */ nv_setlist(argp,flgs,tp); } else @@ -1224,7 +1225,7 @@ int sh_exec(register const Shnode_t *t, int flags) /* check for builtins */ if(np && is_abuiltin(np) && !sh_isstate(SH_XARG)) { - volatile int scope=0, share=0; + volatile char scope=0, share=0, was_mktype=(sh.mktype!=NIL(void*)); volatile void *save_ptr; volatile void *save_data; int save_prompt; @@ -1378,7 +1379,7 @@ int sh_exec(register const Shnode_t *t, int flags) if(sh.bltinfun && (error_info.flags&ERROR_NOTIFY)) (*sh.bltinfun)(-2,com,(void*)bp); /* failure on special built-ins fatal */ - if(jmpval<=SH_JMPCMD && (!nv_isattr(np,BLT_SPC) || command)) + if(jmpval<=SH_JMPCMD && (!nv_isattr(np,BLT_SPC) || command) && !was_mktype) jmpval=0; #if !SHOPT_DEVFD fifo_cleanup(); diff --git a/src/cmd/ksh93/tests/pointtype.sh b/src/cmd/ksh93/tests/pointtype.sh index 0b9d57277..5a603ab92 100755 --- a/src/cmd/ksh93/tests/pointtype.sh +++ b/src/cmd/ksh93/tests/pointtype.sh @@ -84,6 +84,14 @@ typeset -T Pt_t=( Pt_t p [[ ${p.y} == 6 ]] || err_exit '${p.y} != 6' (( p.len == 7 )) || err_exit '((p.len !=7))' +# check for correct error message when failing to redefine a type +exp=': Pt_t: type cannot be redefined' +got=$(set +x; { typeset -T Pt_t=(float foo); } 2>&1); +[[ $got != *$'\n'* && $got == *"$exp" ]] || err_exit "incorrect error on failing to redefine type" \ + "(expected match of *$(printf %q "$exp"), got $(printf %q "$got"))" +got=$(set +x; { typeset -T Pt_t=(float foo=1); } 2>&1); +[[ $got != *$'\n'* && $got == *"$exp" ]] || err_exit "incorrect error on failing to redefine type" \ + "(expected match of *$(printf %q "$exp"), got $(printf %q "$got"))" z=() Pt_t -a z.p