From 76ed53ad0e90e83cc68b61711d1355723399fc54 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Mon, 15 Jan 2024 02:11:03 +0000 Subject: [PATCH] Fix 'export foo+=bar', etc. Example reproducers: $ typeset foo+=bar -ksh: typeset: foo+: invalid variable name $ export foo+=bar -ksh: export: foo+: is not an identifier Expected result: 'bar' is appended to the value of foo and (in the 'export' case) then exported. This works on mksh and bash. Oddly enough, the following does work: $ unset foo $ foo[23]=bar $ typeset foo[23]+=baz $ typeset -p foo typeset -x -a foo=([23]=barbaz) The fact that it works *with* an array subscript strongly suggests that it is supposed to work without one. Indeed, testing historical ksh versions shows that this used to work but stopped working in version 93q+ 2005-05-22. The simple() function in parse.c, where it isolates a variable name from the rest of the assignment, has explicit code for recognising array subscripts preceding both '=' and '+='. But the same is simply not implemented for an assignment with a simple variable name. src/cmd/ksh93/sh/parse.c: simple(): - Add that missing implementation: decrease 'last' (pointer to the character following the last character of the variable name) if '+' is found before '='. --- NEWS | 6 ++++++ src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh/parse.c | 2 ++ src/cmd/ksh93/tests/append.sh | 16 +++++++++++++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index e63211b9df03..1040603cd435 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,12 @@ This documents significant changes in the 1.0 branch of ksh 93u+m. For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0 Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library. +2024-01-15: + +- Fixed a bug, introduced in ksh93q+ 2005-05-22, that stopped an append + assignment from working together with a declaration command. For example, + 'typeset var+=value' or 'export var+=value' now again work as expected. + 2024-01-14: - Fixed a regression introduced on 2022-11-01 that caused ksh to enter diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 52676048569b..ad1b2028908f 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -18,7 +18,7 @@ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_SVER "1.0.9-beta" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2024-01-14" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2024-01-15" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2024 Contributors to ksh " SH_RELEASE_FORK /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ diff --git a/src/cmd/ksh93/sh/parse.c b/src/cmd/ksh93/sh/parse.c index a82926fe4ba7..a4456954a1a8 100644 --- a/src/cmd/ksh93/sh/parse.c +++ b/src/cmd/ksh93/sh/parse.c @@ -1483,6 +1483,8 @@ static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io) last = strchr(argp->argval,'='); if(last && (last[-1]==']'|| (last[-1]=='+' && last[-2]==']')) && (cp=strchr(argp->argval,'[')) && (cp < last) && cp[-1]!='.') last = cp; + else if(last && last[-1]=='+') + last--; stkseek(sh.stk,ARGVAL); sfwrite(sh.stk,argp->argval,last-argp->argval); ap=(struct argnod*)stkfreeze(sh.stk,1); diff --git a/src/cmd/ksh93/tests/append.sh b/src/cmd/ksh93/tests/append.sh index 50ed5efb493c..a86a1fa93d5b 100755 --- a/src/cmd/ksh93/tests/append.sh +++ b/src/cmd/ksh93/tests/append.sh @@ -2,7 +2,7 @@ # # # This software is part of the ast package # # Copyright (c) 1982-2012 AT&T Intellectual Property # -# Copyright (c) 2020-2022 Contributors to ksh 93u+m # +# Copyright (c) 2020-2024 Contributors to ksh 93u+m # # and is licensed under the # # Eclipse Public License, Version 2.0 # # # @@ -104,4 +104,18 @@ typeset -a arr2 } 2> /dev/null [[ $(typeset -p arr2) == "$exp" ]] || err_exit 'append (b=c xxxxx) to indexed array not working' +# ====== +unset foo +exp='typeset -x foo=barbaz' +got=$(foo=bar; export foo+=baz 2>&1 && typeset -p foo) +[[ e=$? -eq 0 && $got == "$exp" ]] || err_exit 'declaration command does not support +=' \ + "(expected status 0, $(printf %q "$exp");" \ + "got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))" +exp='typeset -x -a foo=([23]=barbaz)' +got=$(foo[23]=bar; export foo[23]+=baz 2>&1 && typeset -p foo) +[[ e=$? -eq 0 && $got == "$exp" ]] || err_exit 'declaration command does not support +=' \ + "(expected status 0, $(printf %q "$exp");" \ + "got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))" + +# ====== exit $((Errors<125?Errors:125))