aboutsummaryrefslogtreecommitdiffstats
path: root/shell_cmds/sh/tests/parser
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-09 14:20:58 -0400
commit5fd83771641d15c418f747bd343ba6738d3875f7 (patch)
tree5abf0f78f680d9837dbd93d4d4c3933bb7509599 /shell_cmds/sh/tests/parser
downloadapple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.gz
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.zst
apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.zip
Import macOS userland
adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106
Diffstat (limited to 'shell_cmds/sh/tests/parser')
-rw-r--r--shell_cmds/sh/tests/parser/Makefile88
-rw-r--r--shell_cmds/sh/tests/parser/Makefile.depend11
-rw-r--r--shell_cmds/sh/tests/parser/alias1.05
-rw-r--r--shell_cmds/sh/tests/parser/alias10.09
-rw-r--r--shell_cmds/sh/tests/parser/alias11.06
-rw-r--r--shell_cmds/sh/tests/parser/alias12.06
-rw-r--r--shell_cmds/sh/tests/parser/alias13.06
-rw-r--r--shell_cmds/sh/tests/parser/alias14.06
-rw-r--r--shell_cmds/sh/tests/parser/alias15.012
-rw-r--r--shell_cmds/sh/tests/parser/alias15.0.stdout4
-rw-r--r--shell_cmds/sh/tests/parser/alias16.07
-rw-r--r--shell_cmds/sh/tests/parser/alias17.07
-rw-r--r--shell_cmds/sh/tests/parser/alias18.08
-rw-r--r--shell_cmds/sh/tests/parser/alias2.06
-rw-r--r--shell_cmds/sh/tests/parser/alias3.06
-rw-r--r--shell_cmds/sh/tests/parser/alias4.05
-rw-r--r--shell_cmds/sh/tests/parser/alias5.05
-rw-r--r--shell_cmds/sh/tests/parser/alias6.06
-rw-r--r--shell_cmds/sh/tests/parser/alias7.04
-rw-r--r--shell_cmds/sh/tests/parser/alias8.04
-rw-r--r--shell_cmds/sh/tests/parser/alias9.06
-rw-r--r--shell_cmds/sh/tests/parser/and-pipe-not.02
-rw-r--r--shell_cmds/sh/tests/parser/case1.014
-rw-r--r--shell_cmds/sh/tests/parser/case2.032
-rw-r--r--shell_cmds/sh/tests/parser/comment1.03
-rw-r--r--shell_cmds/sh/tests/parser/comment2.424
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote1.012
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote10.010
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote11.08
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote12.07
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote13.08
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote2.05
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote3.022
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote4.019
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote5.012
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote6.05
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote7.06
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote8.011
-rw-r--r--shell_cmds/sh/tests/parser/dollar-quote9.08
-rw-r--r--shell_cmds/sh/tests/parser/empty-braces1.07
-rw-r--r--shell_cmds/sh/tests/parser/empty-cmd1.03
-rw-r--r--shell_cmds/sh/tests/parser/for1.029
-rw-r--r--shell_cmds/sh/tests/parser/for2.015
-rw-r--r--shell_cmds/sh/tests/parser/func1.025
-rw-r--r--shell_cmds/sh/tests/parser/func2.06
-rw-r--r--shell_cmds/sh/tests/parser/func3.06
-rw-r--r--shell_cmds/sh/tests/parser/heredoc1.085
-rw-r--r--shell_cmds/sh/tests/parser/heredoc10.049
-rw-r--r--shell_cmds/sh/tests/parser/heredoc11.026
-rw-r--r--shell_cmds/sh/tests/parser/heredoc12.047
-rw-r--r--shell_cmds/sh/tests/parser/heredoc13.021
-rw-r--r--shell_cmds/sh/tests/parser/heredoc2.039
-rw-r--r--shell_cmds/sh/tests/parser/heredoc3.07
-rw-r--r--shell_cmds/sh/tests/parser/heredoc4.044
-rw-r--r--shell_cmds/sh/tests/parser/heredoc5.056
-rw-r--r--shell_cmds/sh/tests/parser/heredoc6.05
-rw-r--r--shell_cmds/sh/tests/parser/heredoc7.019
-rw-r--r--shell_cmds/sh/tests/parser/heredoc8.020
-rw-r--r--shell_cmds/sh/tests/parser/heredoc9.058
-rw-r--r--shell_cmds/sh/tests/parser/line-cont1.016
-rw-r--r--shell_cmds/sh/tests/parser/line-cont10.018
-rw-r--r--shell_cmds/sh/tests/parser/line-cont11.023
-rw-r--r--shell_cmds/sh/tests/parser/line-cont2.04
-rw-r--r--shell_cmds/sh/tests/parser/line-cont3.07
-rw-r--r--shell_cmds/sh/tests/parser/line-cont4.08
-rw-r--r--shell_cmds/sh/tests/parser/line-cont5.014
-rw-r--r--shell_cmds/sh/tests/parser/line-cont6.023
-rw-r--r--shell_cmds/sh/tests/parser/line-cont7.07
-rw-r--r--shell_cmds/sh/tests/parser/line-cont8.06
-rw-r--r--shell_cmds/sh/tests/parser/line-cont9.06
-rw-r--r--shell_cmds/sh/tests/parser/no-space1.018
-rw-r--r--shell_cmds/sh/tests/parser/no-space2.07
-rw-r--r--shell_cmds/sh/tests/parser/nul1.012
-rw-r--r--shell_cmds/sh/tests/parser/only-redir1.03
-rw-r--r--shell_cmds/sh/tests/parser/only-redir2.02
-rw-r--r--shell_cmds/sh/tests/parser/only-redir3.02
-rw-r--r--shell_cmds/sh/tests/parser/only-redir4.02
-rw-r--r--shell_cmds/sh/tests/parser/pipe-not1.03
-rw-r--r--shell_cmds/sh/tests/parser/set-v1.08
-rw-r--r--shell_cmds/sh/tests/parser/set-v1.0.stderr5
-rw-r--r--shell_cmds/sh/tests/parser/var-assign1.019
81 files changed, 1185 insertions, 0 deletions
diff --git a/shell_cmds/sh/tests/parser/Makefile b/shell_cmds/sh/tests/parser/Makefile
new file mode 100644
index 0000000..cd83a50
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/Makefile
@@ -0,0 +1,88 @@
+# $FreeBSD: head/bin/sh/tests/parser/Makefile 317039 2017-04-16 22:10:02Z jilles $
+
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/bin/sh/${.CURDIR:T}
+
+.PATH: ${.CURDIR:H}
+ATF_TESTS_SH= functional_test
+
+${PACKAGE}FILES+= alias1.0
+${PACKAGE}FILES+= alias2.0
+${PACKAGE}FILES+= alias3.0
+${PACKAGE}FILES+= alias4.0
+${PACKAGE}FILES+= alias5.0
+${PACKAGE}FILES+= alias6.0
+${PACKAGE}FILES+= alias7.0
+${PACKAGE}FILES+= alias8.0
+${PACKAGE}FILES+= alias9.0
+${PACKAGE}FILES+= alias10.0
+${PACKAGE}FILES+= alias11.0
+${PACKAGE}FILES+= alias12.0
+${PACKAGE}FILES+= alias13.0
+${PACKAGE}FILES+= alias14.0
+${PACKAGE}FILES+= alias15.0 alias15.0.stdout
+${PACKAGE}FILES+= alias16.0
+${PACKAGE}FILES+= alias17.0
+${PACKAGE}FILES+= alias18.0
+${PACKAGE}FILES+= and-pipe-not.0
+${PACKAGE}FILES+= case1.0
+${PACKAGE}FILES+= case2.0
+${PACKAGE}FILES+= comment1.0
+${PACKAGE}FILES+= comment2.42
+${PACKAGE}FILES+= dollar-quote1.0
+${PACKAGE}FILES+= dollar-quote2.0
+${PACKAGE}FILES+= dollar-quote3.0
+${PACKAGE}FILES+= dollar-quote4.0
+${PACKAGE}FILES+= dollar-quote5.0
+${PACKAGE}FILES+= dollar-quote6.0
+${PACKAGE}FILES+= dollar-quote7.0
+${PACKAGE}FILES+= dollar-quote8.0
+${PACKAGE}FILES+= dollar-quote9.0
+${PACKAGE}FILES+= dollar-quote10.0
+${PACKAGE}FILES+= dollar-quote11.0
+${PACKAGE}FILES+= dollar-quote12.0
+${PACKAGE}FILES+= dollar-quote13.0
+${PACKAGE}FILES+= empty-braces1.0
+${PACKAGE}FILES+= empty-cmd1.0
+${PACKAGE}FILES+= for1.0
+${PACKAGE}FILES+= for2.0
+${PACKAGE}FILES+= func1.0
+${PACKAGE}FILES+= func2.0
+${PACKAGE}FILES+= func3.0
+${PACKAGE}FILES+= heredoc1.0
+${PACKAGE}FILES+= heredoc2.0
+${PACKAGE}FILES+= heredoc3.0
+${PACKAGE}FILES+= heredoc4.0
+${PACKAGE}FILES+= heredoc5.0
+${PACKAGE}FILES+= heredoc6.0
+${PACKAGE}FILES+= heredoc7.0
+${PACKAGE}FILES+= heredoc8.0
+${PACKAGE}FILES+= heredoc9.0
+${PACKAGE}FILES+= heredoc10.0
+${PACKAGE}FILES+= heredoc11.0
+${PACKAGE}FILES+= heredoc12.0
+${PACKAGE}FILES+= heredoc13.0
+${PACKAGE}FILES+= line-cont1.0
+${PACKAGE}FILES+= line-cont2.0
+${PACKAGE}FILES+= line-cont3.0
+${PACKAGE}FILES+= line-cont4.0
+${PACKAGE}FILES+= line-cont5.0
+${PACKAGE}FILES+= line-cont6.0
+${PACKAGE}FILES+= line-cont7.0
+${PACKAGE}FILES+= line-cont8.0
+${PACKAGE}FILES+= line-cont9.0
+${PACKAGE}FILES+= line-cont10.0
+${PACKAGE}FILES+= line-cont11.0
+${PACKAGE}FILES+= no-space1.0
+${PACKAGE}FILES+= no-space2.0
+${PACKAGE}FILES+= nul1.0
+${PACKAGE}FILES+= only-redir1.0
+${PACKAGE}FILES+= only-redir2.0
+${PACKAGE}FILES+= only-redir3.0
+${PACKAGE}FILES+= only-redir4.0
+${PACKAGE}FILES+= pipe-not1.0
+${PACKAGE}FILES+= set-v1.0 set-v1.0.stderr
+${PACKAGE}FILES+= var-assign1.0
+
+.include <bsd.test.mk>
diff --git a/shell_cmds/sh/tests/parser/Makefile.depend b/shell_cmds/sh/tests/parser/Makefile.depend
new file mode 100644
index 0000000..af589a4
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD: head/bin/sh/tests/parser/Makefile.depend 296587 2016-03-09 22:46:01Z bdrewery $
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/shell_cmds/sh/tests/parser/alias1.0 b/shell_cmds/sh/tests/parser/alias1.0
new file mode 100644
index 0000000..9b67211
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias1.0
@@ -0,0 +1,5 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias1.0 214280 2010-10-24 16:55:17Z jilles $
+
+alias alias0=exit
+eval 'alias0 0'
+exit 1
diff --git a/shell_cmds/sh/tests/parser/alias10.0 b/shell_cmds/sh/tests/parser/alias10.0
new file mode 100644
index 0000000..b8684f4
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias10.0
@@ -0,0 +1,9 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias10.0 243252 2012-11-18 23:15:22Z jilles $
+
+# This test may start consuming memory indefinitely if it fails.
+ulimit -t 5 2>/dev/null
+ulimit -v 100000 2>/dev/null
+
+alias echo='echo'
+alias echo='echo'
+[ "`eval echo b`" = b ]
diff --git a/shell_cmds/sh/tests/parser/alias11.0 b/shell_cmds/sh/tests/parser/alias11.0
new file mode 100644
index 0000000..10fd827
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias11.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias11.0 261141 2014-01-24 23:00:35Z jilles $
+
+alias alias0=alias1
+alias alias1=exit
+eval 'alias0 0'
+exit 3
diff --git a/shell_cmds/sh/tests/parser/alias12.0 b/shell_cmds/sh/tests/parser/alias12.0
new file mode 100644
index 0000000..52cc4b0
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias12.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias12.0 261160 2014-01-25 14:59:08Z jilles $
+
+unalias -a
+alias alias0=command
+alias true='echo bad'
+eval 'alias0 true'
diff --git a/shell_cmds/sh/tests/parser/alias13.0 b/shell_cmds/sh/tests/parser/alias13.0
new file mode 100644
index 0000000..9f45067
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias13.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias13.0 261160 2014-01-25 14:59:08Z jilles $
+
+unalias -a
+alias command=command
+alias true='echo bad'
+eval 'command true'
diff --git a/shell_cmds/sh/tests/parser/alias14.0 b/shell_cmds/sh/tests/parser/alias14.0
new file mode 100644
index 0000000..2d1bc51
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias14.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias14.0 261192 2014-01-26 21:19:33Z jilles $
+
+alias command='command '
+alias alias0=exit
+eval 'command alias0 0'
+exit 3
diff --git a/shell_cmds/sh/tests/parser/alias15.0 b/shell_cmds/sh/tests/parser/alias15.0
new file mode 100644
index 0000000..c2e6117
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias15.0
@@ -0,0 +1,12 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias15.0 261192 2014-01-26 21:19:33Z jilles $
+
+f_echoanddo() {
+ printf '%s\n' "$*"
+ "$@"
+}
+
+alias echoanddo='f_echoanddo '
+alias alias0='echo test2'
+eval 'echoanddo echo test1'
+eval 'echoanddo alias0'
+exit 0
diff --git a/shell_cmds/sh/tests/parser/alias15.0.stdout b/shell_cmds/sh/tests/parser/alias15.0.stdout
new file mode 100644
index 0000000..6dd179c
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias15.0.stdout
@@ -0,0 +1,4 @@
+echo test1
+test1
+echo test2
+test2
diff --git a/shell_cmds/sh/tests/parser/alias16.0 b/shell_cmds/sh/tests/parser/alias16.0
new file mode 100644
index 0000000..b551216
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias16.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias16.0 316646 2017-04-08 21:57:59Z jilles $
+
+v=1
+alias a='unalias a
+v=2'
+eval a
+[ "$v" = 2 ]
diff --git a/shell_cmds/sh/tests/parser/alias17.0 b/shell_cmds/sh/tests/parser/alias17.0
new file mode 100644
index 0000000..fd233ef
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias17.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias17.0 317037 2017-04-16 21:42:43Z jilles $
+
+v=1
+alias a='unalias -a
+v=2'
+eval a
+[ "$v" = 2 ]
diff --git a/shell_cmds/sh/tests/parser/alias18.0 b/shell_cmds/sh/tests/parser/alias18.0
new file mode 100644
index 0000000..4b072e8
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias18.0
@@ -0,0 +1,8 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias18.0 317039 2017-04-16 22:10:02Z jilles $
+
+v=1
+alias a='alias a=v=2
+v=3
+a'
+eval a
+[ "$v" = 2 ]
diff --git a/shell_cmds/sh/tests/parser/alias2.0 b/shell_cmds/sh/tests/parser/alias2.0
new file mode 100644
index 0000000..f412756
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias2.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias2.0 214280 2010-10-24 16:55:17Z jilles $
+
+alias alias0=exit
+x=alias0
+eval 'case $x in alias0) exit 0;; esac'
+exit 1
diff --git a/shell_cmds/sh/tests/parser/alias3.0 b/shell_cmds/sh/tests/parser/alias3.0
new file mode 100644
index 0000000..97aac19
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias3.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias3.0 214709 2010-11-02 23:44:29Z jilles $
+
+alias alias0=exit
+x=alias0
+eval 'case $x in "alias0") alias0 0;; esac'
+exit 1
diff --git a/shell_cmds/sh/tests/parser/alias4.0 b/shell_cmds/sh/tests/parser/alias4.0
new file mode 100644
index 0000000..4c82c6c
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias4.0
@@ -0,0 +1,5 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias4.0 222165 2011-05-21 22:03:06Z jilles $
+
+alias alias0=exit
+eval 'x=1 alias0 0'
+exit 1
diff --git a/shell_cmds/sh/tests/parser/alias5.0 b/shell_cmds/sh/tests/parser/alias5.0
new file mode 100644
index 0000000..c649562
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias5.0
@@ -0,0 +1,5 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias5.0 222165 2011-05-21 22:03:06Z jilles $
+
+alias alias0=exit
+eval '</dev/null alias0 0'
+exit 1
diff --git a/shell_cmds/sh/tests/parser/alias6.0 b/shell_cmds/sh/tests/parser/alias6.0
new file mode 100644
index 0000000..86e1bfb
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias6.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias6.0 224104 2011-07-16 16:14:14Z jilles $
+
+alias alias0='| cat >/dev/null'
+
+eval '{ echo bad; } alias0'
+eval '(echo bad)alias0'
diff --git a/shell_cmds/sh/tests/parser/alias7.0 b/shell_cmds/sh/tests/parser/alias7.0
new file mode 100644
index 0000000..a5b9077
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias7.0
@@ -0,0 +1,4 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias7.0 240825 2012-09-22 12:52:41Z jilles $
+
+alias echo='echo a'
+[ "`eval echo b`" = "a b" ]
diff --git a/shell_cmds/sh/tests/parser/alias8.0 b/shell_cmds/sh/tests/parser/alias8.0
new file mode 100644
index 0000000..f22dfd4
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias8.0
@@ -0,0 +1,4 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias8.0 240825 2012-09-22 12:52:41Z jilles $
+
+alias echo='echo'
+[ "`eval echo b`" = b ]
diff --git a/shell_cmds/sh/tests/parser/alias9.0 b/shell_cmds/sh/tests/parser/alias9.0
new file mode 100644
index 0000000..bbcb4ce
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/alias9.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/alias9.0 242721 2012-11-07 23:15:36Z jilles $
+
+alias alias0=:
+alias alias0=exit
+eval 'alias0 0'
+exit 1
diff --git a/shell_cmds/sh/tests/parser/and-pipe-not.0 b/shell_cmds/sh/tests/parser/and-pipe-not.0
new file mode 100644
index 0000000..fffb1d4
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/and-pipe-not.0
@@ -0,0 +1,2 @@
+# $FreeBSD: head/bin/sh/tests/parser/and-pipe-not.0 191010 2009-04-13 19:12:28Z stefanf $
+true && ! true | false
diff --git a/shell_cmds/sh/tests/parser/case1.0 b/shell_cmds/sh/tests/parser/case1.0
new file mode 100644
index 0000000..d146399
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/case1.0
@@ -0,0 +1,14 @@
+# $FreeBSD: head/bin/sh/tests/parser/case1.0 207824 2010-05-09 17:10:50Z jilles $
+
+keywords='if then else elif fi while until for do done { } case esac ! in'
+
+# Keywords can be used unquoted in case statements, except the keyword
+# esac as the first pattern of a '|' alternation without a starting '('.
+# (POSIX doesn't seem to require (esac) to work.)
+for k in $keywords; do
+ eval "case $k in (foo|$k) ;; *) echo bad ;; esac"
+ eval "case $k in ($k) ;; *) echo bad ;; esac"
+ eval "case $k in foo|$k) ;; *) echo bad ;; esac"
+ [ "$k" = esac ] && continue
+ eval "case $k in $k) ;; *) echo bad ;; esac"
+done
diff --git a/shell_cmds/sh/tests/parser/case2.0 b/shell_cmds/sh/tests/parser/case2.0
new file mode 100644
index 0000000..df5a319
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/case2.0
@@ -0,0 +1,32 @@
+# $FreeBSD: head/bin/sh/tests/parser/case2.0 207824 2010-05-09 17:10:50Z jilles $
+
+# Pretty much only ash derivatives can parse all of this.
+
+f1() {
+ x=$(case x in
+ (x|esac) ;;
+ (*) echo bad >&2 ;;
+ esac)
+}
+f1
+f2() {
+ x=$(case x in
+ (x|esac) ;;
+ (*) echo bad >&2
+ esac)
+}
+f2
+f3() {
+ x=$(case x in
+ x|esac) ;;
+ *) echo bad >&2 ;;
+ esac)
+}
+f3
+f4() {
+ x=$(case x in
+ x|esac) ;;
+ *) echo bad >&2
+ esac)
+}
+f4
diff --git a/shell_cmds/sh/tests/parser/comment1.0 b/shell_cmds/sh/tests/parser/comment1.0
new file mode 100644
index 0000000..bdf9c3b
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/comment1.0
@@ -0,0 +1,3 @@
+# $FreeBSD: head/bin/sh/tests/parser/comment1.0 295818 2016-02-19 16:56:07Z jilles $
+
+${SH} -c '#'
diff --git a/shell_cmds/sh/tests/parser/comment2.42 b/shell_cmds/sh/tests/parser/comment2.42
new file mode 100644
index 0000000..7e623c9
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/comment2.42
@@ -0,0 +1,4 @@
+# $FreeBSD: head/bin/sh/tests/parser/comment2.42 295818 2016-02-19 16:56:07Z jilles $
+
+${SH} -c '#
+exit 42'
diff --git a/shell_cmds/sh/tests/parser/dollar-quote1.0 b/shell_cmds/sh/tests/parser/dollar-quote1.0
new file mode 100644
index 0000000..1206141
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote1.0
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+set -e
+
+[ $'hi' = hi ]
+[ $'hi
+there' = 'hi
+there' ]
+[ $'\"\'\\\a\b\f\t\v' = "\"'\\$(printf "\a\b\f\t\v")" ]
+[ $'hi\nthere' = 'hi
+there' ]
+[ $'a\rb' = "$(printf "a\rb")" ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote10.0 b/shell_cmds/sh/tests/parser/dollar-quote10.0
new file mode 100644
index 0000000..745d3aa
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote10.0
@@ -0,0 +1,10 @@
+# $FreeBSD: head/bin/sh/tests/parser/dollar-quote10.0 221669 2011-05-08 17:40:10Z jilles $
+
+# a umlaut
+s=$(printf '\303\244')
+# euro sign
+s=$s$(printf '\342\202\254')
+
+# Start a new shell so the locale change is picked up.
+ss="$(LC_ALL=en_US.UTF-8 ${SH} -c "printf %s \$'\u00e4\u20ac'")"
+[ "$s" = "$ss" ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote11.0 b/shell_cmds/sh/tests/parser/dollar-quote11.0
new file mode 100644
index 0000000..b9db067
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote11.0
@@ -0,0 +1,8 @@
+# $FreeBSD: head/bin/sh/tests/parser/dollar-quote11.0 221669 2011-05-08 17:40:10Z jilles $
+
+# some sort of 't' outside BMP
+s=$s$(printf '\360\235\225\245')
+
+# Start a new shell so the locale change is picked up.
+ss="$(LC_ALL=en_US.UTF-8 ${SH} -c "printf %s \$'\U0001d565'")"
+[ "$s" = "$ss" ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote12.0 b/shell_cmds/sh/tests/parser/dollar-quote12.0
new file mode 100644
index 0000000..bb06e3c
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote12.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/dollar-quote12.0 286971 2015-08-20 21:31:36Z jilles $
+
+# \u without any digits at all remains invalid.
+# Our choice is a parse error.
+
+v=$( (eval ": \$'\u'") 2>&1 >/dev/null)
+[ $? -ne 0 ] && [ -n "$v" ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote13.0 b/shell_cmds/sh/tests/parser/dollar-quote13.0
new file mode 100644
index 0000000..fe31d9d
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote13.0
@@ -0,0 +1,8 @@
+# $FreeBSD: head/bin/sh/tests/parser/dollar-quote13.0 286973 2015-08-20 22:05:55Z jilles $
+
+# This Unicode escape sequence that has never been in range should either
+# fail to expand or expand to a fallback.
+
+c=$(eval printf %s \$\'\\Uffffff41\' 2>/dev/null)
+r=$(($? != 0))
+[ "$r.$c" = '1.' ] || [ "$r.$c" = '0.?' ] || [ "$r.$c" = $'0.\u2222' ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote2.0 b/shell_cmds/sh/tests/parser/dollar-quote2.0
new file mode 100644
index 0000000..4617ed8
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote2.0
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+# This depends on the ASCII character set.
+
+[ $'\e' = "$(printf "\033")" ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote3.0 b/shell_cmds/sh/tests/parser/dollar-quote3.0
new file mode 100644
index 0000000..a7e6852
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote3.0
@@ -0,0 +1,22 @@
+# $FreeBSD$
+
+unset LC_ALL
+LC_CTYPE=en_US.ISO8859-1
+export LC_CTYPE
+
+e=
+for i in 0 1 2 3; do
+ for j in 0 1 2 3 4 5 6 7; do
+ for k in 0 1 2 3 4 5 6 7; do
+ case $i$j$k in
+ 000) continue ;;
+ esac
+ e="$e\\$i$j$k"
+ done
+ done
+done
+ee=`printf "$e"`
+[ "${#ee}" = 255 ] || echo length bad
+
+# Start a new shell so the locale change is picked up.
+[ "$(${SH} -c "printf %s \$'$e'")" = "$ee" ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote4.0 b/shell_cmds/sh/tests/parser/dollar-quote4.0
new file mode 100644
index 0000000..f620af5
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote4.0
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+unset LC_ALL
+LC_CTYPE=en_US.ISO8859-1
+export LC_CTYPE
+
+e=
+for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+ for j in 0 1 2 3 4 5 6 7 8 9 a b c d e f; do
+ case $i$j in
+ 00) continue ;;
+ esac
+ e="$e\x$i$j"
+ done
+done
+
+# Start a new shell so the locale change is picked up.
+ee="$(${SH} -c "printf %s \$'$e'")"
+[ "${#ee}" = 255 ] || echo length bad
diff --git a/shell_cmds/sh/tests/parser/dollar-quote5.0 b/shell_cmds/sh/tests/parser/dollar-quote5.0
new file mode 100644
index 0000000..c2c44ca
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote5.0
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+# This depends on the ASCII character set.
+
+set -e
+
+[ $'\ca\cb\cc\cd\ce\cf\cg\ch\ci\cj\ck\cl\cm\cn\co\cp\cq\cr\cs\ct\cu\cv\cw\cx\cy\cz' = $'\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032' ]
+[ $'\cA\cB\cC\cD\cE\cF\cG\cH\cI\cJ\cK\cL\cM\cN\cO\cP\cQ\cR\cS\cT\cU\cV\cW\cX\cY\cZ' = $'\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032' ]
+[ $'\c[' = $'\033' ]
+[ $'\c]' = $'\035' ]
+[ $'\c^' = $'\036' ]
+[ $'\c_' = $'\037' ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote6.0 b/shell_cmds/sh/tests/parser/dollar-quote6.0
new file mode 100644
index 0000000..a4b1e3f
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote6.0
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+# This depends on the ASCII character set.
+
+[ $'\c\\' = $'\034' ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote7.0 b/shell_cmds/sh/tests/parser/dollar-quote7.0
new file mode 100644
index 0000000..c866b1a
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote7.0
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+set -e
+
+[ $'\u0024\u0040\u0060' = '$@`' ]
+[ $'\U00000024\U00000040\U00000060' = '$@`' ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote8.0 b/shell_cmds/sh/tests/parser/dollar-quote8.0
new file mode 100644
index 0000000..8f0b41a
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote8.0
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+[ $'hello\0' = hello ]
+[ $'hello\0world' = hello ]
+[ $'hello\0'$'world' = helloworld ]
+[ $'hello\000' = hello ]
+[ $'hello\000world' = hello ]
+[ $'hello\000'$'world' = helloworld ]
+[ $'hello\x00' = hello ]
+[ $'hello\x00world' = hello ]
+[ $'hello\x00'$'world' = helloworld ]
diff --git a/shell_cmds/sh/tests/parser/dollar-quote9.0 b/shell_cmds/sh/tests/parser/dollar-quote9.0
new file mode 100644
index 0000000..df64b7d
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/dollar-quote9.0
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+# POSIX and C99 say D800-DFFF are undefined in a universal character name.
+# We reject this but many other shells expand to something that looks like
+# CESU-8.
+
+v=$( (eval ": \$'\uD800'") 2>&1 >/dev/null)
+[ $? -ne 0 ] && [ -n "$v" ]
diff --git a/shell_cmds/sh/tests/parser/empty-braces1.0 b/shell_cmds/sh/tests/parser/empty-braces1.0
new file mode 100644
index 0000000..4aac806
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/empty-braces1.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/empty-braces1.0 245382 2013-01-13 19:26:33Z jilles $
+
+# Unfortunately, some scripts depend on the extension of allowing an empty
+# pair of braces.
+
+{ } &
+wait $!
diff --git a/shell_cmds/sh/tests/parser/empty-cmd1.0 b/shell_cmds/sh/tests/parser/empty-cmd1.0
new file mode 100644
index 0000000..60aaa00
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/empty-cmd1.0
@@ -0,0 +1,3 @@
+# $FreeBSD: head/bin/sh/tests/parser/empty-cmd1.0 254843 2013-08-25 10:57:48Z jilles $
+
+! (eval ': || f()') 2>/dev/null
diff --git a/shell_cmds/sh/tests/parser/for1.0 b/shell_cmds/sh/tests/parser/for1.0
new file mode 100644
index 0000000..d863f0a
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/for1.0
@@ -0,0 +1,29 @@
+# $FreeBSD: head/bin/sh/tests/parser/for1.0 218889 2011-02-20 14:18:58Z jilles $
+
+nl='
+'
+list=' a b c'
+for s1 in "$nl" " "; do
+ for s2 in "$nl" ";" ";$nl"; do
+ for s3 in "$nl" " "; do
+ r=''
+ eval "for i${s1}in ${list}${s2}do${s3}r=\"\$r \$i\"; done"
+ [ "$r" = "$list" ] || exit 1
+ done
+ done
+done
+set -- $list
+for s2 in "$nl" " "; do
+ for s3 in "$nl" " "; do
+ r=''
+ eval "for i${s2}do${s3}r=\"\$r \$i\"; done"
+ [ "$r" = "$list" ] || exit 1
+ done
+done
+for s1 in "$nl" " "; do
+ for s2 in "$nl" ";" ";$nl"; do
+ for s3 in "$nl" " "; do
+ eval "for i${s1}in${s2}do${s3}exit 1; done"
+ done
+ done
+done
diff --git a/shell_cmds/sh/tests/parser/for2.0 b/shell_cmds/sh/tests/parser/for2.0
new file mode 100644
index 0000000..8ed92dc
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/for2.0
@@ -0,0 +1,15 @@
+# $FreeBSD: head/bin/sh/tests/parser/for2.0 218889 2011-02-20 14:18:58Z jilles $
+
+# Common extensions to the 'for' syntax.
+
+nl='
+'
+list=' a b c'
+set -- $list
+for s2 in ";" ";$nl"; do
+ for s3 in "$nl" " "; do
+ r=''
+ eval "for i${s2}do${s3}r=\"\$r \$i\"; done"
+ [ "$r" = "$list" ] || exit 1
+ done
+done
diff --git a/shell_cmds/sh/tests/parser/func1.0 b/shell_cmds/sh/tests/parser/func1.0
new file mode 100644
index 0000000..4e82da4
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/func1.0
@@ -0,0 +1,25 @@
+# $FreeBSD: head/bin/sh/tests/parser/func1.0 214291 2010-10-24 20:45:13Z jilles $
+# POSIX does not require these bytes to work in function names,
+# but making them all work seems a good goal.
+
+failures=0
+unset LC_ALL
+export LC_CTYPE=en_US.ISO8859-1
+i=128
+set -f
+while [ "$i" -le 255 ]; do
+ c=$(printf \\"$(printf %o "$i")")
+ ok=0
+ eval "$c() { ok=1; }"
+ $c
+ ok1=$ok
+ ok=0
+ "$c"
+ if [ "$ok" != 1 ] || [ "$ok1" != 1 ]; then
+ echo "Bad results for character $i" >&2
+ : $((failures += 1))
+ fi
+ unset -f $c
+ i=$((i+1))
+done
+exit $((failures > 0))
diff --git a/shell_cmds/sh/tests/parser/func2.0 b/shell_cmds/sh/tests/parser/func2.0
new file mode 100644
index 0000000..5b86522
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/func2.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/func2.0 222512 2011-05-30 21:49:59Z jilles $
+
+f() { return 42; }
+f() { return 3; } &
+f
+[ $? -eq 42 ]
diff --git a/shell_cmds/sh/tests/parser/func3.0 b/shell_cmds/sh/tests/parser/func3.0
new file mode 100644
index 0000000..c4f4922
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/func3.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/func3.0 222512 2011-05-30 21:49:59Z jilles $
+
+name=/var/empty/nosuch
+f() { true; } <$name
+name=/dev/null
+f
diff --git a/shell_cmds/sh/tests/parser/heredoc1.0 b/shell_cmds/sh/tests/parser/heredoc1.0
new file mode 100644
index 0000000..4020249
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc1.0
@@ -0,0 +1,85 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc1.0 204836 2010-03-07 15:08:42Z jilles $
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+check '"$(cat <<EOF
+hi
+EOF
+)" = hi'
+
+check '"$(cat <<EOF
+${$+hi}
+EOF
+)" = hi'
+
+unset yy
+check '"$(cat <<EOF
+${yy-hi}
+EOF
+)" = hi'
+
+check '"$(cat <<EOF
+${$+hi
+there}
+EOF
+)" = "hi
+there"'
+
+check '"$(cat <<EOF
+$((1+1))
+EOF
+)" = 2'
+
+check '"$(cat <<EOF
+$(echo hi)
+EOF
+)" = hi'
+
+check '"$(cat <<EOF
+`echo hi`
+EOF
+)" = hi'
+
+check '"$(cat <<\EOF
+${$+hi}
+EOF
+)" = "\${\$+hi}"'
+
+check '"$(cat <<\EOF
+$(
+EOF
+)" = \$\('
+
+check '"$(cat <<\EOF
+`
+EOF
+)" = \`'
+
+check '"$(cat <<EOF
+"
+EOF
+)" = \"'
+
+check '"$(cat <<\EOF
+"
+EOF
+)" = \"'
+
+check '"$(cat <<esac
+'"'"'
+esac
+)" = "'"'"'"'
+
+check '"$(cat <<\)
+'"'"'
+)
+)" = "'"'"'"'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/heredoc10.0 b/shell_cmds/sh/tests/parser/heredoc10.0
new file mode 100644
index 0000000..f5133b9
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc10.0
@@ -0,0 +1,49 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc10.0 221887 2011-05-14 14:19:30Z jilles $
+
+# It may be argued that
+# x=$(cat <<EOF
+# foo
+# EOF)
+# is a valid complete command that sets x to foo, because
+# cat <<EOF
+# foo
+# EOF
+# is a valid script even without the final newline.
+# However, if the here-document is not within a new-style command substitution
+# or there are other constructs nested inside the command substitution that
+# need terminators, the delimiter at the start of a line followed by a close
+# parenthesis is clearly a literal part of the here-document.
+
+# This file contains tests that may not work with simplistic $(...) parsers.
+# The open parentheses in comments help mksh, but not zsh.
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+check '"$(cat <<EOF # (
+EOF )
+EOF
+)" = "EOF )"'
+
+check '"$({ cat <<EOF # (
+EOF)
+EOF
+})" = "EOF)"'
+
+check '"$(if :; then cat <<EOF # (
+EOF)
+EOF
+fi)" = "EOF)"'
+
+check '"$( (cat <<EOF # (
+EOF)
+EOF
+))" = "EOF)"'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/heredoc11.0 b/shell_cmds/sh/tests/parser/heredoc11.0
new file mode 100644
index 0000000..3e74aea
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc11.0
@@ -0,0 +1,26 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc11.0 222134 2011-05-20 16:03:36Z jilles $
+
+failures=''
+
+check() {
+ if eval "[ $* ]"; then
+ :
+ else
+ echo "Failed: $*"
+ failures=x$failures
+ fi
+}
+
+check '`cat <<EOF
+foo
+EOF` = foo'
+
+check '"`cat <<EOF
+foo
+EOF`" = foo'
+
+check '`eval "cat <<EOF
+foo
+EOF"` = foo'
+
+test "x$failures" = x
diff --git a/shell_cmds/sh/tests/parser/heredoc12.0 b/shell_cmds/sh/tests/parser/heredoc12.0
new file mode 100644
index 0000000..644cae1
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc12.0
@@ -0,0 +1,47 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc12.0 271593 2014-09-14 16:46:30Z jilles $
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+longmark=`printf %01000d 4`
+longmarkstripped=`printf %0999d 0`
+
+check '"$(cat <<'"$longmark
+$longmark"'
+echo yes)" = "yes"'
+
+check '"$(cat <<\'"$longmark
+$longmark"'
+echo yes)" = "yes"'
+
+check '"$(cat <<'"$longmark
+yes
+$longmark"'
+)" = "yes"'
+
+check '"$(cat <<\'"$longmark
+yes
+$longmark"'
+)" = "yes"'
+
+check '"$(cat <<'"$longmark
+$longmarkstripped
+$longmark.
+$longmark"'
+)" = "'"$longmarkstripped
+$longmark."'"'
+
+check '"$(cat <<\'"$longmark
+$longmarkstripped
+$longmark.
+$longmark"'
+)" = "'"$longmarkstripped
+$longmark."'"'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/heredoc13.0 b/shell_cmds/sh/tests/parser/heredoc13.0
new file mode 100644
index 0000000..4eb45e0
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc13.0
@@ -0,0 +1,21 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc13.0 287408 2015-09-02 19:49:55Z jilles $
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+check '"$(cat <<""
+
+echo yes)" = "yes"'
+
+check '"$(cat <<""
+yes
+
+)" = "yes"'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/heredoc2.0 b/shell_cmds/sh/tests/parser/heredoc2.0
new file mode 100644
index 0000000..f07f5d4
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc2.0
@@ -0,0 +1,39 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc2.0 211405 2010-08-16 21:14:49Z jilles $
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+s='ast*que?non' sq=\' dq=\"
+
+check '"$(cat <<EOF
+${s}
+EOF
+)" = "ast*que?non"'
+
+check '"$(cat <<EOF
+${s+'$sq'x'$sq'}
+EOF
+)" = ${sq}x${sq}'
+
+check '"$(cat <<EOF
+${s#ast}
+EOF
+)" = "*que?non"'
+
+check '"$(cat <<EOF
+${s##"ast"}
+EOF
+)" = "*que?non"'
+
+check '"$(cat <<EOF
+${s##'$sq'ast'$sq'}
+EOF
+)" = "*que?non"'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/heredoc3.0 b/shell_cmds/sh/tests/parser/heredoc3.0
new file mode 100644
index 0000000..15c0a1c
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc3.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc3.0 207824 2010-05-09 17:10:50Z jilles $
+
+# This may be expected to work, but pretty much only ash derivatives allow it.
+
+test "$(cat <<EOF)" = "hi there"
+hi there
+EOF
diff --git a/shell_cmds/sh/tests/parser/heredoc4.0 b/shell_cmds/sh/tests/parser/heredoc4.0
new file mode 100644
index 0000000..a544354
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc4.0
@@ -0,0 +1,44 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc4.0 208655 2010-05-30 14:11:27Z jilles $
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+f() {
+ cat <<EOF && echo `echo bar`
+foo
+EOF
+}
+check '"`f`" = "foo
+bar"'
+
+f() {
+ cat <<EOF && echo $(echo bar)
+foo
+EOF
+}
+check '"$(f)" = "foo
+bar"'
+
+f() {
+ echo `echo bar` && cat <<EOF
+foo
+EOF
+}
+check '"`f`" = "bar
+foo"'
+
+f() {
+ echo $(echo bar) && cat <<EOF
+foo
+EOF
+}
+check '"$(f)" = "bar
+foo"'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/heredoc5.0 b/shell_cmds/sh/tests/parser/heredoc5.0
new file mode 100644
index 0000000..0bcc617
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc5.0
@@ -0,0 +1,56 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc5.0 208655 2010-05-30 14:11:27Z jilles $
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+f() {
+ cat <<EOF && echo `cat <<EOF
+bar
+EOF
+`
+foo
+EOF
+}
+check '"`f`" = "foo
+bar"'
+
+f() {
+ cat <<EOF && echo $(cat <<EOF
+bar
+EOF
+)
+foo
+EOF
+}
+check '"$(f)" = "foo
+bar"'
+
+f() {
+ echo `cat <<EOF
+bar
+EOF
+` && cat <<EOF
+foo
+EOF
+}
+check '"`f`" = "bar
+foo"'
+
+f() {
+ echo $(cat <<EOF
+bar
+EOF
+) && cat <<EOF
+foo
+EOF
+}
+check '"$(f)" = "bar
+foo"'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/heredoc6.0 b/shell_cmds/sh/tests/parser/heredoc6.0
new file mode 100644
index 0000000..003f548
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc6.0
@@ -0,0 +1,5 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc6.0 208656 2010-05-30 14:20:32Z jilles $
+
+r=
+! command eval ": <<EOF; )" 2>/dev/null; command eval : hi \${r:=0}
+exit ${r:-3}
diff --git a/shell_cmds/sh/tests/parser/heredoc7.0 b/shell_cmds/sh/tests/parser/heredoc7.0
new file mode 100644
index 0000000..28d867c
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc7.0
@@ -0,0 +1,19 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc7.0 210488 2010-07-25 22:25:52Z jilles $
+
+# Some of these created malformed parse trees with null pointers for here
+# documents, causing the here document writing process to segfault.
+eval ': <<EOF'
+eval ': <<EOF;'
+eval '`: <<EOF`'
+eval '`: <<EOF;`'
+eval '`: <<EOF`;'
+eval '`: <<EOF;`;'
+
+# Some of these created malformed parse trees with null pointers for here
+# documents, causing sh to segfault.
+eval ': <<\EOF'
+eval ': <<\EOF;'
+eval '`: <<\EOF`'
+eval '`: <<\EOF;`'
+eval '`: <<\EOF`;'
+eval '`: <<\EOF;`;'
diff --git a/shell_cmds/sh/tests/parser/heredoc8.0 b/shell_cmds/sh/tests/parser/heredoc8.0
new file mode 100644
index 0000000..482c060
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc8.0
@@ -0,0 +1,20 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc8.0 211405 2010-08-16 21:14:49Z jilles $
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+s='ast*que?non' sq=\' dq=\"
+
+# This is possibly useful but differs from other shells.
+check '"$(cat <<EOF
+${s+"x"}
+EOF
+)" = ${dq}x${dq}'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/heredoc9.0 b/shell_cmds/sh/tests/parser/heredoc9.0
new file mode 100644
index 0000000..bb4a04c
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/heredoc9.0
@@ -0,0 +1,58 @@
+# $FreeBSD: head/bin/sh/tests/parser/heredoc9.0 221887 2011-05-14 14:19:30Z jilles $
+
+# It may be argued that
+# x=$(cat <<EOF
+# foo
+# EOF)
+# is a valid complete command that sets x to foo, because
+# cat <<EOF
+# foo
+# EOF
+# is a valid script even without the final newline.
+# However, if the here-document is not within a new-style command substitution
+# or there are other constructs nested inside the command substitution that
+# need terminators, the delimiter at the start of a line followed by a close
+# parenthesis is clearly a literal part of the here-document.
+
+# This file contains tests that also work with simplistic $(...) parsers.
+
+failures=0
+
+check() {
+ if ! eval "[ $* ]"; then
+ echo "Failed: $*"
+ : $((failures += 1))
+ fi
+}
+
+check '`${SH} -c "cat <<EOF
+EOF)
+EOF
+"` = "EOF)"'
+
+check '`${SH} -c "(cat <<EOF
+EOF)
+EOF
+)"` = "EOF)"'
+
+check '"`cat <<EOF
+EOF x
+EOF
+`" = "EOF x"'
+
+check '"`cat <<EOF
+EOF )
+EOF
+`" = "EOF )"'
+
+check '"`cat <<EOF
+EOF)
+EOF
+`" = "EOF)"'
+
+check '"$(cat <<EOF
+EOF x
+EOF
+)" = "EOF x"'
+
+exit $((failures != 0))
diff --git a/shell_cmds/sh/tests/parser/line-cont1.0 b/shell_cmds/sh/tests/parser/line-cont1.0
new file mode 100644
index 0000000..717c2c2
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont1.0
@@ -0,0 +1,16 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont1.0 273243 2014-10-17 21:52:57Z jilles $
+
+i\
+f
+t\
+r\
+u\
+e
+t\
+h\
+e\
+n
+:
+\
+f\
+i
diff --git a/shell_cmds/sh/tests/parser/line-cont10.0 b/shell_cmds/sh/tests/parser/line-cont10.0
new file mode 100644
index 0000000..dbb064b
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont10.0
@@ -0,0 +1,18 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont10.0 273276 2014-10-19 11:59:15Z jilles $
+
+v=XaaaXbbbX
+[ "${v\
+#\
+*\
+a}.${v\
+#\
+#\
+*\
+a}.${v\
+%\
+b\
+*}.${v\
+%\
+%\
+b\
+*}" = aaXbbbX.XbbbX.XaaaXbb.XaaaX ]
diff --git a/shell_cmds/sh/tests/parser/line-cont11.0 b/shell_cmds/sh/tests/parser/line-cont11.0
new file mode 100644
index 0000000..f398a98
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont11.0
@@ -0,0 +1,23 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont11.0 273276 2014-10-19 11:59:15Z jilles $
+
+T=$(mktemp "${TMPDIR:-/tmp}/sh-test.XXXXXXXX") || exit
+trap 'rm -f -- "$T"' 0
+w='#A'
+# A naive pgetc_linecont() would push back two characters here, which
+# fails if a new buffer is read between the two characters.
+c='${w#\#}'
+c=$c$c$c$c
+c=$c$c$c$c
+c=$c$c$c$c
+c=$c$c$c$c
+c=$c$c$c$c
+c=$c$c$c$c
+printf 'v=%s\n' "$c" >"$T"
+. "$T"
+if [ "${#v}" != 4096 ]; then
+ echo "Length is bad (${#v})"
+ exit 3
+fi
+case $v in
+*[!A]*) echo "Content is bad"; exit 3 ;;
+esac
diff --git a/shell_cmds/sh/tests/parser/line-cont2.0 b/shell_cmds/sh/tests/parser/line-cont2.0
new file mode 100644
index 0000000..83928cf
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont2.0
@@ -0,0 +1,4 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont2.0 273243 2014-10-17 21:52:57Z jilles $
+
+[ "a\
+b" = ab ]
diff --git a/shell_cmds/sh/tests/parser/line-cont3.0 b/shell_cmds/sh/tests/parser/line-cont3.0
new file mode 100644
index 0000000..cc2af7b
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont3.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont3.0 273243 2014-10-17 21:52:57Z jilles $
+
+v=`printf %s 'a\
+b'`
+w="`printf %s 'c\
+d'`"
+[ "$v$w" = abcd ]
diff --git a/shell_cmds/sh/tests/parser/line-cont4.0 b/shell_cmds/sh/tests/parser/line-cont4.0
new file mode 100644
index 0000000..7d59c19
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont4.0
@@ -0,0 +1,8 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont4.0 273276 2014-10-19 11:59:15Z jilles $
+
+v=abcd
+[ "$\
+v.$\
+{v}.${\
+v}.${v\
+}" = abcd.abcd.abcd.abcd ]
diff --git a/shell_cmds/sh/tests/parser/line-cont5.0 b/shell_cmds/sh/tests/parser/line-cont5.0
new file mode 100644
index 0000000..23a4d94
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont5.0
@@ -0,0 +1,14 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont5.0 273276 2014-10-19 11:59:15Z jilles $
+
+bad=1
+case x in
+x\
+) ;\
+; *) exit 7
+esac &\
+& bad= &\
+& : >\
+>/dev/null
+
+false |\
+| [ -z "$bad" ]
diff --git a/shell_cmds/sh/tests/parser/line-cont6.0 b/shell_cmds/sh/tests/parser/line-cont6.0
new file mode 100644
index 0000000..66838e1
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont6.0
@@ -0,0 +1,23 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont6.0 273276 2014-10-19 11:59:15Z jilles $
+
+v0\
+=abc
+
+v=$(cat <\
+<\
+E\
+O\
+F
+${v0}d
+EOF
+)
+
+w=$(cat <\
+<\
+-\
+EOF
+ efgh
+EOF
+)
+
+[ "$v.$w" = "abcd.efgh" ]
diff --git a/shell_cmds/sh/tests/parser/line-cont7.0 b/shell_cmds/sh/tests/parser/line-cont7.0
new file mode 100644
index 0000000..6c48642
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont7.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont7.0 273276 2014-10-19 11:59:15Z jilles $
+
+[ "$(\
+(
+1\
++ 1)\
+)" = 2 ]
diff --git a/shell_cmds/sh/tests/parser/line-cont8.0 b/shell_cmds/sh/tests/parser/line-cont8.0
new file mode 100644
index 0000000..8fc84bb
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont8.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont8.0 273276 2014-10-19 11:59:15Z jilles $
+
+set -- a b c d e f g h i j
+[ "${1\
+0\
+}" = j ]
diff --git a/shell_cmds/sh/tests/parser/line-cont9.0 b/shell_cmds/sh/tests/parser/line-cont9.0
new file mode 100644
index 0000000..9618ae2
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/line-cont9.0
@@ -0,0 +1,6 @@
+# $FreeBSD: head/bin/sh/tests/parser/line-cont9.0 273276 2014-10-19 11:59:15Z jilles $
+
+[ "${$\
+:\
++\
+xyz}" = xyz ]
diff --git a/shell_cmds/sh/tests/parser/no-space1.0 b/shell_cmds/sh/tests/parser/no-space1.0
new file mode 100644
index 0000000..5b15bfe
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/no-space1.0
@@ -0,0 +1,18 @@
+# $FreeBSD: head/bin/sh/tests/parser/no-space1.0 218891 2011-02-20 17:28:58Z jilles $
+
+# These are ugly but are required to work.
+
+set -e
+
+while(false)do(:)done
+if(false)then(:)fi
+if(false)then(:)else(:)fi
+(:&&:)||:
+until(:)do(:)done
+case x in(x);;*)exit 1;(:)esac
+case x in(x);;*)exit 1;;esac
+for i do(:)done
+{(:)}
+f(){(:)}
+:|:
+(:)|(:)
diff --git a/shell_cmds/sh/tests/parser/no-space2.0 b/shell_cmds/sh/tests/parser/no-space2.0
new file mode 100644
index 0000000..0f63e6e
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/no-space2.0
@@ -0,0 +1,7 @@
+# $FreeBSD: head/bin/sh/tests/parser/no-space2.0 218891 2011-02-20 17:28:58Z jilles $
+
+# This conflicts with ksh extended patterns but occurs in the wild.
+
+set -e
+
+!(false)
diff --git a/shell_cmds/sh/tests/parser/nul1.0 b/shell_cmds/sh/tests/parser/nul1.0
new file mode 100644
index 0000000..bb5442e
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/nul1.0
@@ -0,0 +1,12 @@
+# $FreeBSD: head/bin/sh/tests/parser/nul1.0 295825 2016-02-19 21:53:12Z jilles $
+# Although POSIX does not specify the effect of NUL bytes in scripts,
+# we ignore them.
+
+{
+ printf 'v=%03000d\0%02000d' 7 2
+ dd if=/dev/zero bs=1000 count=1 status=none
+ printf '1 w=%03000d%02000d1\0\n' 7 2
+ printf '\0l\0v\0=\0$\0{\0#\0v\0}\n'
+ printf '\0l\0w\0=\0\0$\0{\0#\0w}\0\0\0\n'
+ printf '[ "$lv.$lw.$v" = "5001.5001.$w" ]\n'
+} | ${SH}
diff --git a/shell_cmds/sh/tests/parser/only-redir1.0 b/shell_cmds/sh/tests/parser/only-redir1.0
new file mode 100644
index 0000000..7aedde7
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/only-redir1.0
@@ -0,0 +1,3 @@
+# $FreeBSD: head/bin/sh/tests/parser/only-redir1.0 210221 2010-07-18 12:45:31Z jilles $
+</dev/null &
+wait $!
diff --git a/shell_cmds/sh/tests/parser/only-redir2.0 b/shell_cmds/sh/tests/parser/only-redir2.0
new file mode 100644
index 0000000..b55be16
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/only-redir2.0
@@ -0,0 +1,2 @@
+# $FreeBSD: head/bin/sh/tests/parser/only-redir2.0 254335 2013-08-14 19:34:13Z jilles $
+</dev/null | :
diff --git a/shell_cmds/sh/tests/parser/only-redir3.0 b/shell_cmds/sh/tests/parser/only-redir3.0
new file mode 100644
index 0000000..f51617b
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/only-redir3.0
@@ -0,0 +1,2 @@
+# $FreeBSD: head/bin/sh/tests/parser/only-redir3.0 254335 2013-08-14 19:34:13Z jilles $
+case x in x) </dev/null ;; esac
diff --git a/shell_cmds/sh/tests/parser/only-redir4.0 b/shell_cmds/sh/tests/parser/only-redir4.0
new file mode 100644
index 0000000..a3ce893
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/only-redir4.0
@@ -0,0 +1,2 @@
+# $FreeBSD: head/bin/sh/tests/parser/only-redir4.0 254335 2013-08-14 19:34:13Z jilles $
+case x in x) </dev/null ;& esac
diff --git a/shell_cmds/sh/tests/parser/pipe-not1.0 b/shell_cmds/sh/tests/parser/pipe-not1.0
new file mode 100644
index 0000000..421e235
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/pipe-not1.0
@@ -0,0 +1,3 @@
+# $FreeBSD: head/bin/sh/tests/parser/pipe-not1.0 214281 2010-10-24 17:06:49Z jilles $
+
+: | ! : | false
diff --git a/shell_cmds/sh/tests/parser/set-v1.0 b/shell_cmds/sh/tests/parser/set-v1.0
new file mode 100644
index 0000000..c5ed944
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/set-v1.0
@@ -0,0 +1,8 @@
+# $FreeBSD: head/bin/sh/tests/parser/set-v1.0 295937 2016-02-23 22:44:01Z jilles $
+
+${SH} <<\EOF
+echo one >&2
+set -v
+echo two >&2
+echo three >&2
+EOF
diff --git a/shell_cmds/sh/tests/parser/set-v1.0.stderr b/shell_cmds/sh/tests/parser/set-v1.0.stderr
new file mode 100644
index 0000000..d904fa5
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/set-v1.0.stderr
@@ -0,0 +1,5 @@
+one
+echo two >&2
+two
+echo three >&2
+three
diff --git a/shell_cmds/sh/tests/parser/var-assign1.0 b/shell_cmds/sh/tests/parser/var-assign1.0
new file mode 100644
index 0000000..4949bfd
--- /dev/null
+++ b/shell_cmds/sh/tests/parser/var-assign1.0
@@ -0,0 +1,19 @@
+# $FreeBSD: head/bin/sh/tests/parser/var-assign1.0 257920 2013-11-10 18:46:59Z jilles $
+# In a variable assignment, both the name and the equals sign must be entirely
+# unquoted. Therefore, there is only one assignment below; the other words
+# containing equals signs are command words.
+
+abc=0
+\abc=1 2>/dev/null
+a\bc=2 2>/dev/null
+abc\=3 2>/dev/null
+a\bc\=4 2>/dev/null
+'abc'=5 2>/dev/null
+a'b'c=6 2>/dev/null
+abc'='7 2>/dev/null
+'abc=8' 2>/dev/null
+"abc"=9 2>/dev/null
+a"b"c=10 2>/dev/null
+abc"="11 2>/dev/null
+"abc=12" 2>/dev/null
+[ "$abc" = 0 ]