diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ae180d6..021f2968 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,13 +15,14 @@
- [csharp] recognise functions with nullable results
### Changed
-- Simplified catalog.xml.
+- Simplified catalog.xml.
- Use new xsd schema for catalog.xml.
- Common.jar rename to common.zip
- reformat proto.hrc and included files; changed namespace.
- Tweak visual.hrd xml CData markup
- remove obsolete from visual-rgb.hrd
- [groovy] add .gradle as groovy
+- Use the new shell-posix schema for shell scripts by default
### Added
- New package type of base - all packed. Hrc and hrd files in one archive. Directory 'auto' not in archive.
@@ -37,6 +38,8 @@
- [csharp] support C# 11 raw strings
- [cpp] add support for C++11 string literals
- [asm] add new registers, blocks. New masks for filenames and firstline
+- [shell-posix] add a new schema for POSIX shell with block structures and error checking
+- [shell-bash] add a new schema for bash script based on shell-posix
## [1.2.0] - 2021-09-12
diff --git a/hrc/hrc/proto.hrc b/hrc/hrc/proto.hrc
index b4dff6e7..f8f04669 100644
--- a/hrc/hrc/proto.hrc
+++ b/hrc/hrc/proto.hrc
@@ -591,11 +591,23 @@
+ /^\#(!\s*.+sh\b)/
+
+
+
/\.(sh|spec)$/i
/^PKGBUILD$/i
- /\.(bash_|z)?profile/
- /\.(ba|k|z)?shrc/
- /^\#(!\s*.+sh\b)/
+ /\.z?profile/
+ /\.(k|z)?shrc/
+ /^\#(!\s*.+sh\b)/
+
+
+
+ /\.sh$/i
+ /\.bash$/i
+ /\.bash_profile/
+ /\.bashrc/
+ /^\#!(\s*.+bash\b)/
diff --git a/hrc/hrc/scripts/shell-bash.hrc b/hrc/hrc/scripts/shell-bash.hrc
new file mode 100644
index 00000000..bde4024f
--- /dev/null
+++ b/hrc/hrc/scripts/shell-bash.hrc
@@ -0,0 +1,698 @@
+
+
+
+
+
+
+ Shell Scripts (bash)
+
+ Based on:
+ https://www.gnu.org/software/bash/manual/bash.html
+ This is Edition 5.2, last updated 19 September 2022
+
+ Notes:
+ - nested here-docs are not supported.
+
+ Home: https://github.com/chpock/ck.colorer-schemes
+ Send requests there for bug fixes and features.
+
+
+ ]]>
+
+
+
+
+ /\.sh$/i
+ /\.bash$/i
+ /^\#(!\s*.+bash\b)/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hrc/hrc/scripts/shell-posix.hrc b/hrc/hrc/scripts/shell-posix.hrc
new file mode 100644
index 00000000..136935e2
--- /dev/null
+++ b/hrc/hrc/scripts/shell-posix.hrc
@@ -0,0 +1,645 @@
+
+
+
+
+
+
+ Shell Scripts (POSIX)
+
+ Based on:
+ IEEE Std 1003.1-2008
+ https://pubs.opengroup.org/onlinepubs/9699919799/utilities/toc.html
+
+ Notes:
+ - nested here-docs are not supported.
+
+ Home: https://github.com/chpock/ck.colorer-schemes
+ Send requests there for bug fixes and features.
+
+
+ ]]>
+
+
+
+
+ /\.(sh|spec)$/i
+ /^PKGBUILD$/i
+ /^\#(!\s*.+sh\b)/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hrc/test/_valid/other/test.sh.html b/hrc/test/_valid/other/test.sh.html
deleted file mode 100644
index 5f2d1966..00000000
--- a/hrc/test/_valid/other/test.sh.html
+++ /dev/null
@@ -1,9 +0,0 @@
-0:
-1: /bin/sh
-2: (cd x; y/a-b.sh)
-3:
-4: echo ${#aoeu[@]}
-5:
-6: DATE=`date`
-7: echo $DATE
-8:
diff --git a/hrc/test/_valid/shell/shell-bash-spec.bash.html b/hrc/test/_valid/shell/shell-bash-spec.bash.html
new file mode 100644
index 00000000..facdc946
--- /dev/null
+++ b/hrc/test/_valid/shell/shell-bash-spec.bash.html
@@ -0,0 +1,459 @@
+ 0: /usr/bin/env bash
+ 1:
+ 2:
+ 3:
+ 4: $'\nfoo\e'
+ 5: A=$'\\\'\"\?no special meaning'
+ 6: CDPATH=$'octal \1 \12 \123 foo' $'octal error \9 \19 \181 foo'
+ 7: command ${CDPATH%$'test\rtest'} `in backquote $'test\1test'`
+ 8: ( in subshell $'\1' )
+ 9: { in group $'1'; }
+ 10: command $'hex \x1 \x1a \xFFnospecial meaning'
+ 11: A=$(foo $'unicode \u1 \uF1 \uFFA \udeadno special meaning')
+ 12: $'unicode \U1 \UF1 \UFFA \Udead \UDEAD1 \U12345 \U123456 \U1234567 \U12345678no special meaning'
+ 13: $'control-x \cx no cpecial meaning'
+ 14:
+ 15:
+ 16:
+ 17: $"some message"
+ 18: A=$"some message $VAR inside"
+ 19: CDPATH=$"msg $'ansi-c\\here\r'"
+ 20: command ${CDPATH%$"msg $(command)"}
+ 21: ( in subshell $"msg" )
+ 22: { in group $"msg"; }
+ 23: A=$(foo $"something $'ansi-c\t\\' ${CDPATH#$"msg"}") `in bq $"some\$th\\i\ng"`
+ 24:
+ 25:
+ 26:
+ 27:
+ 28: for (( i = 0; $i < $VAR; i++ )); do
+ 29: cmd
+ 30: done
+ 31:
+ 32: for (( i = 0; i < $VAR; i++ )); do
+ 33: cmd
+ 34: done
+ 35:
+ 36: for (( i = 0; $i < '$NO_VAR'; i = $i + $'ansi-c' ))
+ 37: do
+ 38: cmd
+ 39: done
+ 40:
+ 41: for (( i = "123"; $i < ${CDPATH}; i = $i / 100 )); do V1=456 command here; done
+ 42: for ((;;)); do V1=456 command here; done
+ 43:
+ 44:
+ 45:
+ 46:
+ 47:
+ 48: select var in $VAR; do
+ 49:
+ 50: done
+ 51:
+ 52: select var in; do done
+ 53:
+ 54: select VAR in "BLA" "FOO" "BAR"; do; done
+ 55:
+ 56: select VAR; do
+ 57: command
+ 58: if [ -n "$FOO" ]; then
+ 59: something
+ 60: select VAR; do
+ 61: done
+ 62: fi
+ 63: select VAR; do
+ 64: select VAR; do
+ 65: done
+ 66: done
+ 67: done
+ 68:
+ 69: select IFS in; do done
+ 70: select CDPATH in; do done
+ 71:
+ 72: ( select VAR; do done )
+ 73: { select VAR; do done; }
+ 74:
+ 75:
+ 76:
+ 77:
+ 78: (( "asd" '123' $'\r\t123' $"foo" 1 ))
+ 79: (( $(V1=1 command) `command` ))
+ 80: (( \$ \" \' \$ ))
+ 81: (( $VAR $IFS $CDPATH ))
+ 82: (( ${VAR%10} ${IFS#10} ${CDPATH%10} ))
+ 83: (( i++ i-- ++IFS --CDPATH ))
+ 84: (( 1 + 1 - 2 ! 1 ~ 3 ** 3 * 4 / 5 % -6 >> 10 << 20 ))
+ 85: (( 1 <= 2 >= 4 < 1 > 4 == 5 != 4 & 1 ^ 5 | 8 && 10 || 20 ? 30 : 2 ))
+ 86: (( a = 1 || w *= 1 || IFS /= 10 || CDPATH %= 10 || x += 10 || y -= 10 ))
+ 87: (( a <<= 10 || b >>= 30 || c &= 1 || f |= 40 ))
+ 88:
+ 89: (( 0174 + 0$VAR + 8#123 + 09874 + 8#845 ))
+ 90: (( 0x12F + 0XDeaDBeEf111 + 0x$VAR + 16#411Ab + 0x1Z23 + 16#123K ))
+ 91: (( 3#10 + 10#$VAR + 44#50 + 65#567 ))
+ 92: (( 2#45 + 10#45A ))
+ 93:
+ 94:
+ 95:
+ 96: [[ a -f e || -f /bla || -o fofofof || -v varname || -R varname && -z "$STRING" ]]
+ 97: [[ 1 > 2 ]]
+ 98: [[ "asd" '123' $'\r\t123' $"foo" 1 ]]
+ 99: [[ $(V1=1 command) `command` ]]
+100: [[ \$ \" \' \$ ]]
+101: [[ $VAR $IFS $CDPATH ]]
+102: [[ ${VAR%10} ${IFS#10} ${CDPATH%10} ]]
+103: [[ $fffj =~ [[:space:]]*(a)?b ]]
+104: [[ $line =~ ^"initial string" ]]
+105: [[ $line =~ "^initial string" ]]
+106: pattern='[[:space:]]*(a)?b'
+107: [[ $line =~ $pattern ]]
+108: [[ $line =~ $CDPATH ]]
+109: [[ 'Hello World' =~ Hello ]]
+110: [[ $digit =~ [0-9] ]]
+111: [[ $REPLY =~ ^[0-9]+$ ]]
+112: [[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}$ ]]
+113: [[ $ip =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]
+114:
+115:
+116:
+117: coproc CDPATH {
+118: select far in; do
+119: done
+120: } 2>/dev/null
+121:
+122: coproc name_as_variable { V=1 command here; } 2>/dev/null 1<foo
+123:
+124: coproc command here 1>/dev/null
+125:
+126: coproc name_as_var {
+127: V=1 command here
+128: }
+129:
+130: coproc {
+131: V1=1 command here
+132: }
+133:
+134:
+135:
+136: func-name () command here 2>/dev/null
+137:
+138: func%name () {
+139: command here
+140: } 2>/dev/null
+141:
+142: func-name () { command here; }
+143:
+144: ,func-name-comma () { command here; }
+145:
+146: function fu1[nc]name command here 1>/dev/null
+147:
+148: function f-un[c () command here
+149:
+150: function f123 () {
+151: command here
+152: }
+153:
+154: function func-name { command here; }
+155:
+156: function -error here;
+157:
+158:
+159:
+160: ${A:-word} ${BASH:-word}
+161: ${A:=word} ${BASH:=word}
+162: ${A:?word} ${BASH:?word}
+163: ${A:+word} ${BASH:+word}
+164:
+165: ${A:0} ${A:0:10} ${A: -1} ${A: -1:-10} ${BASH:0} ${BASH:0:10} ${BASH: -1} ${BASH: -1:-10}
+166: ${@:7} ${@:1:2} ${*:1} ${*:1:2}
+167: ${A:$(( ${#B} + 10 )):$(command here)} ${A:"10":$'\r\t10'}
+168:
+169: ${!prefix*} ${!prefix@} ${!1@}
+170:
+171: ${!name[@]} ${!name[*]}
+172: ${!A} ${!BASH} ${!1} ${!@}
+173:
+174: ${#A} ${#BASH} ${#*} ${#@}
+175: ${A#word} ${BASH#word} ${A##word} ${BASH##word}
+176: ${A%word} ${BASH%word} ${A%%word} ${BASH%%word}
+177:
+178: ${A/pat/str} ${BASH/pat/str} ${A//pat/str} ${BASH//pat/str}
+179: ${A/#pat/str} ${BASH/#pat/str} ${A/%pat/str} ${BASH/%pat/str}
+180: ${A/$(command)/`test`"dbl"$'ansi'}
+181:
+182: " ${A/pat/str} ${A/$(command)/`test`"dbl"$'ansi'} "
+183:
+184: ${A^pat} ${BASH^pat} ${A^^pat} ${BASH^^pat}
+185: ${A,pat} ${BASH,pat} ${A,,pat} ${BASH,,pat}
+186: ${A^$(command here)} ${BASH,,`test`"sdfasdf"$'\r\t\e'}
+187:
+188: ${A@U} ${A@u} ${A@L} ${A@Q} ${A@E} ${A@P} ${A@A} ${A@K} ${A@a} ${A@k}
+189: ${BASH@U} ${BASH@u} ${BASH@L} ${BASH@Q} ${BASH@E} ${BASH@P} ${BASH@A} ${BASH@K} ${BASH@a} ${BASH@k}
+190:
+191: for i in; do
+192: "'${M:$i:1}"
+193: done
+194:
+195:
+196:
+197: $CDPATH $HOME $IFS $MAIL $MAILPATH $OPTARG $OPTIND $PATH $PS1 $PS2
+198:
+199: ${#CDPATH}
+200:
+201: CDPATH=1 CDPATH=somestring
+202:
+203:
+204:
+205: command here <(V=1 command here) >(V=1 command here)
+206:
+207: command here < <(V=1 command here)
+208:
+209:
+210:
+211: ls > dirlist 2>&1
+212: ls 2>&1 > dirlist
+213:
+214:
+215:
+216: command < test < $VAR
+217: command 2< test 1<$CDPATH
+218:
+219:
+220:
+221: command >test >$VAR
+222: command >|test >|$VAR
+223: command 1>test 2>$VAR
+224: command 1>|test 0>|$VAR
+225:
+226:
+227:
+228: command >>test >>$VAR
+229: command 2>>test 2>>$VAR
+230:
+231:
+232:
+233: command &>test >&test
+234: command >test 2>&1
+235:
+236:
+237:
+238: command &>>test
+239:
+240:
+241:
+242: command <<< word
+243: command <<< $VAR
+244: command <<< $(V=1 command here)
+245: command 1<<< word
+246: command 1<<< "string"$'ansi''single'
+247: command <<< "HERE STRING"
+248:
+249: for i in; do
+250: if bla; then
+251: while read -r; do
+252: done <<< "HERE STRING"
+253: fi
+254: done
+255:
+256:
+257:
+258: command <&1
+259: command 1<&1
+260: command 1<&$VAR
+261: command 1<&-
+262: command >&1
+263: command 2>&3
+264: command 1>&$VAR
+265: command 1>&-
+266:
+267:
+268:
+269: command <&1-
+270: command 1<&1-
+271: command >&1-
+272: command 1>&1-
+273:
+274:
+275:
+276: command <> test
+277: command 1<>test
+278:
+279:
+280:
+281: :
+282: . file arg1 arg2 arg3
+283: break; break $VAR; break 1; break error here
+284: cd; cd -L -e dir
+285: continue; continue $VAR; continue 1; continue error here
+286: eval a b c d
+287: exec -c -a foo command a f g
+288: exit; exit $VAR; exit 1; exit error here
+289: export -fn -p VARNAME VAR="value" BASH CDPATH
+290: getopts optstring NAME foo rrr ooo
+291: hash -r -p name
+292: pwd; pwd -L -P
+293: readonly -aA VARNAME VAR="value" BASH IFS
+294: return; return $VAR; return 1; return error here
+295: shift; shift $VAR; shift 1; shift error here
+296: test -x foo -o $ASD
+297: [ -x foo -o $VAR ]
+298: times; times error here
+299: trap; trap -l -p a s df
+300: umask -p -S 0444
+301: unset -f -n -v VAR1 VAR2 $VAR_IN_VAR CDPATH BASH
+302:
+303:
+304:
+305: alias; alias -p foo=bla
+306: bind; bind -m aaa -f foo
+307: builtin; builtin umask 0444
+308: caller; caller $VAR; caller 123 error here
+309: command -pV grep here
+310: declare -aA -p VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str'
+311: echo -neE foo
+312: enable -a -d fff
+313: help -d patt
+314: local -aA -p VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str'
+315: logout; logout $VAR; logout 1; logout error here
+316: mapfile -d 'f' file array
+317: printf -v VAR 'format' foo
+318: read -a -r VAR bla
+319: readarray -d dd -C call array
+320: source file; source file error here
+321: type -af name
+322: typeset -afFg VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str'
+323: ulimit; ulimit -a; ulimit -H name
+324: unalias; unalias -a; unalias name1 name2
+325:
+326: let a=4
+327: let z=a++
+328: let y=--b
+329: let result=~a
+330: let "result=a<<2"
+331: let "result=a&b"
+332: let i=5 result=~a "result=a<<2"
+333: let "myvar=7" "myvar2=4" "myvar3= myvar ^ myvar2"
+334:
+335:
+336:
+337: set -a a b d
+338:
+339:
+340:
+341: shopt -p -o opt
+342:
+343:
+344:
+345: $_ $BASH $BASHOPTS $BASHPID $BASH_ALIASES $BASH_ARGC
+346: $BASH_ARGV $BASH_ARGV0 $BASH_CMDS $BASH_COMMAND $BASH_COMPAT $BASH_ENV
+347: $BASH_EXECUTION_STRING $BASH_LINENO $BASH_LOADABLES_PATH $BASH_REMATCH
+348: $BASH_SOURCE $BASH_SUBSHELL $BASH_VERSINFO $BASH_VERSION $BASH_XTRACEFD
+349: $CHILD_MAX $COLUMNS $COMP_CWORD $COMP_LINE $COMP_POINT $COMP_TYPE $COMP_KEY
+350: $COMP_WORDBREAKS $COMP_WORDS $COMPREPLY $COPROC $DIRSTACK $EMACS $ENV $EPOCHREALTIME
+351: $EPOCHSECONDS $EUID $EXECIGNORE $FCEDIT $FIGNORE $FUNCNAME $FUNCNEST $GLOBIGNORE
+352: $GROUPS $histchars $HISTCMD $HISTCONTROL $HISTFILE $HISTFILESIZE $HISTIGNORE
+353: $HISTSIZE $HISTTIMEFORMAT $HOSTFILE $HOSTNAME $HOSTTYPE $IGNOREEOF $INPUTRC
+354: $INSIDE_EMACS $LANG $LC_ALL $LC_COLLATE $LC_CTYPE $LC_MESSAGES $LC_NUMERIC
+355: $LC_TIME $LINENO $LINES $MACHTYPE $MAILCHECK $MAPFILE $OLDPWD $OPTERR $OSTYPE
+356: $PIPESTATUS $POSIXLY_CORRECT $PPID $PROMPT_COMMAND $PROMPT_DIRTRIM $PS0 $PS3 $PS4
+357: $PWD $RANDOM $READLINE_ARGUMENT $READLINE_LINE $READLINE_MARK $READLINE_POINT
+358: $REPLY $SECONDS $SHELL $SHELLOPTS $SHLVL $SRANDOM $TIMEFORMAT $TMOUT $TMPDIR $UID
+359:
+360: ${#BASH}
+361:
+362: BASH=1 BASH=somestring
+363:
+364:
+365:
+366: for CDPATH; do
+367: foo
+368: done
+369:
+370: for CDPATH in 1 2 3; do
+371: foo
+372: done
+373:
+374:
+375:
+376: export CDPATH CDPATH=123
+377: unset CDPATH
+378:
+379:
+380:
+381: bash; bash -c fff
+382:
+383:
+384:
+385: ADD=()
+386: ARR=("val1" "val2" value\$one "val3" $(command here; echo \)) $'ansi-str')
+387: ARR+=("val1" "val2" "val3" $(command here; echo \)) $'ansi-str')
+388: ARR=(["foo"]="val1" [$VAR $VAR2 \] $VAR3]="val2" [$(V=1 command)]="foo" ["str"'str'$'\rstr']="str"'str'$'\rstr' )
+389:
+390: ${!A[1]} ${!A["idx"]}
+391:
+392: ARR[1]="val"
+393:
+394: ARR["FOO"]="val" [sdfsdf]
+395: ARR[$IDX]="val"
+396: ADD[${IDX[0]}]="foo"
+397: ADD[${#IDX[@]}]="foo"
+398:
+399: echo $A["foo"]
+400: echo ${A["foo"]}
+401:
+402: A[$(echo bla)]
+403: A[$(echo bla)]=1 command here foo
+404:
+405: A[fla echo 1]=1
+406: A[fla "echo]=" 1]=foo
+407: echo ${A[fla "echo]=" 1]}
+408:
+409:
+410:
+411: ${A[foo]:-word} ${A['sdf']:=word} ${A[1]:?word} ${A[fff]:+word}
+412:
+413: ${A[foo]:0} ${A[$'bla']:0:10} ${A[$(command)]: -1} ${A[10]: -1:-10}
+414: ${A[1]:$(( ${#B} + 10 )):$(command here)} ${A[foo]:"10":$'\r\t10'}
+415: ${A[0]:7} ${A[0]:1:10} ${A[@]:1} ${A[*]:1}
+416:
+417: ${#A[foo]}
+418:
+419: ${A[1]#word} ${A[foo]##word} ${A['sdf']%word} ${A[$(test)]%%word}
+420:
+421: " ${A[1]#word} ${A[foo]##word} ${A['sdf']%word} ${A[$(test)]%%word} "
+422:
+423: ${A[10]/pat/str} ${A[foo]//pat/str} ${A["a"]/#pat/str} ${A[0]/%pat/str}
+424: ${A[foo]/$(command)/`test`"dbl"$'ansi'}
+425:
+426: ${A[10]^pat} ${A[foo]^^pat} ${A["bla bla"],pat} ${A[iii],,pat}
+427: ${A[0]^$(command here)} ${A[1],,`test`"sdfasdf"$'\r\t\e'}
+428:
+429: ${A[0]@U} ${A[1]@u} ${A[foo]@L} ${A["bla"]@Q} ${A[1]@E}
+430: ${A[$'ansi']@P} ${A[$(command here)]@A} ${A[`command here`]@K} ${A[$VAR]@a} ${A[0]@k}
+431:
+432:
+433:
+434: dirs -c -l +N; dirs
+435: popd; popd -n
+436: pushd; pushd -n dir
+437:
+438:
+439:
+440: bg; bg 1
+441: fg; fg 1 error here
+442: jobs; jobs -l 123
+443: kill; kill -l 1
+444: wait; wait -f 10 1
+445: disown; disown -a id $ID
+446: suspend; suspend -f; suspend -f error here
+447:
+448:
+449:
+450: compgen -o word
+451: complete -a name name
+452: compopt -o opt name
+453:
+454:
+455:
+456: fc; fc -e name
+457: history; history 1; history -c
+458:
diff --git a/hrc/test/_valid/shell/shell-posix-spec.sh.html b/hrc/test/_valid/shell/shell-posix-spec.sh.html
new file mode 100644
index 00000000..acd28115
--- /dev/null
+++ b/hrc/test/_valid/shell/shell-posix-spec.sh.html
@@ -0,0 +1,921 @@
+ 0: /bin/sh
+ 1:
+ 2:
+ 3:
+ 4:
+ 5:
+ 6: \| \& \; \> \< \( \) \$ \` \\ \" \' no meaning
+ 7: test for no meaning for new line \
+ 8: I_AM_NOT_VARIABLE=1 command \
+ 9: if doesn\'t work also
+ 10:
+ 11:
+ 12: 'single quote string' 'escape does not \work here'
+ 13:
+ 14:
+ 15: double quoted "only these chars should be escaped \$, \`, \", \\, but \nothing \! else"
+ 16:
+ 17:
+ 18: ! command
+ 19:
+ 20: do elif else
+ 21: elif
+ 22: elif VAR=1 some command here >&1
+ 23: else
+ 24: in
+ 25: then
+ 26:
+ 27:
+ 28:
+ 29:
+ 30:
+ 31:
+ 32: do elif else
+ 33:
+ 34:
+ 35:
+ 36: $@ $* $# $? $- $$ $0
+ 37: ${@} ${*} ${#} ${?} ${-} ${$} ${0}
+ 38:
+ 39:
+ 40: $ENV $HOME $IFS $LANG $LC_ALL $LC_COLLATE $LC_TYPE $LC_MESSAGES
+ 41: $LINENO $NLSPATH $PATH $PPID $PS1 $PS2 $PS4 $PWD
+ 42:
+ 43: $PATH_SEPARATOR
+ 44:
+ 45: ${ENV} ${HOME} ${IFS} ${LANG} ${LC_ALL} ${LC_COLLATE} ${LC_TYPE} ${LC_MESSAGES}
+ 46: ${LINENO} ${NLSPATH} ${PATH} ${PPID} ${PS1} ${PS2} ${PS4} ${PWD}
+ 47:
+ 48: ENV=1 HOME=2 IFS=3 LANG=foo LC_ALL=bar LC_COLLATE=xxx LC_TYPE=1 LC_MESSAGES=2
+ 49: LINENO=1 NLSPATH=bla PATH=11 PPID=r PS1=x PS2=+ PS4=e PWD=5
+ 50:
+ 51:
+ 52: ${ASD-fo br} ${ASD:-fo" br"} ${ASD='br bz'} ${ASD:=br \{ bo}
+ 53: ${ASD?$VARH} ${ASD:?"$QVAR"} ${ASD+$(V=1 cmd re)} ${ASD:+`V=1 a here`}
+ 54: ${1-foo bar} ${1:-foo" bar"} ${1='bar baz'} ${1:=bar \{ boo}
+ 55: ${1?$VARHERE} ${1:?"$QVAR"} ${1+$(V=1 cmd here)} ${1:+`V=1 a here`}
+ 56:
+ 57: ${#ASD} ${#1}
+ 58:
+ 59: ${ASD%fo ba} ${ASD%%fo" br"} ${ASD#'bz bz'} ${ASD##br \{ bo}
+ 60: ${1%$VARH} ${1%%"$QVAR"} ${1#$(V=1 cmd re)} ${1##`V=1 a here`}
+ 61:
+ 62: $ASD $1
+ 63:
+ 64:
+ 65:
+ 66:
+ 67: ${A%foo # bar}
+ 68: ${A%foo ; command}
+ 69: ${A%foo > command}
+ 70: ${A%foo ) command}
+ 71: ${A%foo ( command}
+ 72: ${A%foo & command}
+ 73: ${A%foo | command}
+ 74:
+ 75: A=123 A="sdfasdf" A=$(V=1 command here 2>/dev/null) B=`cd asd`
+ 76: A=123; cd test
+ 77: A=1|B=2|topipe command
+ 78: A=1;nextcmd
+ 79: A=1>A=1 cmd here
+ 80:
+ 81:
+ 82: exec 1 $( { V=123 V2="sdsdf"; }; execute something 2>&1 1>/dev/null && X=1 echo 123 V=1)
+ 83: exec 2 "$(V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1)"
+ 84: exec 3 `V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1`
+ 85: exec 4 "`V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1`"
+ 86:
+ 87: TODO?)
+ 88: exec 3 `V=123 V2="sdsdf" \`X=1 echo 123 V=1\` more params`
+ 89: exec 4 "`V=123 V2="sdsdf" \`X=1 echo 123 V=1\` more params`"
+ 90:
+ 91:
+ 92: $(( X + B << 2 * 10 / 30 + $X - $1 % "123" ))
+ 93: A=$(( X + B << 2 * 10 / 30 ))
+ 94: A="$(( X + B << 2 * 10 / 30 ))"
+ 95:
+ 96:
+ 97: foo < bla
+ 98: foo 0< bla
+ 99:
+100:
+101: foo > bla
+102: foo 2>bla
+103: foo 2>|bla
+104:
+105:
+106: foo >> bla
+107: foo 2>>bla
+108:
+109:
+110: Non quoted here-doc 2<<BLA
+111: If no part of word is ${quoted}, all lines of the here-document shall be
+112: expanded for $parameter ${expansion}, `A=1 command` $(B=2 substitution >/dev/null),
+113: and $((arithmetic expansion + 1 / 10)). In this case, the <backslash> in the input
+114: behaves as the <backslash> inside double-quotes (see Double-Quotes).
+115: ( Here we are \$, \`, \", \\, but \nothing \! else )
+116: However, the double-quote character ( ' )' shall not be treated specially
+117: within a here-document, except when the double-quote appears
+118: within "$()", "``", or "${}". (WTF?!)
+119: BLA
+120:
+121: Quoted here-doc <<-"FOO"
+122: If any part of word is quoted, the delimiter shall be formed by performing
+123: quote removal on word, and the here-document lines $shall not be $(expanded).
+124: FOO
+125:
+126: Single-quoted here-doc <<'FOO'
+127: not $expanded
+128: FOO
+129:
+130: heredoc after redirection >foobar << BLA
+131: with space before label
+132: BLA
+133:
+134:
+135: 1<&2 <&-
+136:
+137:
+138: 1>&2 2>&-
+139:
+140:
+141: <>/blabla 1<> /blabla
+142:
+143:
+144:
+145: alias foo=bla
+146: bg alias cd
+147: cd command A1=11
+148: DEFINE_VAR=1 command
+149: false
+150: DEFINEVAR=2 command cd alias >/dev/null
+151: DEFVAR=1 fc 1>&1
+152: fg
+153: getopts more parameters here
+154: hash THIS_IS_PARAMETER_BUT_NOT_VARIABLE=1
+155: jobs
+156: kill
+157: newgrp
+158: pwd
+159: read
+160: true
+161: umask
+162: unalias
+163: wait while do for in
+164:
+165:
+166:
+167:
+168: alias bg cd hash
+169:
+170:
+171: alias VAR1=1
+172:
+173: command while something; command
+174:
+175:
+176: VAR1=1 foo bla | VAR=2 ! test cmd
+177:
+178:
+179: VAR1=1 foo bla && ! VAR=2 test cmd || VAR=3 command read
+180: VAR=1 foo & && VAR=2 test cmd
+181: R=1 date && V=1 who || VAR=1 ls; VAR=2 cat file
+182: V=1 wc file > output & R=1 true
+183:
+184: V=1 background1 & V=2 background2
+185:
+186: V=1 command1; V=2 command2
+187:
+188:
+189: ( V1=1 grouped command1; V=1 command2 )
+190: (
+191: V1=1 command1 here
+192: V2=2 command2
+193: (
+194: V2= nested
+195: {
+196: V3=1 nested
+197: }
+198: )
+199: )
+200: ( V1=1 command1
+201: V2=2 command2 \) )
+202:
+203: { V1=1 group 1; V1= command2 here should be an error here because of the missing semicolon }
+204: }
+205: { cmd1; cmd2; no error here; }
+206: {
+207: cmd1
+208: V1=cmd1
+209: {
+210: nested
+211: \}
+212: }
+213: }
+214:
+215: if
+216: fi
+217: then
+218: fi
+219:
+220:
+221:
+222: for IFS in 1 2 3
+223: do
+224: done
+225:
+226: for IFS in $(V1=val command) 2 3; do command; done;
+227: for "IFS" in $(V1=val command) 2 3; do command; done;
+228:
+229: for var in $VAR; do
+230:
+231: done
+232:
+233: for var in; error here do done
+234: do
+235: done
+236:
+237: for var in; error here; do done
+238:
+239: for var in; do done
+240:
+241: for VAR in "BLA" "FOO" "BAR"; do; done
+242:
+243: for VAR
+244: do
+245: done
+246:
+247: for $(V1=val command here); do
+248: command
+249: done
+250:
+251: for VAR error here; do
+252: done
+253:
+254: for VAR; do
+255: command
+256: if [ -n "$FOO" ]; then
+257: something
+258: fi
+259: done
+260:
+261: for IFS; do command; done;
+262:
+263: for "IFS"; do command; done;
+264: for "IFS"; do command; done;
+265:
+266:
+267:
+268: case $FOO in
+269: a aaaaa pat1) A=1 xdo; A=2 something ;;
+270: pat2|fff\) BLA=123) B=2;;
+271: pat3)
+272: A=x cmd;;
+273: pat4)
+274: B=1 cmd
+275: C=3 cmd1
+276: if [ -x "$BLA" ]; then
+277: ffff
+278: case $BLA in
+279: fff) F=1;;
+280: bla) no the last ";;" here
+281: esac
+282: fi
+283: ;;
+284: here pat) T=1 ttt;;
+285: $VAR_HERE) cmd;;
+286: $(V1=1 some command here)) cmd2;;
+287: *) bla
+288: fooo
+289: ;;
+290: esac
+291:
+292:
+293:
+294: if foo; then
+295: C=1 cmd here 2>/dev/null
+296: fi
+297:
+298: if [ $BLABLA -gt 1 ]; then VAR=HERE cd blalbla; fi
+299:
+300: if [ -x "$N" ]; then
+301: alias skdfjlkj
+302: elif V=1 some command here; then
+303: V1=1 anything here
+304: blalba
+305: elif [ -t -o 1 -x ]; then
+306: X=1 ffff
+307: else
+308: command here
+309: fi
+310:
+311: if [ $BLABLA != "123" ]; then
+312: X=1 somecmd sfasfasd sfsfasdf afa sdf sdf;
+313: if foo; then
+314: cd sdfkjkjfkj
+315: fi
+316: fi
+317:
+318: if V=1 command here
+319: then
+320: V1=2 we do something
+321: if nested; then
+322: nothing to do
+323: fi
+324: fi
+325:
+326:
+327:
+328: while true; do
+329: something
+330: done
+331:
+332: while [ -x "$BLA" ]; do something here; done
+333: while [ -x "FOO" ]; do while bla; do nothing; done; done
+334:
+335: while x 2>&1; do
+336: while nested; do
+337: nothing
+338: done
+339: done
+340:
+341:
+342:
+343: until true; do
+344: something
+345: done
+346:
+347: until [ -x "$BLA" ]; do something here; done
+348:
+349: until x 2>&1; do
+350: while nested; do
+351: until [ -x nested ]; do
+352: nothing
+353: done
+354: done
+355: done
+356:
+357:
+358:
+359: somefn() sfkjskdfj;
+360: no fn here
+361:
+362: somefn () {
+363: still fn
+364: bla
+365: fnd2() {
+366: another fn
+367: }
+368: }
+369:
+370: somefn()
+371:
+372: errorfn() { blalbla }
+373: close the curved bracket from above; }
+374:
+375: func( ) cmd function with space between brackets
+376: func ( ) cmd function with space between brackets#2
+377:
+378:
+379:
+380:
+381:
+382:
+383:
+384:
+385: break
+386: break; break; break
+387: break 10
+388: break "$VAR"; break '123'
+389: break a10
+390: break; break 10; break error here; break 1;
+391: break error here
+392: break;
+393: break $SOMEVAR but error here
+394: break $(V=1 eval something here) but error here
+395:
+396:
+397:
+398:
+399:
+400:
+401: :
+402: :$VAR$(V=1 evaluations)
+403:
+404:
+405:
+406:
+407:
+408:
+409: continue
+410: continue; continue; continue 10 20
+411: continue 10
+412: continue a10
+413: continue; continue 10; continue error here; continue 1;
+414: continue error here
+415: continue;
+416: continue $SOMEVAR but error here
+417: continue $(V=1 eval something here) but error here
+418:
+419:
+420:
+421:
+422:
+423:
+424: . file; . tttt
+425: . file 2>/dev/null error here;
+426: . file; . file $VAR error here; command next here
+427: . file; . file error here
+428:
+429:
+430:
+431:
+432:
+433:
+434: eval "something" 2>/dev/null
+435: eval "something"
+436: eval "one" "two" $(V1=1 cmd3 >/dev/null)
+437: eval; V=1 another command here
+438: eval ; V=1 another command here
+439: eval
+440:
+441:
+442:
+443:
+444:
+445:
+446: exec command is not highlighted as buildin 1>/dev/null
+447: exec; V1=1 command here
+448: exec ; V1=1 command here too
+449: exec 3< readfile
+450: exec 4> writefile
+451: exec 5<&0
+452: exec 3<&-
+453: foo=bar exec cmd
+454:
+455:
+456:
+457:
+458:
+459:
+460: exit
+461: exit; exit; exit
+462: exit 10
+463: exit a10
+464: exit; exit 10; exit error here; exit 1;
+465: exit error here
+466: exit;
+467: exit $SOMEVAR but error here
+468: exit $(V=1 eval something here) but error here
+469:
+470:
+471:
+472:
+473:
+474:
+475:
+476: export ; export VAR FOO BLA=1 PATH $IFS PATH=123 -wrong variable name
+477: export X="fff" R="$(V=1 cmd here)" $VAR_ALSO 'quoted' 1wrong variable name
+478: export -p; export only;
+479: export -p a
+480: export -p error here; export VAR one two
+481: export X=$(false)
+482:
+483:
+484:
+485:
+486:
+487:
+488:
+489: readonly
+490: readonly 1>/a123 FFF
+491: readonly DFF 1>/b123
+492: readonly; readonly VAR FOO BLA=1 PATH $IFS PATH=123 -wrong variable name
+493: readonly X="fff" R="$(V=1 cmd here)" $VAR_ALSO 'quoted' 1wrong variable name
+494: readonly -p; readonly only;
+495: readonly -p a
+496: readonly -p error here; readonly VAR one two
+497: readonly X=$(false)
+498:
+499:
+500:
+501:
+502:
+503:
+504: return
+505: return 2>/dev/null error here
+506: return 10 2>/dev/null error here
+507: return; return; return
+508: return 10
+509: return a10 <- errors here
+510: return; return 10; return error here; return 1;
+511: return error here
+512: return;
+513: return $SOMEVAR but error here
+514: return $(V=1 eval something here) but error here
+515:
+516:
+517:
+518:
+519:
+520:
+521:
+522:
+523:
+524:
+525: set
+526: set; set +a 1>/dev/null
+527: set -o option $(cmd here); set -- "$VAR"
+528: set -o
+529: set +o
+530:
+531:
+532:
+533:
+534:
+535:
+536: shift
+537: shift 2>/dev/null error here
+538: shift; shift; shift
+539: shift 10
+540: shift a10 <- errors here
+541: shift; shift 10; shift error here; shift 1;
+542: shift error here
+543: shift;
+544: shift $SOMEVAR but error here
+545: shift $(V=1 eval something here) but error here
+546:
+547:
+548:
+549:
+550:
+551:
+552: times; times error here;
+553: times aaa
+554: times error here; times 2>/dev/null sdfsdfasf
+555:
+556:
+557:
+558:
+559:
+560:
+561:
+562: trap 1 SIG1 SIG2 $SIG_AS_VARIABLE $(command here)
+563: trap "some sction" SIG1 SIG2 2>/dev/null; V=1 the next command here
+564: trap 1 1>/dev/null
+565:
+566:
+567:
+568:
+569:
+570:
+571: unset -x;
+572: unset;
+573: unset -f; unset -v; unset -fv; unset -vf
+574: unset -f VAR VAR2; unset -v VAR VAR2; unset -vf VAR VAR ERR_HERE=1
+575: unset VAR VAR2 IFS VAR3 $(V=1 cmd here) "quote" 'single' 2>/dev/null
+576: unset VAR=234 FFFgger;
+577:
+578:
+579:
+580:
+581:
+582: test -x /some/file -o -n "$BLABLA" && test -n "$VAR"
+583:
+584: batch; batch error hereas; batch $(AGAIN ERROR) fasdf
+585:
+586: false; false error here;
+587:
+588: true; true error here;
+589:
+590: logname; logname error here;
+591:
+592: sleep; sleep 10; sleep $VAR; sleep a10
+593:
+594: tty; tty error here;
+595:
+596: dirname; dirname $A; dirname test error here ;
+597: dirname $VAR error here; dirname foo
+598:
+599: uname; uname -a;
+600: uname -a error here
+601:
+602:
+603:
+604: alias;
+605: alias name; alias name='string'
+606: alias name=$FOO;
+607: ar -x; ar -r;
+608: ar
+609: ar; ar -p
+610: at -l -1 bla; at; at -m '10' $(V1=1 cmd run)
+611: awk; awk -F bla; awk $(TE=1 cmd)
+612: basename; basename bla; basename $(TE=1 cmd)
+613: bc; bc -l; bc foo $(V1=1 cmd) $VAR_HERE;
+614: bg; bg $ID;
+615: cal 1 2020; cal; cal 1 $(C1=1 cmd here);
+616: cat; cat -u; cat /some/file; cat $FROM_VAR;
+617: cd -; cd /foo/bar; cd -L;
+618: chgrp; chgrp -h ${GROUP} /some/file;
+619: chmod; chmod -R 0666 /some/file; chmod -R;
+620: chown; chown -h root:root /some/file; chown -R;
+621: cksum; cksum /file; cksum ${VAR};
+622: cmp; cmp -l; cmp file1 file2;
+623: comm; comm -1 file1 file2; comm $(V=1 cmd here);
+624: command some command here; command cd $FOO;
+625: compress; compress -c file;
+626: cp; cp a b;
+627: crontab; crontab file;
+628: csplit; csplit -k file;
+629: cut; cut -d1 -f;
+630: date; date +Z;
+631: dd; dd if=bla;
+632: df; df -m;
+633: diff; diff -r ba br;
+634: du; du foo;
+635: echo; echo "$SOMETHING";
+636: ed; ed bbbb;
+637: env; env foo;
+638: ex; ex file;
+639: expand; expand foo;
+640: expr; expr $A + 1;
+641: fc; fc -l;
+642: fg; fg $ID;
+643: file; file /dev/$FILE;
+644: find; find -x $XXX;
+645: fold; fold -bs /some/file;
+646: fuser; fuser -c /some/file;
+647: getconf; getconf $VAR;
+648: getopts; getopts "$VAR";
+649: grep; grep blalba $VAR;
+650: hash; hash $FOO;
+651: head; head -n 1; head /file/$VAR;
+652: iconv; iconv -f bla -t foo;
+653: id; id -a; id $USER;
+654: ipcrm; ipcrm -q $ID;
+655: ipcs; ipcs -q $VAR;
+656: jobs; jobs -l;
+657: join; join -a $VAR;
+658: kill; kill -9
+659: link; link file $VAR;
+660: ln; ln -s /ffff $VAR;
+661: locale; locale -a $VAR;
+662: localedef; localedef -a;
+663: logger; logger -a;
+664: ls; ls -a /foo;
+665: mailx; mailx $FOO;
+666: make; make -f makefile;
+667: man; man foo;
+668: mesg; mesg --option;
+669: mkdir; mkdir -p;
+670: mkfifo; mkfifo $FOO;
+671: more; more $FOO;
+672: mv; mv -f foo bla;
+673: newgrp; newgrp -n $VAR;
+674: nice; nice -c 1;
+675: nl; nl $FOO;
+676: nm; nm $FOO;
+677: nohup; nohup test;
+678: od; od $FOO;
+679: paste; paste /from/file;
+680: patch; patch -p0 /patch/file;
+681: pathchk; pathchk $FOO;
+682: pr; pr $FOO;
+683: printf; printf -v BLA 'STRING';
+684: ps; ps -a;
+685: pwd; pwd -L;
+686: read; read -r VAR;
+687: renice; renice -a;
+688: rm; rm -rf;
+689: rmdir; rmdir /test;
+690: sed; sed -i $VAR;
+691: sh; sh -c $FOO;
+692: sort; sort $FOO;
+693: split; split $FOO;
+694: strings; strings /some/file;
+695: strip; strip $FOO;
+696: stty; stty -a;
+697: tabs; tabs -t;
+698: tail; tail -f /foo;
+699: tee; tee /foo/bar;
+700: time; time -a $VAR;
+701: touch; touch $FOO;
+702: tput; tput $FOO;
+703: tr; tr 'ff' 'bbb';
+704: tsort; tsort $FILE;
+705: type; type -p;
+706: ulimit; ulimit -t;
+707: umask; umask 0444;
+708: unalias; unalias -a;
+709: uncompress; uncompress $FOO;
+710: unexpand; unexpand $FOO;
+711: uniq; uniq --help;
+712: unlink; unlink $FILE;
+713: vi; vi $FILE;
+714: wait; wait $PID1 $PID2;
+715: wc; wc -l; wc $FILE;
+716: who; who -a; who am i;
+717: write; write $TEST;
+718: xargs; xargs $FOO $BLA;
+719: zcat; zcat $FILE;
+720:
+721:
+722: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
+723:
+724: a=1
+725: set 2
+726: echo ${a}b-$ab-${1}0-${10}-$10
+727:
+728: foo=asdf
+729: echo ${foo-bar}xyz}
+730:
+731: ${x:-$(ls)}
+732:
+733: unset X
+734: echo ${X:=abc}
+735:
+736: unset posix
+737: echo ${posix:?}
+738:
+739: set a b c
+740: echo ${3:+posix}
+741:
+742: HOME=/usr/posix
+743: echo ${#HOME}
+744:
+745: x=file.c
+746: echo ${x%.c}.o
+747:
+748: x=posix/src/std
+749: echo ${x%%/*}
+750:
+751: x=$HOME/src/cmd
+752: echo ${x#$HOME}
+753:
+754: x=/one/two/three
+755: echo ${x##*/}
+756:
+757: "${x#*}"
+758:
+759: ${x#"*"}
+760:
+761:
+762: x=100
+763: while [ $x -gt 0 ]
+764: do
+765: command
+766: x=$(($x-1))
+767: done
+768:
+769:
+770:
+771: cat <<eof1 > /some/file
+772: Hi,
+773: eof1
+774: Helene.
+775: eof2
+776:
+777: false && echo foo || echo bar
+778: true || echo foo && echo bar
+779:
+780: while
+781:
+782:
+783:
+784:
+785: date && who || ls; cat file
+786:
+787:
+788:
+789:
+790: wc file > output & true
+791:
+792:
+793: do
+794:
+795: ls
+796: cat file
+797: done
+798:
+799: for i in *
+800: do
+801: if test -d "$i"
+802: then break
+803: fi
+804: done
+805:
+806: foo() {
+807: for j in 1 2; do
+808: echo 'break 2' >/tmp/do_break
+809: echo " sourcing /tmp/do_break ($j)..."
+810:
+811:
+812: . /tmp/do_break
+813:
+814:
+815: do_continue() { continue 2; }
+816: echo " running do_continue ($j)..."
+817:
+818:
+819:
+820: do_continue
+821:
+822:
+823: trap 'continue 2' USR1
+824: echo " sending SIGUSR1 to self ($j)..."
+825:
+826:
+827:
+828: kill -s USR1 $$
+829: sleep 1
+830: done
+831: }
+832: for i in 1 2; do
+833: echo "running foo ($i)..."
+834: foo
+835: done
+836:
+837: :${X=abc}
+838: if false
+839: then :
+840: else echo $X
+841: fi
+842:
+843: x=y :>
+844:
+845: for i in *
+846: do
+847: if test -d "$i"
+848: then continue
+849: fi
+850: printf '"%s" is not a directory.\n' "$i"
+851: done
+852:
+853: cat foobar
+854: . ./foobar
+855: echo $foo $ba
+856:
+857: eval " $commands"
+858: eval " $(some_command)"
+859: foo=10 x=foo
+860: y='$'$x
+861: echo $y
+862: eval y='$'$x
+863: echo $y
+864:
+865: exec 3< readfile
+866: exec 4> writefile
+867: exec 5<&0
+868: exec 3<&-
+869: exec cat maggie
+870: foo=bar exec cmd
+871:
+872: exit 0
+873: exit 1
+874: (
+875: command1 || exit 1
+876: command2 || exit 1
+877: exec command3
+878: ) > outputfile || exit 1
+879: echo "outputfile created successfully"
+880:
+881: export X=$(false)
+882: X=$(false)
+883: export X
+884:
+885: export PWD HOME
+886: export PATH=/local/bin:$PATH
+887: export -p > temp-file
+888: unset a lot of variables
+889:
+890: set -e
+891: start() {
+892: some_server
+893: echo some_server started successfully
+894: }
+895: start || echo >&2 some_server failed
+896: set
+897: set c a b
+898: set -xv
+899: set --
+900: set -- "$x"
+901: set -- $x
+902: set -- "$@"
+903:
+904: trap "jobs -n" CLD
+905:
+906: set a b c d e
+907: shift 2
+908: echo $*
+909:
+910: save_traps=$(trap)
+911: eval "$save_traps"
+912:
+913: trap '"$HOME"/logout' EXIT
+914: trap '"$HOME"/logout' 0
+915: trap - INT QUIT TERM EXIT
+916:
+917: trap 'read foo; echo "-$foo-"' 0
+918: trap 'eval " $cmd"' 0
+919: trap " $cmd" 0
+920:
diff --git a/hrc/test/_valid/shell/test.sh.html b/hrc/test/_valid/shell/test.sh.html
new file mode 100644
index 00000000..2fd1f58e
--- /dev/null
+++ b/hrc/test/_valid/shell/test.sh.html
@@ -0,0 +1,9 @@
+0:
+1:
+2: (cd x; y/a-b.sh)
+3:
+4: echo ${#aoeu[@]}
+5:
+6: DATE=`date`
+7: echo $DATE
+8:
diff --git a/hrc/test/shell/shell-bash-spec.bash b/hrc/test/shell/shell-bash-spec.bash
new file mode 100644
index 00000000..98e4cd01
--- /dev/null
+++ b/hrc/test/shell/shell-bash-spec.bash
@@ -0,0 +1,458 @@
+#!/usr/bin/env bash
+
+# 3.1.2.4 ANSI-C Quoting
+
+$'\nfoo\e'
+A=$'\\\'\"\?no special meaning'
+CDPATH=$'octal \1 \12 \123 foo' $'octal error \9 \19 \181 foo'
+command ${CDPATH%$'test\rtest'} `in backquote $'test\1test'`
+( in subshell $'\1' )
+{ in group $'1'; }
+command $'hex \x1 \x1a \xFFnospecial meaning'
+A=$(foo $'unicode \u1 \uF1 \uFFA \udeadno special meaning')
+$'unicode \U1 \UF1 \UFFA \Udead \UDEAD1 \U12345 \U123456 \U1234567 \U12345678no special meaning'
+$'control-x \cx no cpecial meaning'
+
+# 3.1.2.5 Locale-Specific Translation
+
+$"some message"
+A=$"some message $VAR inside"
+CDPATH=$"msg $'ansi-c\\here\r'"
+command ${CDPATH%$"msg $(command)"}
+( in subshell $"msg" )
+{ in group $"msg"; }
+A=$(foo $"something $'ansi-c\t\\' ${CDPATH#$"msg"}") `in bq $"some\$th\\i\ng"`
+
+# 3.2.5.1 Looping Constructs
+# for (( expr1 ; expr2 ; expr3 )) ; do commands ; done
+
+for (( i = 0; $i < $VAR; i++ )); do
+ cmd
+done
+
+for (( i = 0; i < $VAR; i++ )); do
+ cmd
+done
+
+for (( i = 0; $i < '$NO_VAR'; i = $i + $'ansi-c' ))
+do
+ cmd
+done
+
+for (( i = "123"; $i < ${CDPATH}; i = $i / 100 )); do V1=456 command here; done
+for ((;;)); do V1=456 command here; done
+
+# 3.2.5.2 Conditional Constructs
+
+# select
+
+select var in $VAR; do
+
+done
+
+select var in; do done
+
+select VAR in "BLA" "FOO" "BAR"; do; done
+
+select VAR; do
+ command
+ if [ -n "$FOO" ]; then
+ something
+ select VAR; do
+ done
+ fi
+ select VAR; do
+ select VAR; do
+ done
+ done
+done
+
+select IFS in; do done # POSIX special variable
+select CDPATH in; do done # Bash special variable
+
+( select VAR; do done )
+{ select VAR; do done; }
+
+
+# (( ... ))
+
+(( "asd" '123' $'\r\t123' $"foo" 1 )) # test strings / numbers
+(( $(V1=1 command) `command` )) # evaluations
+(( \$ \" \' \$ )) # escapes
+(( $VAR $IFS $CDPATH )) # variables
+(( ${VAR%10} ${IFS#10} ${CDPATH%10} )) # parameter expansion
+(( i++ i-- ++IFS --CDPATH )) # increment / decrement
+(( 1 + 1 - 2 ! 1 ~ 3 ** 3 * 4 / 5 % -6 >> 10 << 20 )) # operations
+(( 1 <= 2 >= 4 < 1 > 4 == 5 != 4 & 1 ^ 5 | 8 && 10 || 20 ? 30 : 2 )) # operations
+(( a = 1 || w *= 1 || IFS /= 10 || CDPATH %= 10 || x += 10 || y -= 10 )) # assignment
+(( a <<= 10 || b >>= 30 || c &= 1 || f |= 40 )) # assignment
+
+(( 0174 + 0$VAR + 8#123 + 09874 + 8#845 )) # octal + octal var + bad octal numbers
+(( 0x12F + 0XDeaDBeEf111 + 0x$VAR + 16#411Ab + 0x1Z23 + 16#123K )) # hex + hex var + bad hex numbers
+(( 3#10 + 10#$VAR + 44#50 + 65#567 )) # any base + wrong base (65+)
+(( 2#45 + 10#45A )) # bad bin/dec bases
+
+# [[ ... ]]
+
+[[ a -f e || -f /bla || -o fofofof || -v varname || -R varname && -z "$STRING" ]]
+[[ 1 > 2 ]]
+[[ "asd" '123' $'\r\t123' $"foo" 1 ]] # test strings / numbers
+[[ $(V1=1 command) `command` ]] # evaluations
+[[ \$ \" \' \$ ]] # escapes
+[[ $VAR $IFS $CDPATH ]] # variables
+[[ ${VAR%10} ${IFS#10} ${CDPATH%10} ]] # parameter expansion
+[[ $fffj =~ [[:space:]]*(a)?b ]]
+[[ $line =~ ^"initial string" ]]
+[[ $line =~ "^initial string" ]]
+pattern='[[:space:]]*(a)?b'
+[[ $line =~ $pattern ]]
+[[ $line =~ $CDPATH ]] # special variable
+[[ 'Hello World' =~ Hello ]]
+[[ $digit =~ [0-9] ]]
+[[ $REPLY =~ ^[0-9]+$ ]] # special variable
+[[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}$ ]]
+[[ $ip =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]
+
+# 3.2.6 Coprocesses
+
+coproc CDPATH {
+ select far in; do
+ done
+} 2>/dev/null
+
+coproc name_as_variable { V=1 command here; } 2>/dev/null 1/dev/null
+
+coproc name_as_var {
+ V=1 command here
+}
+
+coproc {
+ V1=1 command here
+}
+
+# 3.3 Shell Functions
+
+func-name () command here 2>/dev/null
+
+func%name () {
+ command here
+} 2>/dev/null
+
+func-name () { command here; }
+
+,func-name-comma () { command here; }
+
+function fu1[nc]name command here 1>/dev/null
+
+function f-un[c () command here
+
+function f123 () {
+ command here
+}
+
+function func-name { command here; }
+
+function -error here;
+
+# 3.5.3 Shell Parameter Expansion
+
+${A:-word} ${BASH:-word}
+${A:=word} ${BASH:=word}
+${A:?word} ${BASH:?word}
+${A:+word} ${BASH:+word}
+
+${A:0} ${A:0:10} ${A: -1} ${A: -1:-10} ${BASH:0} ${BASH:0:10} ${BASH: -1} ${BASH: -1:-10}
+${@:7} ${@:1:2} ${*:1} ${*:1:2}
+${A:$(( ${#B} + 10 )):$(command here)} ${A:"10":$'\r\t10'}
+
+${!prefix*} ${!prefix@} ${!1@}
+
+${!name[@]} ${!name[*]}
+${!A} ${!BASH} ${!1} ${!@}
+
+${#A} ${#BASH} ${#*} ${#@}
+${A#word} ${BASH#word} ${A##word} ${BASH##word}
+${A%word} ${BASH%word} ${A%%word} ${BASH%%word}
+
+${A/pat/str} ${BASH/pat/str} ${A//pat/str} ${BASH//pat/str}
+${A/#pat/str} ${BASH/#pat/str} ${A/%pat/str} ${BASH/%pat/str}
+${A/$(command)/`test`"dbl"$'ansi'}
+
+" ${A/pat/str} ${A/$(command)/`test`"dbl"$'ansi'} " # <- in double quoted strings
+
+${A^pat} ${BASH^pat} ${A^^pat} ${BASH^^pat}
+${A,pat} ${BASH,pat} ${A,,pat} ${BASH,,pat}
+${A^$(command here)} ${BASH,,`test`"sdfasdf"$'\r\t\e'}
+
+${A@U} ${A@u} ${A@L} ${A@Q} ${A@E} ${A@P} ${A@A} ${A@K} ${A@a} ${A@k}
+${BASH@U} ${BASH@u} ${BASH@L} ${BASH@Q} ${BASH@E} ${BASH@P} ${BASH@A} ${BASH@K} ${BASH@a} ${BASH@k}
+
+for i in; do
+ "'${M:$i:1}" # <- test in for loop
+done
+
+# 5.1 Bourne Shell Variables
+
+$CDPATH $HOME $IFS $MAIL $MAILPATH $OPTARG $OPTIND $PATH $PS1 $PS2
+
+${#CDPATH}
+
+CDPATH=1 CDPATH=somestring
+
+# 3.5.6 Process Substitution
+
+command here <(V=1 command here) >(V=1 command here)
+
+command here < <(V=1 command here)
+
+# 3.6 Redirections
+
+ls > dirlist 2>&1
+ls 2>&1 > dirlist
+
+# 3.6.1 Redirecting Input
+
+command < test < $VAR
+command 2< test 1<$CDPATH
+
+# 3.6.2 Redirecting Output
+
+command >test >$VAR
+command >|test >|$VAR
+command 1>test 2>$VAR
+command 1>|test 0>|$VAR
+
+# 3.6.3 Appending Redirected Output
+
+command >>test >>$VAR
+command 2>>test 2>>$VAR
+
+# 3.6.4 Redirecting Standard Output and Standard Error
+
+command &>test >&test
+command >test 2>&1
+
+# 3.6.5 Appending Standard Output and Standard Error
+
+command &>>test
+
+# 3.6.7 Here Strings
+
+command <<< word
+command <<< $VAR
+command <<< $(V=1 command here)
+command 1<<< word
+command 1<<< "string"$'ansi''single'
+command <<< "HERE STRING"
+
+for i in; do
+ if bla; then
+ while read -r; do
+ done <<< "HERE STRING"
+ fi
+done
+
+# 3.6.8 Duplicating File Descriptors
+
+command <&1
+command 1<&1
+command 1<&$VAR
+command 1<&-
+command >&1
+command 2>&3
+command 1>&$VAR
+command 1>&-
+
+# 3.6.9 Moving File Descriptors
+
+command <&1-
+command 1<&1-
+command >&1-
+command 1>&1-
+
+# 3.6.10 Opening File Descriptors for Reading and Writing
+
+command <> test
+command 1<>test
+
+# 4.1 Bourne Shell Builtins
+
+: a b c d
+. file arg1 arg2 arg3
+break; break $VAR; break 1; break error here
+cd; cd -L -e dir
+continue; continue $VAR; continue 1; continue error here
+eval a b c d
+exec -c -a foo command a f g
+exit; exit $VAR; exit 1; exit error here
+export -fn -p VARNAME VAR="value" BASH CDPATH
+getopts optstring NAME foo rrr ooo
+hash -r -p name
+pwd; pwd -L -P
+readonly -aA VARNAME VAR="value" BASH IFS
+return; return $VAR; return 1; return error here
+shift; shift $VAR; shift 1; shift error here
+test -x foo -o $ASD
+[ -x foo -o $VAR ]
+times; times error here
+trap; trap -l -p a s df
+umask -p -S 0444
+unset -f -n -v VAR1 VAR2 $VAR_IN_VAR CDPATH BASH
+
+# 4.2 Bash Builtin Commands
+
+alias; alias -p foo=bla
+bind; bind -m aaa -f foo
+builtin; builtin umask 0444 # <- should be as a command
+caller; caller $VAR; caller 123 error here
+command -pV grep here
+declare -aA -p VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str'
+echo -neE foo
+enable -a -d fff
+help -d patt
+local -aA -p VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str'
+logout; logout $VAR; logout 1; logout error here
+mapfile -d 'f' file array
+printf -v VAR 'format' foo
+read -a -r VAR bla
+readarray -d dd -C call array
+source file; source file error here
+type -af name
+typeset -afFg VAR1 VAR2=$FOO VAR3=$(command here) VAR4="str"'str'$'str'
+ulimit; ulimit -a; ulimit -H name
+unalias; unalias -a; unalias name1 name2
+
+let a=4
+let z=a++
+let y=--b
+let result=~a
+let "result=a<<2"
+let "result=a&b"
+let i=5 result=~a "result=a<<2"
+let "myvar=7" "myvar2=4" "myvar3= myvar ^ myvar2"
+
+# 4.3.1 The Set Builtin
+
+set -a a b d
+
+# 4.3.2 The Shopt Builtin
+
+shopt -p -o opt
+
+# 5.2 Bash Variables
+
+$_ $BASH $BASHOPTS $BASHPID $BASH_ALIASES $BASH_ARGC
+$BASH_ARGV $BASH_ARGV0 $BASH_CMDS $BASH_COMMAND $BASH_COMPAT $BASH_ENV
+$BASH_EXECUTION_STRING $BASH_LINENO $BASH_LOADABLES_PATH $BASH_REMATCH
+$BASH_SOURCE $BASH_SUBSHELL $BASH_VERSINFO $BASH_VERSION $BASH_XTRACEFD
+$CHILD_MAX $COLUMNS $COMP_CWORD $COMP_LINE $COMP_POINT $COMP_TYPE $COMP_KEY
+$COMP_WORDBREAKS $COMP_WORDS $COMPREPLY $COPROC $DIRSTACK $EMACS $ENV $EPOCHREALTIME
+$EPOCHSECONDS $EUID $EXECIGNORE $FCEDIT $FIGNORE $FUNCNAME $FUNCNEST $GLOBIGNORE
+$GROUPS $histchars $HISTCMD $HISTCONTROL $HISTFILE $HISTFILESIZE $HISTIGNORE
+$HISTSIZE $HISTTIMEFORMAT $HOSTFILE $HOSTNAME $HOSTTYPE $IGNOREEOF $INPUTRC
+$INSIDE_EMACS $LANG $LC_ALL $LC_COLLATE $LC_CTYPE $LC_MESSAGES $LC_NUMERIC
+$LC_TIME $LINENO $LINES $MACHTYPE $MAILCHECK $MAPFILE $OLDPWD $OPTERR $OSTYPE
+$PIPESTATUS $POSIXLY_CORRECT $PPID $PROMPT_COMMAND $PROMPT_DIRTRIM $PS0 $PS3 $PS4
+$PWD $RANDOM $READLINE_ARGUMENT $READLINE_LINE $READLINE_MARK $READLINE_POINT
+$REPLY $SECONDS $SHELL $SHELLOPTS $SHLVL $SRANDOM $TIMEFORMAT $TMOUT $TMPDIR $UID
+
+${#BASH}
+
+BASH=1 BASH=somestring
+
+# Bash variables in for loop
+
+for CDPATH; do
+ foo
+done
+
+for CDPATH in 1 2 3; do
+ foo
+done
+
+# Bash variables in commands that take variable names
+
+export CDPATH CDPATH=123
+unset CDPATH
+
+# 6.1 Invoking Bash
+
+bash; bash -c fff
+
+# 6.7 Arrays
+
+ADD=()
+ARR=("val1" "val2" value\$one "val3" $(command here; echo \)) $'ansi-str')
+ARR+=("val1" "val2" "val3" $(command here; echo \)) $'ansi-str')
+ARR=(["foo"]="val1" [$VAR $VAR2 \] $VAR3]="val2" [$(V=1 command)]="foo" ["str"'str'$'\rstr']="str"'str'$'\rstr' )
+
+${!A[1]} ${!A["idx"]}
+
+ARR[1]="val"
+
+ARR["FOO"]="val" [sdfsdf] # '[sdfsdf]' is a command
+ARR[$IDX]="val"
+ADD[${IDX[0]}]="foo" # <- index as array element
+ADD[${#IDX[@]}]="foo" # <- index as array element
+
+echo $A["foo"] # <- here is A["foo"] is not an array, it is "$A" and '["foo"]'
+echo ${A["foo"]} # <- here is A["foo"] is an array
+
+A[$(echo bla)] # <- this should be the command 'A[bla]', not a variable/array
+A[$(echo bla)]=1 command here foo # <- this should be an array assignment and a command
+
+A[fla echo 1]=1 # assignment
+A[fla "echo]=" 1]=foo # assignment
+echo ${A[fla "echo]=" 1]} # echo the assignment
+
+# Arrays + Shell Parameter Expansion
+
+${A[foo]:-word} ${A['sdf']:=word} ${A[1]:?word} ${A[fff]:+word}
+
+${A[foo]:0} ${A[$'bla']:0:10} ${A[$(command)]: -1} ${A[10]: -1:-10}
+${A[1]:$(( ${#B} + 10 )):$(command here)} ${A[foo]:"10":$'\r\t10'}
+${A[0]:7} ${A[0]:1:10} ${A[@]:1} ${A[*]:1}
+
+${#A[foo]}
+
+${A[1]#word} ${A[foo]##word} ${A['sdf']%word} ${A[$(test)]%%word}
+
+" ${A[1]#word} ${A[foo]##word} ${A['sdf']%word} ${A[$(test)]%%word} " # <- in double quoted strings
+
+${A[10]/pat/str} ${A[foo]//pat/str} ${A["a"]/#pat/str} ${A[0]/%pat/str}
+${A[foo]/$(command)/`test`"dbl"$'ansi'}
+
+${A[10]^pat} ${A[foo]^^pat} ${A["bla bla"],pat} ${A[iii],,pat}
+${A[0]^$(command here)} ${A[1],,`test`"sdfasdf"$'\r\t\e'}
+
+${A[0]@U} ${A[1]@u} ${A[foo]@L} ${A["bla"]@Q} ${A[1]@E}
+${A[$'ansi']@P} ${A[$(command here)]@A} ${A[`command here`]@K} ${A[$VAR]@a} ${A[0]@k}
+
+# 6.8.1 Directory Stack Builtins
+
+dirs -c -l +N; dirs
+popd; popd -n
+pushd; pushd -n dir
+
+# 7.2 Job Control Builtins
+
+bg; bg 1
+fg; fg 1 error here
+jobs; jobs -l 123
+kill; kill -l 1
+wait; wait -f 10 1
+disown; disown -a id $ID
+suspend; suspend -f; suspend -f error here
+
+# 8.7 Programmable Completion Builtins
+
+compgen -o word
+complete -a name name
+compopt -o opt name
+
+# 9.2 Bash History Builtins
+
+fc; fc -e name
+history; history 1; history -c
diff --git a/hrc/test/shell/shell-posix-spec.sh b/hrc/test/shell/shell-posix-spec.sh
new file mode 100644
index 00000000..0dd01775
--- /dev/null
+++ b/hrc/test/shell/shell-posix-spec.sh
@@ -0,0 +1,920 @@
+#!/bin/sh
+
+# ------------------------------------------------------------------------
+# POSIX doc:
+
+# 2.2 Quoting
+\| \& \; \> \< \( \) \$ \` \\ \" \' no meaning
+test for no meaning for new line \
+ I_AM_NOT_VARIABLE=1 command \
+ if doesn\'t work also
+
+# 2.2.2 Single-Quotes
+'single quote string' 'escape does not \work here'
+
+# 2.2.3 Double-Quotes
+double quoted "only these chars should be escaped \$, \`, \", \\, but \nothing \! else"
+
+# 2.4 Reserved Words
+! command
+# Everything is marked as errors, except 'in'
+do elif else
+elif
+elif VAR=1 some command here >&1
+else
+in
+then
+# the following words are in their blocks:
+# case/esac if/fi for/done while/done until/done
+#
+# Special cases
+#
+# Only the first reserved word must be highlighted
+do elif else
+#
+
+# 2.5.2 Special Parameters
+$@ $* $# $? $- $$ $0
+${@} ${*} ${#} ${?} ${-} ${$} ${0}
+
+# 2.5.3 Shell Variables
+$ENV $HOME $IFS $LANG $LC_ALL $LC_COLLATE $LC_TYPE $LC_MESSAGES
+$LINENO $NLSPATH $PATH $PPID $PS1 $PS2 $PS4 $PWD
+
+$PATH_SEPARATOR # <- this is not a shell variable
+
+${ENV} ${HOME} ${IFS} ${LANG} ${LC_ALL} ${LC_COLLATE} ${LC_TYPE} ${LC_MESSAGES}
+${LINENO} ${NLSPATH} ${PATH} ${PPID} ${PS1} ${PS2} ${PS4} ${PWD}
+
+ENV=1 HOME=2 IFS=3 LANG=foo LC_ALL=bar LC_COLLATE=xxx LC_TYPE=1 LC_MESSAGES=2
+LINENO=1 NLSPATH=bla PATH=11 PPID=r PS1=x PS2=+ PS4=e PWD=5
+
+# 2.6.2 Parameter Expansion
+${ASD-fo br} ${ASD:-fo" br"} ${ASD='br bz'} ${ASD:=br \{ bo}
+${ASD?$VARH} ${ASD:?"$QVAR"} ${ASD+$(V=1 cmd re)} ${ASD:+`V=1 a here`}
+${1-foo bar} ${1:-foo" bar"} ${1='bar baz'} ${1:=bar \{ boo}
+${1?$VARHERE} ${1:?"$QVAR"} ${1+$(V=1 cmd here)} ${1:+`V=1 a here`}
+
+${#ASD} ${#1}
+
+${ASD%fo ba} ${ASD%%fo" br"} ${ASD#'bz bz'} ${ASD##br \{ bo}
+${1%$VARH} ${1%%"$QVAR"} ${1#$(V=1 cmd re)} ${1##`V=1 a here`}
+
+$ASD $1
+
+# Word break characters should not be considered as the end of
+# the parameter extension.
+
+${A%foo # bar}
+${A%foo ; command}
+${A%foo > command}
+${A%foo ) command}
+${A%foo ( command}
+${A%foo & command}
+${A%foo | command}
+
+A=123 A="sdfasdf" A=$(V=1 command here 2>/dev/null) B=`cd asd`
+A=123; cd test
+A=1|B=2|topipe command
+A=1;nextcmd
+A=1>A=1 cmd here # <- 'A=1' is not a variable assignment, it is a file
+
+# 2.6.3 Command Substitution
+exec 1 $( { V=123 V2="sdsdf"; }; execute something 2>&1 1>/dev/null && X=1 echo 123 V=1)
+exec 2 "$(V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1)"
+exec 3 `V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1`
+exec 4 "`V=123 V2="sdsdf" execute something 2>&1 1>/dev/null && X=1 echo 123 V=1`"
+
+# nested (not implemented, TODO?)
+exec 3 `V=123 V2="sdsdf" \`X=1 echo 123 V=1\` more params`
+exec 4 "`V=123 V2="sdsdf" \`X=1 echo 123 V=1\` more params`"
+
+# 2.6.4 Arithmetic Expansion
+$(( X + B << 2 * 10 / 30 + $X - $1 % "123" ))
+A=$(( X + B << 2 * 10 / 30 ))
+A="$(( X + B << 2 * 10 / 30 ))"
+
+# 2.7.1 Redirecting Input
+foo < bla
+foo 0< bla
+
+# 2.7.2 Redirecting Output
+foo > bla
+foo 2>bla
+foo 2>|bla
+
+# 2.7.3 Appending Redirected Output
+foo >> bla
+foo 2>>bla
+
+# 2.7.4 Here-Document
+Non quoted here-doc 2</dev/null),
+and $((arithmetic expansion + 1 / 10)). In this case, the in the input
+behaves as the inside double-quotes (see Double-Quotes).
+( Here we are \$, \`, \", \\, but \nothing \! else )
+However, the double-quote character ( ' )' shall not be treated specially
+within a here-document, except when the double-quote appears
+within "$()", "``", or "${}". (WTF?!)
+BLA
+
+Quoted here-doc <<-"FOO"
+If any part of word is quoted, the delimiter shall be formed by performing
+quote removal on word, and the here-document lines $shall not be $(expanded).
+FOO
+
+Single-quoted here-doc <<'FOO'
+not $expanded
+FOO
+
+heredoc after redirection >foobar << BLA
+with space before label
+BLA
+
+# 2.7.5 Duplicating an Input File Descriptor
+1<&2 <&-
+
+# 2.7.6 Duplicating an Output File Descriptor
+1>&2 2>&-
+
+# 2.7.7 Open File Descriptors for Reading and Writing
+<>/blabla 1<> /blabla
+
+# 2.9.1 Simple Commands / Command Search and Execution / builtin
+# The command must be on the first place
+alias foo=bla
+bg alias cd
+cd command A1=11
+DEFINE_VAR=1 command
+false
+DEFINEVAR=2 command cd alias >/dev/null
+DEFVAR=1 fc 1>&1
+fg
+getopts more parameters here
+hash THIS_IS_PARAMETER_BUT_NOT_VARIABLE=1
+jobs
+kill
+newgrp
+pwd
+read
+true
+umask
+unalias
+wait while do for in
+#
+# Special cases:
+#
+# Only the first buildin command must be highlighted
+alias bg cd hash
+# variables after buildin command must not be highlighted as are plain parameters
+# however, variables after reserved words must be highlighted
+alias VAR1=1
+# reserved words must not be highlighted after builtin command
+command while something; command
+
+# 2.9.2 Pipelines
+VAR1=1 foo bla | VAR=2 ! test cmd # exclamation mark is NOT highlighted
+
+# 2.9.3 Lists
+VAR1=1 foo bla && ! VAR=2 test cmd || VAR=3 command read # exclamation mark is highlighted
+VAR=1 foo & && VAR=2 test cmd
+R=1 date && V=1 who || VAR=1 ls; VAR=2 cat file
+V=1 wc file > output & R=1 true
+# Asynchronous Lists
+V=1 background1 & V=2 background2
+# Sequential Lists
+V=1 command1; V=2 command2
+
+# 2.9.4 Compound Commands
+( V1=1 grouped command1; V=1 command2 )
+(
+ V1=1 command1 here
+ V2=2 command2
+ (
+ V2= nested
+ {
+ V3=1 nested
+ }
+ )
+)
+( V1=1 command1
+V2=2 command2 \) )
+
+{ V1=1 group 1; V1= command2 here should be an error here because of the missing semicolon }
+} # this one works
+{ cmd1; cmd2; no error here; }
+{
+ cmd1
+ V1=cmd1
+ {
+ nested
+ \}
+ }
+}
+
+if
+fi # <- error here, there is no 'then'
+then
+fi # <- close the above 'if'
+
+# The for Loop
+
+for IFS in 1 2 3 # comment here
+do
+done
+
+for IFS in $(V1=val command) 2 3; do command; done; # check special variable
+for "IFS" in $(V1=val command) 2 3; do command; done; # check variable in quotes
+
+for var in $VAR; do
+
+done
+
+for var in; error here do done
+do
+done
+
+for var in; error here; do done
+
+for var in; do done
+
+for VAR in "BLA" "FOO" "BAR"; do; done
+
+for VAR # comment here
+do
+done
+
+for $(V1=val command here); do
+ command
+done
+
+for VAR error here; do
+done
+
+for VAR; do
+ command
+ if [ -n "$FOO" ]; then
+ something
+ fi
+done
+
+for IFS; do command; done; # check special variable
+
+for "IFS"; do command; done; # variable in quotes <- 'in' word must not activate the 'in' syntax for form
+for "IFS"; do command; done; # variable _in quotes
+
+# Case Conditional Construct
+
+case $FOO in
+a aaaaa pat1) A=1 xdo; A=2 something ;;
+ pat2|fff\) BLA=123) B=2;;
+ pat3)
+ A=x cmd;;
+ pat4)
+ B=1 cmd
+ C=3 cmd1
+ if [ -x "$BLA" ]; then
+ ffff
+ case $BLA in
+ fff) F=1;;
+ bla) no the last ";;" here
+ esac
+ fi
+ ;;
+here pat) T=1 ttt;;
+ $VAR_HERE) cmd;;
+ $(V1=1 some command here)) cmd2;;
+ *) bla
+ fooo
+ ;;
+esac
+
+# The if Conditional Construct
+
+if foo; then
+ C=1 cmd here 2>/dev/null
+fi
+
+if [ $BLABLA -gt 1 ]; then VAR=HERE cd blalbla; fi
+
+if [ -x "$N" ]; then
+ alias skdfjlkj
+elif V=1 some command here; then
+ V1=1 anything here
+ blalba
+elif [ -t -o 1 -x ]; then
+ X=1 ffff
+else
+ command here
+fi
+
+if [ $BLABLA != "123" ]; then
+ X=1 somecmd sfasfasd sfsfasdf afa sdf sdf;
+ if foo; then
+ cd sdfkjkjfkj
+ fi
+fi
+
+if V=1 command here
+then
+ V1=2 we do something
+ if nested; then
+ nothing to do
+ fi
+fi
+
+# The while Loop
+
+while true; do
+ something
+done
+
+while [ -x "$BLA" ]; do something here; done
+while [ -x "FOO" ]; do while bla; do nothing; done; done
+
+while x 2>&1; do
+ while nested; do
+ nothing
+ done
+done
+
+# The until Loop
+
+until true; do
+ something
+done
+
+until [ -x "$BLA" ]; do something here; done
+
+until x 2>&1; do
+ while nested; do
+ until [ -x nested ]; do
+ nothing
+ done
+ done
+done
+
+# 2.9.5 Function Definition Command
+
+somefn() sfkjskdfj;
+no fn here
+
+somefn () {
+ still fn
+ bla
+ fnd2() {
+ another fn
+ }
+}
+
+somefn()
+
+errorfn() { blalbla }
+close the curved bracket from above; }
+
+func( ) cmd function with space between brackets
+func ( ) cmd function with space between brackets#2
+
+# 2.14. Special Built-In Utilities
+
+# NAME
+# break - exit from for, while, or until loop
+# SYNOPSIS
+# break [n]
+
+break
+break; break; break
+break 10
+break "$VAR"; break '123'
+break a10 # <- errors here
+break; break 10; break error here; break 1; # the last is ok
+break error here
+break; # this is ok
+break $SOMEVAR but error here
+break $(V=1 eval something here) but error here
+
+# NAME
+# colon - null utility
+# SYNOPSIS
+# : [argument...]
+
+:
+: highlight only $VAR here and $(V=1 evaluations)
+
+# NAME
+# continue - continue for, while, or until loop
+# SYNOPSIS
+# continue [n]
+
+continue
+continue; continue; continue 10 20 # second parameter is an error
+continue 10
+continue a10 # <- errors here
+continue; continue 10; continue error here; continue 1; # the last is ok
+continue error here
+continue; # this is ok
+continue $SOMEVAR but error here
+continue $(V=1 eval something here) but error here
+
+# NAME
+# dot - execute commands in the current environment
+# SYNOPSIS
+# . file
+
+. file; . tttt
+. file 2>/dev/null error here;
+. file; . file $VAR error here; command next here
+. file; . file error here # comment here
+
+# NAME
+# eval - construct command by concatenating arguments
+# SYNOPSIS
+# eval [argument...]
+
+eval "something" 2>/dev/null
+eval "something"
+eval "one" "two" $(V1=1 cmd3 >/dev/null)
+eval; V=1 another command here
+eval ; V=1 another command here
+eval # comment here
+
+# NAME
+# exec - execute commands and open, close, or copy file descriptors
+# SYNOPSIS
+# exec [command [argument...]]
+
+exec command is not highlighted as buildin 1>/dev/null
+exec; V1=1 command here
+exec ; V1=1 command here too
+exec 3< readfile
+exec 4> writefile
+exec 5<&0
+exec 3<&-
+foo=bar exec cmd
+
+# NAME
+# exit - cause the shell to exit
+# SYNOPSIS
+# exit [n]
+
+exit
+exit; exit; exit
+exit 10
+exit a10 # <- errors here
+exit; exit 10; exit error here; exit 1; # the last is ok
+exit error here
+exit; # this is ok
+exit $SOMEVAR but error here
+exit $(V=1 eval something here) but error here
+
+# NAME
+# export - set the export attribute for variables
+# SYNOPSIS
+# export name[=word]...
+# export -p
+
+export ; export VAR FOO BLA=1 PATH $IFS PATH=123 -wrong variable name
+export X="fff" R="$(V=1 cmd here)" $VAR_ALSO 'quoted' 1wrong variable name
+export -p; export only; #comment here
+export -p a # <- error here
+export -p error here; export VAR one two
+export X=$(false)
+
+# NAME
+# readonly - set the readonly attribute for variables
+# SYNOPSIS
+# readonly name[=word]...
+# readonly -p
+
+readonly
+readonly 1>/a123 FFF # <- error here
+readonly DFF 1>/b123
+readonly; readonly VAR FOO BLA=1 PATH $IFS PATH=123 -wrong variable name
+readonly X="fff" R="$(V=1 cmd here)" $VAR_ALSO 'quoted' 1wrong variable name
+readonly -p; readonly only; #comment here
+readonly -p a # comment here
+readonly -p error here; readonly VAR one two
+readonly X=$(false)
+
+# NAME
+# return - return from a function or dot script
+# SYNOPSIS
+# return [n]
+
+return
+return 2>/dev/null error here
+return 10 2>/dev/null error here
+return; return; return
+return 10
+return a10 <- errors here
+return; return 10; return error here; return 1; # the last is ok
+return error here
+return; # this is ok
+return $SOMEVAR but error here
+return $(V=1 eval something here) but error here
+
+# NAME
+# set - set or unset options and positional parameters
+# SYNOPSIS
+# set [-abCefhmnuvx] [-o option] [argument...]
+# set [+abCefhmnuvx] [+o option] [argument...]
+# set -- [argument...]
+# set -o
+# set +o
+
+set
+set; set +a 1>/dev/null
+set -o option $(cmd here); set -- "$VAR"
+set -o
+set +o
+
+# NAME
+# shift - shift positional parameters
+# SYNOPSIS
+# shift [n]
+
+shift
+shift 2>/dev/null error here
+shift; shift; shift
+shift 10
+shift a10 <- errors here
+shift; shift 10; shift error here; shift 1; # the last is ok
+shift error here
+shift; # this is ok
+shift $SOMEVAR but error here
+shift $(V=1 eval something here) but error here
+
+# NAME
+# times - write process times
+# SYNOPSIS
+# times
+
+times; times error here; #comment here
+times aaa # comment here
+times error here; times 2>/dev/null sdfsdfasf
+
+# NAME
+# trap - trap signals
+# SYNOPSIS
+# trap n [condition...]
+# trap [action condition...]
+
+trap 1 SIG1 SIG2 $SIG_AS_VARIABLE $(command here)
+trap "some sction" SIG1 SIG2 2>/dev/null; V=1 the next command here
+trap 1 1>/dev/null
+
+# NAME
+# unset - unset values and attributes of variables and functions
+# SYNOPSIS
+# unset [-fv] name...
+
+unset -x; #<- error here
+unset;
+unset -f; unset -v; unset -fv; unset -vf
+unset -f VAR VAR2; unset -v VAR VAR2; unset -vf VAR VAR ERR_HERE=1
+unset VAR VAR2 IFS VAR3 $(V=1 cmd here) "quote" 'single' 2>/dev/null
+unset VAR=234 FFFgger; # <- error here, no assignments
+
+# 4. Utilities
+
+# Special cases
+
+test -x /some/file -o -n "$BLABLA" && test -n "$VAR"
+
+batch; batch error hereas; batch $(AGAIN ERROR) fasdf # comment here
+
+false; false error here; #comment
+
+true; true error here; #comment
+
+logname; logname error here; #comment
+
+sleep; sleep 10; sleep $VAR; sleep a10 # <- error here
+
+tty; tty error here; #comment
+
+dirname; dirname $A; dirname test error here ;# comment
+dirname $VAR error here; dirname foo
+
+uname; uname -a; #comment here
+uname -a error here
+
+# Common cases
+
+alias;
+alias name; alias name='string' # comment here
+alias name=$FOO; # comment here
+ar -x; ar -r; #comment here
+ar
+ar; ar -p
+at -l -1 bla; at; at -m '10' $(V1=1 cmd run)
+awk; awk -F bla; awk $(TE=1 cmd) # comment here
+basename; basename bla; basename $(TE=1 cmd) # comment here
+bc; bc -l; bc foo $(V1=1 cmd) $VAR_HERE; # comment
+bg; bg $ID; #comment here
+cal 1 2020; cal; cal 1 $(C1=1 cmd here); #comment
+cat; cat -u; cat /some/file; cat $FROM_VAR; # comment
+cd -; cd /foo/bar; cd -L; # comment
+chgrp; chgrp -h ${GROUP} /some/file; # comment
+chmod; chmod -R 0666 /some/file; chmod -R; # comment
+chown; chown -h root:root /some/file; chown -R; # comment
+cksum; cksum /file; cksum ${VAR}; # comment
+cmp; cmp -l; cmp file1 file2; # comment
+comm; comm -1 file1 file2; comm $(V=1 cmd here); # comment
+command some command here; command cd $FOO; #comment
+compress; compress -c file; #comment
+cp; cp a b; #comment
+crontab; crontab file; #comment
+csplit; csplit -k file; #comment
+cut; cut -d1 -f; #comment
+date; date +Z; # comment
+dd; dd if=bla; #comment
+df; df -m; # comment
+diff; diff -r ba br; #comment
+du; du foo; # comment
+echo; echo "$SOMETHING"; #comment here
+ed; ed bbbb; # comment
+env; env foo; #comment
+ex; ex file; #comment
+expand; expand foo; #comment
+expr; expr $A + 1; #comment
+fc; fc -l; #comment here
+fg; fg $ID; #comment here
+file; file /dev/$FILE; #comment
+find; find -x $XXX; #comment
+fold; fold -bs /some/file; #comment
+fuser; fuser -c /some/file; #comment
+getconf; getconf $VAR; #comment
+getopts; getopts "$VAR"; #comment
+grep; grep blalba $VAR; #comment
+hash; hash $FOO; #comment
+head; head -n 1; head /file/$VAR; #comment
+iconv; iconv -f bla -t foo; #comment
+id; id -a; id $USER; #comment
+ipcrm; ipcrm -q $ID; #comment
+ipcs; ipcs -q $VAR; #comment
+jobs; jobs -l; #comment
+join; join -a $VAR; #comment
+kill; kill -9 #ID; #comment
+link; link file $VAR; #comment
+ln; ln -s /ffff $VAR; #comment
+locale; locale -a $VAR; #comment
+localedef; localedef -a; #comment
+logger; logger -a; #comment
+ls; ls -a /foo; #comment here
+mailx; mailx $FOO; #comment here
+make; make -f makefile; # comment here
+man; man foo; #comment here
+mesg; mesg --option; #comment here
+mkdir; mkdir -p; #comment here
+mkfifo; mkfifo $FOO; #comment here
+more; more $FOO; #comment here
+mv; mv -f foo bla; #comment here
+newgrp; newgrp -n $VAR; #comment here
+nice; nice -c 1; #comment here
+nl; nl $FOO; # comment here
+nm; nm $FOO; #comment here
+nohup; nohup test; #comment here
+od; od $FOO; # comment here
+paste; paste /from/file; #comment here
+patch; patch -p0 /patch/file; #comment here
+pathchk; pathchk $FOO; #comment here
+pr; pr $FOO; #comment here
+printf; printf -v BLA 'STRING'; #comment here
+ps; ps -a; #comment here
+pwd; pwd -L; #comment here
+read; read -r VAR; #comment here
+renice; renice -a; #comment here
+rm; rm -rf; #comment here
+rmdir; rmdir /test; #comment here
+sed; sed -i $VAR; #comment here
+sh; sh -c $FOO; #comment here
+sort; sort $FOO; #comment here
+split; split $FOO; #comment here
+strings; strings /some/file; #comment here
+strip; strip $FOO; #comment here
+stty; stty -a; #comment here
+tabs; tabs -t; #comment here
+tail; tail -f /foo; #comment here
+tee; tee /foo/bar; #comment here
+time; time -a $VAR; #comment here
+touch; touch $FOO; #comment here
+tput; tput $FOO; #comment here
+tr; tr 'ff' 'bbb'; #comment here
+tsort; tsort $FILE; #comment here
+type; type -p; #comment here
+ulimit; ulimit -t; #comment here
+umask; umask 0444; #comment here
+unalias; unalias -a; #comment here
+uncompress; uncompress $FOO; #comment here
+unexpand; unexpand $FOO; #comment here
+uniq; uniq --help; #comment here
+unlink; unlink $FILE; #comment here
+vi; vi $FILE; #comment here
+wait; wait $PID1 $PID2; #comment here
+wc; wc -l; wc $FILE; #comment here
+who; who -a; who am i; #comment here
+write; write $TEST; #comment here
+xargs; xargs $FOO $BLA; #comment here
+zcat; zcat $FILE; #comment here
+
+# The usual chunks of code from:
+# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
+
+a=1
+set 2
+echo ${a}b-$ab-${1}0-${10}-$10
+
+foo=asdf
+echo ${foo-bar}xyz}
+
+${x:-$(ls)}
+
+unset X
+echo ${X:=abc}
+
+unset posix
+echo ${posix:?}
+
+set a b c
+echo ${3:+posix}
+
+HOME=/usr/posix
+echo ${#HOME}
+
+x=file.c
+echo ${x%.c}.o
+
+x=posix/src/std
+echo ${x%%/*}
+
+x=$HOME/src/cmd
+echo ${x#$HOME}
+
+x=/one/two/three
+echo ${x##*/}
+
+"${x#*}"
+
+${x#"*"}
+
+# repeat a command 100 times
+x=100
+while [ $x -gt 0 ]
+do
+ command
+ x=$(($x-1))
+done
+
+# nested heredocs are not supported
+#cat < /some/file
+Hi,
+eof1
+Helene.
+eof2
+
+false && echo foo || echo bar
+true || echo foo && echo bar
+
+while
+ # a couple of s
+
+
+ # a list
+ date && who || ls; cat file
+ # a couple of s
+
+
+ # another list
+ wc file > output & true
+
+
+do
+ # 2 lists
+ ls
+ cat file
+done
+
+for i in *
+do
+ if test -d "$i"
+ then break
+ fi
+done
+
+foo() {
+ for j in 1 2; do
+ echo 'break 2' >/tmp/do_break
+ echo " sourcing /tmp/do_break ($j)..."
+ # the behavior of the break from running the following command
+ # results in unspecified behavior:
+ . /tmp/do_break
+
+
+ do_continue() { continue 2; }
+ echo " running do_continue ($j)..."
+ # the behavior of the continue in the following function call
+ # results in unspecified behavior (if execution reaches this
+ # point):
+ do_continue
+
+
+ trap 'continue 2' USR1
+ echo " sending SIGUSR1 to self ($j)..."
+ # the behavior of the continue in the trap invoked from the
+ # following signal results in unspecified behavior (if
+ # execution reaches this point):
+ kill -s USR1 $$
+ sleep 1
+ done
+}
+for i in 1 2; do
+ echo "running foo ($i)..."
+ foo
+done
+
+: ${X=abc}
+if false
+then :
+else echo $X
+fi
+
+x=y : > z
+
+for i in *
+do
+ if test -d "$i"
+ then continue
+ fi
+ printf '"%s" is not a directory.\n' "$i"
+done
+
+cat foobar
+. ./foobar
+echo $foo $ba
+
+eval " $commands"
+eval " $(some_command)"
+foo=10 x=foo
+y='$'$x
+echo $y
+eval y='$'$x
+echo $y
+
+exec 3< readfile
+exec 4> writefile
+exec 5<&0
+exec 3<&-
+exec cat maggie
+foo=bar exec cmd
+
+exit 0
+exit 1
+(
+ command1 || exit 1
+ command2 || exit 1
+ exec command3
+) > outputfile || exit 1
+echo "outputfile created successfully"
+
+export X=$(false)
+X=$(false)
+export X
+
+export PWD HOME
+export PATH=/local/bin:$PATH
+export -p > temp-file
+unset a lot of variables
+
+set -e
+start() {
+ some_server
+ echo some_server started successfully
+}
+start || echo >&2 some_server failed
+set
+set c a b
+set -xv
+set --
+set -- "$x"
+set -- $x
+set -- "$@"
+
+trap "jobs -n" CLD
+
+set a b c d e
+shift 2
+echo $*
+
+save_traps=$(trap)
+eval "$save_traps"
+
+trap '"$HOME"/logout' EXIT
+trap '"$HOME"/logout' 0
+trap - INT QUIT TERM EXIT
+
+trap 'read foo; echo "-$foo-"' 0
+trap 'eval " $cmd"' 0
+trap " $cmd" 0
diff --git a/hrc/test/other/test.sh b/hrc/test/shell/test.sh
similarity index 100%
rename from hrc/test/other/test.sh
rename to hrc/test/shell/test.sh