runtime(sh): Do not conflate empty array and function declarations in Bash
Commit:
https://github.com/vim/vim/commit/23c77d8ec8c8e8f35b2301648c9c1727ebcefedf
Author: Aliaksei Budavei <
0x00...@gmail.com>
Date: Sun May 17 18:05:13 2026 +0000
runtime(sh): Do not conflate empty array and function declarations in Bash
Although the "=" character is permitted in function names,
a construct that parses as a variable assignment is
preferred to it parsing as a function declaration. See the
updated test file "sh_functions_bash.sh" for details.
fixes: #20183
closes: #20205
Co-authored-by: Doug Kearns <
dougk...@gmail.com>
Signed-off-by: Aliaksei Budavei <
0x00...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim
index 41570cce4..044f2a9e3 100644
--- a/runtime/syntax/sh.vim
+++ b/runtime/syntax/sh.vim
@@ -3,30 +3,7 @@
" Maintainer: This runtime file is looking for a new maintainer.
" Previous Maintainers: Charles E. Campbell
" Lennart Schultz <
Lennart...@ecmwf.int>
-" Last Change: 2024 Mar 04 by Vim Project {{{1
-" 2024 Nov 03 by Aliaksei Budavei <0x000c70 AT gmail DOT com> improved bracket expressions, #15941
-" 2025 Jan 06 add $PS0 to bashSpecialVariables #16394
-" 2025 Jan 18 add bash coproc, remove duplicate syn keywords #16467
-" 2025 Mar 21 update shell capability detection #16939
-" 2025 Apr 03 command substitution opening paren at EOL #17026
-" 2025 Apr 10 improve shell detection #17084
-" 2025 Apr 29 match escaped chars in test operands #17221
-" 2025 May 06 improve single-quote string matching in parameter expansions
-" 2025 May 06 match KornShell compound arrays
-" 2025 May 10 improve wildcard character class lists
-" 2025 May 21 improve supported KornShell features
-" 2025 Jun 16 change how sh_fold_enabled is reset #17557
-" 2025 Jul 18 properly delete :commands #17785
-" 2025 Aug 23 bash: add support for ${ cmd;} and ${|cmd;} #18084
-" 2025 Sep 23 simplify ksh logic, update sh statements #18355
-" 2026 Jan 15 highlight command switches that contain a digit
-" 2026 Feb 11 improve support for KornShell function names and variables
-" 2026 Feb 15 improve comment handling #19414
-" 2026 Mar 23 improve matching of function definitions #19638
-" 2026 Apr 02 improve matching of function definitions #19849
-" 2026 Apr 19 improve detection of special variables #20016
-" 2026 May 14 don't highlight parens as part of the function name #20219
-" }}}
+" Last Change: 2026 May 17 by Vim Project
" Version: 208
" Former URL:
http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
" For options and settings, please use: :help ft-sh-syntax
@@ -281,7 +258,7 @@ syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial
syn cluster shDerefVarList contains=shDerefOffset,shDerefOp,shDerefVarArray,shDerefOpError
syn cluster shEchoList contains=shArithmetic,shBracketExpr,shCommandSub,shCommandSubBQ,shDerefVarArray,shSubshare,shValsub,shDeref,shDerefSimple,shEscape,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote
syn cluster shExprList1 contains=shBracketExpr,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq
-syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest
+syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest,shFunctionNameError
syn cluster shFunctionCmds contains=shFor,shCaseEsac,shIf,shRepeat,shDblBrace,shDblParen
if exists("b:is_ksh88") || exists("b:is_mksh")
" Offer "shFunctionCmds" as is.
@@ -307,7 +284,7 @@ if exists("b:is_kornshell") || exists("b:is_bash")
endif
syn cluster shPPSLeftList contains=shAlias,shArithmetic,shBracketExpr,shCmdParenRegion,shCommandSub,shSubshare,shValsub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
syn cluster shPPSRightList contains=shDeref,shDerefSimple,shEscape,shPosnParm
-syn cluster shSubShList contains=shBracketExpr,@shCommandSubList,shCommandSubBQ,shSubshare,shValsub,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator
+syn cluster shSubShList contains=shBracketExpr,@shCommandSubList,shCommandSubBQ,shSubshare,shValsub,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator,shFunctionNameError
syn cluster shTestList contains=shArithmetic,shBracketExpr,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr
syn cluster shNoZSList contains=shSpecialNoZS
syn cluster shForList contains=shTestOpr,shNumber,shDerefSimple,shDeref,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shArithmetic
@@ -676,6 +653,12 @@ if exists("b:is_bash")
syn match shFunctionTwo "\%#=1\%(\%(\<\k\+\|[^()<>|&$; ]\+\)\+\)\@>\ze\s*\%(()\ze\)\=\_s*{" contained skipwhite skipnl nextgroup=shFunctionExpr contains=shFunctionParens
syn match shFunctionThree "\%#=1^\s*\zs\%(\%(\<\k\+\|[^()<>|&$; ]\+\)\+\)\@>\s*()\ze\_s*((\@!" skipwhite skipnl nextgroup=shFunctionSubSh contains=shFunctionParens
syn match shFunctionFour "\%#=1\%(\%(\<\k\+\|[^()<>|&$; ]\+\)\+\)\@>\ze\s*\%(\%(()\ze\)\=\)\@>\_s*((\@!" contained skipwhite skipnl nextgroup=shFunctionSubSh contains=shFunctionParens
+ " Claim empty array assignments.
+ syn match shArrayEmptyDecl "\%#=1\ze\%(\<\h\w*=\)\@>()" transparent nextgroup=shVariable
+
+ if !exists("g:sh_no_error")
+ syn match shFunctionNameError "\%#=1\%(\%(\<\h\w*\)\@>=\)\%(\%(\w\+\)\@>=\=\)\+()" skipwhite skipnl nextgroup=shExpr,shSubSh
+ endif
elseif exists("b:is_ksh88")
" AT&T ksh88
syn match shFunctionCmdOne "^\s*\zs\h\w*\s*()\ze\_s*\%(\%(for\|case\|select\|if\|while\|until\)\>\|\[\[\s\|((\)" skipwhite skipnl nextgroup=@shFunctionCmds contains=shFunctionParens
@@ -970,6 +953,9 @@ if !exists("skip_sh_syntax_inits")
hi def link shInError Error
hi def link shParenError Error
hi def link shTestError Error
+ if exists("b:is_bash")
+ hi def link shFunctionNameError Error
+ endif
if exists("b:is_kornshell") || exists("b:is_posix")
hi def link shDTestError Error
endif
diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_01.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_01.dump
index de0d7d6f1..aba361e65 100644
--- a/runtime/syntax/testdir/dumps/sh_functions_bash_01.dump
+++ b/runtime/syntax/testdir/dumps/sh_functions_bash_01.dump
@@ -17,4 +17,4 @@
| +0#0000e05#a8a8a8255@1|f+0#af5f00255#ffffff0|o|r| +0#0000000&|x| |i+0#af5f00255&|n| +0#0000000&|1+0#e000002&| +0#0000000&|2+0#e000002&| +0#0000000&@60
|-+0#0000e05#a8a8a8255| |d+0#af5f00255#ffffff0|o| +0#0000000&@70
||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|:| @67
-@57|1|9|,|1| @9|3|6|%|
+@57|1|9|,|1| @9|1|6|%|
diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_02.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_02.dump
index 8016beea4..8901e58ac 100644
--- a/runtime/syntax/testdir/dumps/sh_functions_bash_02.dump
+++ b/runtime/syntax/testdir/dumps/sh_functions_bash_02.dump
@@ -16,5 +16,5 @@
|3+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|}+0#e000e06&| +0#0000000&@63
|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|@|伪|!+0#af5f00255&| +0#0000000&|"+0#af5f00255&|$+0#e000e06&|1|"+0#af5f00255&| +0#0000000&@56
|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|)+0#af5f00255&| +0#0000000&@67
-||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|e+0#af5f00255&|v|a|l| +0#0000000&|!+0#af5f00255&|?+0#0000000&|\+0#e000e06&|#| +0#0000000&|"+0#af5f00255&|$+0#e000e06&|1|"+0#af5f00255&| +0#0000000&@54
-@57|3|7|,|1| @9|8|6|%|
+||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|e+0#af5f00255&|v|a|l| +0#0000000&|!+0#af5f00255&|?+0#0000000&|\+0#e000e06&|#| +0#0000000&|"+0#af5f00255&|\+0#e000e06&|"|$|1|\|"|"+0#af5f00255&| +0#0000000&@50
+@57|3|7|,|1| @9|4|0|%|
diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_03.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_03.dump
index a90642e1d..98fcc942e 100644
--- a/runtime/syntax/testdir/dumps/sh_functions_bash_03.dump
+++ b/runtime/syntax/testdir/dumps/sh_functions_bash_03.dump
@@ -1,20 +1,20 @@
-||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|e+0#af5f00255&|v|a|l| +0#0000000&|!+0#af5f00255&|?+0#0000000&|\+0#e000e06&|#| +0#0000000&|"+0#af5f00255&|$+0#e000e06&|1|"+0#af5f00255&| +0#0000000&@54
+||+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|e+0#af5f00255&|v|a|l| +0#0000000&|!+0#af5f00255&|?+0#0000000&|\+0#e000e06&|#| +0#0000000&|"+0#af5f00255&|\+0#e000e06&|"|$|1|\|"|"+0#af5f00255&| +0#0000000&@50
||+0#0000e05#a8a8a8255| |f+0#af5f00255#ffffff0|i| +0#0000000&@70
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@72
| +0#0000e05#a8a8a8255@1|n+0#00e0e07#ffffff0|a|m|e|s|p|a|c|e| |(+0#e000e06&|)| +0#0000000&@60
|-+0#0000e05#a8a8a8255| |{+0#e000e06#ffffff0| +0#0000000&|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|#|;+0#af5f00255&| +0#0000000&@62
||+0#0000e05#a8a8a8255| >}+0#e000e06#ffffff0|;+0#0000000&| |n|a|m|e|s|p|a|c|e| |$+0#e000e06&|@| +0#0000000&@57
-|~+0#4040ff13&| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-|~| @73
-| +0#0000000&@56|5@1|,|1| @9|B|o|t|
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@72
+| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |W|h|e|t|h|e|r| |"|=|"| |b|e|l|o|n|g|s| |t|o| |a| |n|a|m|e| |o|r| |d|e|l|i|m|i|t|s| |a| |n|a|m|e| |d|e|p|e|n|d|s| |o|n| |w|h|e|t|h|e|r| +0#0000000&@3
+| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |t|h|e| |r|e|s|e|r|v|e|d| |w|o|r|d| |"|f|u|n|c|t|i|o|n|"| |i|s| |p|r|e|s|e|n|t|,| |i|f| |s|o|,| |t|h|e|n| |"|=|"| |i|s| |p|a|r|t| |o|f| +0#0000000&@3
+| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |t|h|e| |f|u|n|c|t|i|o|n| |n|a|m|e|;| |e|l|s|e|,| |"|=|"| |d|e|l|i|m|i|t|s| |t|h|e| |n|a|m|e| |o|f| |a| |v|a|r|i|a|b|l|e| |w|h|e|n| |t|h|i|s| +0#0000000&
+| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |n|a|m|e| |i|s| |g|i|v|e|n| |i|n| |a|l|p|h|a|n|u|m|e|r|i|c| |c|h|a|r|a|c|t|e|r|s| |a|n|d| |"|_|"|s| |b|e|f|o|r|e| |t|h|e| |l|e|f|t|m|o|s|t| +0#0000000&@1
+| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |"|=|"|;| |o|t|h|e|r|w|i|s|e|,| |"|=|"| |i|s| |p|a|r|t| |o|f| |t|h|e| |f|u|n|c|t|i|o|n| |n|a|m|e| |w|h|e|n| |t|h|i|s| |n|a|m|e| |h|a|s| +0#0000000&@3
+| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |o|n|e| |o|r| |m|o|r|e| |s|u|p@1|o|r|t|e|d| |N|O|N|-|a|l|p|h|a|n|u|m|e|r|i|c| |(|o|r| |"|_|"|)| |c|h|a|r|a|c|t|e|r|s| |b|e|f|o|r|e| |"|=|"|.| +0#0000000&
+| +0#0000e05#a8a8a8255@1|x+0#00e0e07#ffffff0|s|=+0#0000000&|(+0#e000e06&|)| +0#0000000&@67
+| +0#0000e05#a8a8a8255@1|(+0#e000e06#ffffff0| +0#0000000&@71
+| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@3|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|(@1| |1+0#e000002&| +0#e000e06&|+| |$|{|#|x|s|[|*+0#0000000&|]+0#e000e06&|}| |)@1| +0#0000000&@43
+| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@3|x+0#00e0e07&|s|=+0#0000000&|(+0#e000e06&|)| +0#0000000&@63
+| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@3|{| +0#0000000&@67
+| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@7|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|(@1| |2+0#e000002&| +0#e000e06&|+| |$|{|#|x|s|[|*+0#0000000&|]+0#e000e06&|}| |)@1| +0#0000000&@39
+@57|5@1|,|1| @9|6|3|%|
diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_04.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_04.dump
new file mode 100644
index 000000000..d1be88c7d
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/sh_functions_bash_04.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@7|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|(@1| |2+0#e000002&| +0#e000e06&|+| |$|{|#|x|s|[|*+0#0000000&|]+0#e000e06&|}| |)@1| +0#0000000&@39
+| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@7|x+0#00e0e07&|s|=+0#0000000&|(+0#e000e06&|)| +0#0000000&@59
+| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@7|i+0#af5f00255&|f| |:+0#e000e06&|;+0#af5f00255&| +0#e000e06&|t+0#af5f00255&|h|e|n| +0#e000e06&|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|(@1| |3+0#e000002&| +0#e000e06&|+| |$|{|#|x|s|[|*+0#0000000&|]+0#e000e06&|}| |)@1|;+0#af5f00255&| +0#e000e06&|f+0#af5f00255&|i| +0#0000000&@24
+| +0#0000e05#a8a8a8255@1| +0#e000e06#ffffff0@3|}| +0#0000000&@67
+| +0#0000e05#a8a8a8255@1|)+0#e000e06#ffffff0| +0#0000000&@71
+| +0#0000e05#a8a8a8255@1> +0#0000000#ffffff0@72
+|-+0#0000e05#a8a8a8255| |i+0#00e0e07#ffffff0|未|=|(+0#e000e06&|)| +0#0000000&|(+0#af5f00255&| +0#0000000&@65
+|-+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|=+0#00e0e07&|i|d|=|(+0#e000e06&|)| +0#0000000&|{+0#e000e06&| +0#0000000&@60
+|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|=+0#00e0e07&@2|(+0#e000e06&|)| +0#0000000&@59
+|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|i+0#af5f00255&|f| |:+0#0000000&|;+0#af5f00255&| +0#0000000&|t+0#af5f00255&|h|e|n| +0#0000000&|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|*|;+0#af5f00255&| +0#0000000&|f+0#af5f00255&|i|;| +0#0000000&|=+0#af5f00255&@2| +0#0000000&|$+0#e000e06&|*| +0#0000000&@34
+|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|}+0#e000e06&|;+0#af5f00255&| +0#0000000&|=+0#af5f00255&|i|d|=| +0#0000000&|$+0#e000e06&|*| +0#0000000&@58
+||+0#0000e05#a8a8a8255| |)+0#af5f00255#ffffff0|;+0#0000000&| |i+0#af5f00255&|d|=| +0#0000000&|i|未|=+0#af5f00255&| +0#0000000&|i|未|=+0#af5f00255&| +0#0000000&|i|未|=+0#af5f00255&| +0#0000000&@54
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@72
+|-+0#0000e05#a8a8a8255| |f+0#af5f00255#ffffff0|u|n|c|t|i|o|n| +0#0000000&|f+0#00e0e07&|=|(+0#e000e06&|)| +0#0000000&|(+0#af5f00255&| +0#0000000&@57
+|-+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|f+0#af5f00255&|u|n|c|t|i|o|n| +0#0000000&|f+0#00e0e07&|=|f| +0#0000000&|{+0#e000e06&| +0#0000000&@54
+|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|f+0#af5f00255&|u|n|c|t|i|o|n| +0#0000000&|f+0#00e0e07&|=|f|=| +0#0000000&@51
+|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@7|i+0#af5f00255&|f| |:+0#0000000&|;+0#af5f00255&| +0#0000000&|t+0#af5f00255&|h|e|n| +0#0000000&|e+0#af5f00255&|c|h|o| +0#e000002&|$+0#e000e06&|*|;+0#af5f00255&| +0#0000000&|f+0#af5f00255&|i|;| +0#0000000&|f|\+0#e000e06&|=|f+0#0000000&|\+0#e000e06&|=| +0#0000000&|$+0#e000e06&|*| +0#0000000&@31
+|2+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@3|}+0#e000e06&|;+0#af5f00255&| +0#0000000&|f|\+0#e000e06&|=|f+0#0000000&| |$+0#e000e06&|*| +0#0000000&@58
+||+0#0000e05#a8a8a8255| |)+0#af5f00255#ffffff0|;+0#0000000&| |f+0#00e0e07&|=+0#0000000&| |f|\|=+0#af5f00255&| +0#0000000&|f+0#00e0e07&|=+0#0000000&| |f+0#00e0e07&|=+0#0000000&| @57
+@57|7|3|,|0|-|1| @7|8|7|%|
diff --git a/runtime/syntax/testdir/dumps/sh_functions_bash_05.dump b/runtime/syntax/testdir/dumps/sh_functions_bash_05.dump
new file mode 100644
index 000000000..9b805c189
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/sh_functions_bash_05.dump
@@ -0,0 +1,20 @@
+||+0#0000e05#a8a8a8255| |)+0#af5f00255#ffffff0|;+0#0000000&| |f+0#00e0e07&|=+0#0000000&| |f|\|=+0#af5f00255&| +0#0000000&|f+0#00e0e07&|=+0#0000000&| |f+0#00e0e07&|=+0#0000000&| @57
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@72
+| +0#0000e05#a8a8a8255@1|#+0&#ffffff0| |P|a|r|e|n|s| |a|r|e| |n|o|t| |e|s|c|a|p|e|d|,| |h|e|n|c|e| |t|h|i|s| |i|s| |i|n|v|a|l|i|d| |v|a|r|i|a|b|l|e| |a|s@1|i|g|n|m|e|n|t|.| +0#0000000&@4
+| +0#0000e05#a8a8a8255@1|f+0#ffffff16#ff404010|=|f|(|)| +0#0000000#ffffff0@67
+| +0#0000e05#a8a8a8255@1|{+0#e000e06#ffffff0| +0#0000000&@71
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3>f+0#ffffff16#ff404010|=|f|=|(|)| +0#0000000#ffffff0@62
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|(+0#af5f00255&| +0#0000000&@67
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@7|f+0#ffffff16#ff404010|=|f|=|f|(|)| +0#0000000#ffffff0@57
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@7|i+0#af5f00255&|f| |:+0#0000000&|;+0#af5f00255&| +0#0000000&|t+0#af5f00255&|h|e|n| +0#0000000&|:|;+0#af5f00255&| +0#0000000&|f+0#af5f00255&|i| +0#0000000&@48
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@3|)+0#af5f00255&| +0#0000000&@67
+| +0#0000e05#a8a8a8255@1|}+0#e000e06#ffffff0| +0#0000000&@71
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|9|1|,|5| @9|B|o|t|
diff --git a/runtime/syntax/testdir/input/sh_functions_bash.sh b/runtime/syntax/testdir/input/sh_functions_bash.sh
index 161f14f97..714d2a74b 100644
--- a/runtime/syntax/testdir/input/sh_functions_bash.sh
+++ b/runtime/syntax/testdir/input/sh_functions_bash.sh
@@ -47,9 +47,50 @@ if :; then
}
@伪! "$1"
)
- eval !?\# "$1"
+ eval !?\# "\"$1\""
fi
namespace ()
{ echo $#;
}; namespace $@
+
+# Whether "=" belongs to a name or delimits a name depends on whether
+# the reserved word "function" is present, if so, then "=" is part of
+# the function name; else, "=" delimits the name of a variable when this
+# name is given in alphanumeric characters and "_"s before the leftmost
+# "="; otherwise, "=" is part of the function name when this name has
+# one or more supported NON-alphanumeric (or "_") characters before "=".
+xs=()
+(
+ echo $(( 1 + ${#xs[*]} ))
+ xs=()
+ {
+ echo $(( 2 + ${#xs[*]} ))
+ xs=()
+ if :; then echo $(( 3 + ${#xs[*]} )); fi
+ }
+)
+
+i未=() (
+ =id=() {
+ ===()
+ if :; then echo $*; fi; === $*
+ }; =id= $*
+); id= i未= i未= i未=
+
+function f=() (
+ function f=f {
+ function f=f=
+ if :; then echo $*; fi; f\=f\= $*
+ }; f\=f $*
+); f= f\= f= f=
+
+# Parens are not escaped, hence this is invalid variable assignment.
+f=f()
+{
+ f=f=()
+ (
+ f=f=f()
+ if :; then :; fi
+ )
+}