tenseleyflow/bensch / 5356b21

Browse files

replace FORTSH_BIN with SHELL_BIN across all shell scripts

39 files updated. SHELL_BIN is now required (no default path).
Scripts that previously defaulted to ../bin/fortsh now error
with "SHELL_BIN must be set" if the variable is unset.
Authored by espadonne
SHA
5356b218f416741ddfc65b0f627621d766131d19
Parents
d97abf7
Tree
e66be13

40 changed files

StatusFile+-
M suites/builtins/integration/run_integration_tests.sh 5 5
M suites/builtins/integration/test_int_builtin_cross.sh 2 2
M suites/builtins/integration/test_int_control_flow.sh 2 2
M suites/builtins/integration/test_int_error_handling.sh 2 2
M suites/builtins/integration/test_int_expansion.sh 2 2
M suites/builtins/integration/test_int_function.sh 2 2
M suites/builtins/integration/test_int_job_control.sh 3 3
M suites/builtins/integration/test_int_pipeline.sh 3 3
M suites/builtins/integration/test_int_redirection.sh 2 2
M suites/builtins/integration/test_int_scope_env.sh 2 2
M suites/builtins/integration/test_int_signal_trap.sh 2 2
M suites/builtins/integration/test_int_subshell.sh 2 2
M suites/builtins/run_builtin_tests.sh 5 5
M suites/posix/posix_compliance_advanced.sh 6 6
M suites/posix/posix_compliance_builtins.sh 58 58
M suites/posix/posix_compliance_charclass.sh 33 33
M suites/posix/posix_compliance_control.sh 132 132
M suites/posix/posix_compliance_coverage.sh 8 8
M suites/posix/posix_compliance_extended.sh 6 6
M suites/posix/posix_compliance_filetest.sh 124 124
M suites/posix/posix_compliance_gaps.sh 7 7
M suites/posix/posix_compliance_heredoc.sh 81 81
M suites/posix/posix_compliance_jobcontrol.sh 8 8
M suites/posix/posix_compliance_options.sh 133 133
M suites/posix/posix_compliance_printf.sh 45 45
M suites/posix/posix_compliance_quoting.sh 106 106
M suites/posix/posix_compliance_redirect.sh 87 87
M suites/posix/posix_compliance_special.sh 142 142
M suites/posix/posix_compliance_test.sh 7 7
M suites/posix/posix_compliance_untested.sh 8 8
M suites/posix/posix_gaps_arithmetic.sh 6 6
M suites/posix/posix_gaps_builtins.sh 7 7
M suites/posix/posix_gaps_charclass.sh 5 5
M suites/posix/posix_gaps_control.sh 6 6
M suites/posix/posix_gaps_heredoc.sh 6 6
M suites/posix/posix_gaps_quoting.sh 5 5
M suites/posix/posix_gaps_redirect.sh 6 6
M suites/posix/posix_gaps_special.sh 5 5
M suites/posix/run_posix_tests.sh 7 7
M suites/test_harness.sh 1 1
suites/builtins/integration/run_integration_tests.shmodified
@@ -44,12 +44,12 @@ for arg in "$@"; do
4444
 done
4545
 
4646
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
47
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
48
-export FORTSH_BIN
47
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
48
+export SHELL_BIN
4949
 
50
-if [ ! -x "$FORTSH_BIN" ]; then
51
-    printf "${RED}ERROR${NC}: fortsh binary not found at %s\n" "$FORTSH_BIN"
52
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
50
+if [ ! -x "$SHELL_BIN" ]; then
51
+    printf "${RED}ERROR${NC}: shell binary not found at %s\n" "$SHELL_BIN"
52
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
5353
     exit 1
5454
 fi
5555
 
suites/builtins/integration/test_int_builtin_cross.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-builtin-cross]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: builtin-to-builtin interactions
suites/builtins/integration/test_int_control_flow.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-control-flow]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: builtins in loops, conditionals, and control flow
suites/builtins/integration/test_int_error_handling.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-error-handling]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: error handling with set -e, pipefail, and error propagation
suites/builtins/integration/test_int_expansion.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-expansion]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: builtins with parameter, arithmetic, and command substitution
suites/builtins/integration/test_int_function.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-function]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: builtins in/with functions
suites/builtins/integration/test_int_job_control.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-job-control]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: job control, background processes, wait, kill
@@ -18,7 +18,7 @@ compare_output "background false status" 'false & wait $!; echo $?'
1818
 # Output order of concurrent background jobs is non-deterministic — sort to normalize
1919
 TEST_NUM=$((TEST_NUM + 1))
2020
 _jc_expected=$(run_with_timeout "$TEST_TIMEOUT" "$BASH_REF" -c 'echo a & echo b & wait; echo done' 2>&1 | sort)
21
-_jc_actual=$(run_with_timeout "$TEST_TIMEOUT" "$FORTSH_BIN" -c 'echo a & echo b & wait; echo done' 2>&1 | sort)
21
+_jc_actual=$(run_with_timeout "$TEST_TIMEOUT" "$SHELL_BIN" -c 'echo a & echo b & wait; echo done' 2>&1 | sort)
2222
 if [ "$_jc_expected" = "$_jc_actual" ]; then pass "multiple background wait all"
2323
 else fail "multiple background wait all" "$_jc_expected" "$_jc_actual"; fi
2424
 compare_output "background dollar-bang" 'sleep 0.01 & [ -n "$!" ] && echo has_pid'
suites/builtins/integration/test_int_pipeline.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-pipeline]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: builtins interacting with pipelines
@@ -50,7 +50,7 @@ compare_output "cd in pipeline doesnt affect parent" 'cd /tmp | cat; pwd'
5050
 # Filter out non-deterministic "Broken pipe" errors from comparison
5151
 TEST_NUM=$((TEST_NUM + 1))
5252
 _pp_expected=$(run_with_timeout "$TEST_TIMEOUT" "$BASH_REF" -c 'echo test | { export PVAR=pipe; echo $PVAR; }; echo ${PVAR:-unset}' 2>&1 | grep -v 'Broken pipe')
53
-_pp_actual=$(run_with_timeout "$TEST_TIMEOUT" "$FORTSH_BIN" -c 'echo test | { export PVAR=pipe; echo $PVAR; }; echo ${PVAR:-unset}' 2>&1 | grep -v 'Broken pipe')
53
+_pp_actual=$(run_with_timeout "$TEST_TIMEOUT" "$SHELL_BIN" -c 'echo test | { export PVAR=pipe; echo $PVAR; }; echo ${PVAR:-unset}' 2>&1 | grep -v 'Broken pipe')
5454
 if [ "$_pp_expected" = "$_pp_actual" ]; then pass "export in pipeline segment"
5555
 else fail "export in pipeline segment" "$_pp_expected" "$_pp_actual"; fi
5656
 compare_output "cmd sub in pipeline" 'echo "$(echo hello)" | tr h H'
suites/builtins/integration/test_int_redirection.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-redirection]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: builtins with I/O redirections
suites/builtins/integration/test_int_scope_env.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-scope-env]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: variable scope, export, source, environment inheritance
suites/builtins/integration/test_int_signal_trap.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-signal-trap]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: traps and signal handling
suites/builtins/integration/test_int_subshell.shmodified
@@ -1,8 +1,8 @@
11
 #!/bin/sh
22
 TEST_PREFIX="[int-subshell]"
33
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
4
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../../bin/fortsh}"
5
-export FORTSH_BIN
4
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
5
+export SHELL_BIN
66
 . "$SCRIPT_DIR/../test_harness.sh"
77
 
88
 # Integration tests: builtins in subshells
suites/builtins/run_builtin_tests.shmodified
@@ -45,12 +45,12 @@ for arg in "$@"; do
4545
 done
4646
 
4747
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
48
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../../bin/fortsh}"
49
-export FORTSH_BIN
48
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
49
+export SHELL_BIN
5050
 
51
-if [ ! -x "$FORTSH_BIN" ]; then
52
-    printf "${RED}ERROR${NC}: fortsh binary not found at %s\n" "$FORTSH_BIN"
53
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
51
+if [ ! -x "$SHELL_BIN" ]; then
52
+    printf "${RED}ERROR${NC}: shell binary not found at %s\n" "$SHELL_BIN"
53
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
5454
     exit 1
5555
 fi
5656
 
suites/posix/posix_compliance_advanced.shmodified
@@ -35,13 +35,13 @@ FAILED_TESTS_LIST=""
3535
 
3636
 # Get script directory (POSIX way)
3737
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
38
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
38
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
3939
 BASH_REF="${BASH_REF:-bash}"
4040
 
4141
 # Check if fortsh exists
42
-if [ ! -x "$FORTSH_BIN" ]; then
43
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
44
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
42
+if [ ! -x "$SHELL_BIN" ]; then
43
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
44
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
4545
     exit 1
4646
 fi
4747
 
@@ -98,7 +98,7 @@ compare_posix_output() {
9898
     "$BASH_REF" -c "$command" 2>&1 | normalize_output > "$posix_file" || true
9999
 
100100
     # Run in fortsh
101
-    "$FORTSH_BIN" -c "$command" 2>&1 | normalize_output > "$fortsh_file" || true
101
+    "$SHELL_BIN" -c "$command" 2>&1 | normalize_output > "$fortsh_file" || true
102102
 
103103
     # Compare outputs
104104
     if diff -q "$posix_file" "$fortsh_file" > /dev/null 2>&1; then
@@ -118,7 +118,7 @@ compare_posix_exit_code() {
118118
     "$BASH_REF" -c "$command" > /dev/null 2>&1
119119
     posix_exit=$?
120120
 
121
-    "$FORTSH_BIN" -c "$command" > /dev/null 2>&1
121
+    "$SHELL_BIN" -c "$command" > /dev/null 2>&1
122122
     fortsh_exit=$?
123123
 
124124
     if [ "$posix_exit" -eq "$fortsh_exit" ]; then
suites/posix/posix_compliance_builtins.shmodified
@@ -7,7 +7,7 @@
77
 # ==============================================================================
88
 
99
 # Configuration
10
-FORTSH_BIN="${FORTSH_BIN:-./bin/fortsh}"
10
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
1111
 VERBOSE="${VERBOSE:-0}"
1212
 
1313
 # Test identification
@@ -66,7 +66,7 @@ test_p0_readonly_enforcement() {
6666
     section "P0-1: readonly Variable Enforcement"
6767
 
6868
     # Test 1: Cannot modify readonly variable
69
-    output=$($FORTSH_BIN -c 'readonly VAR=test; VAR=other' 2>&1)
69
+    output=$($SHELL_BIN -c 'readonly VAR=test; VAR=other' 2>&1)
7070
     if echo "$output" | grep -q "readonly variable"; then
7171
         pass "P0-1.1: Readonly violation produces error message"
7272
     else
@@ -74,7 +74,7 @@ test_p0_readonly_enforcement() {
7474
     fi
7575
 
7676
     # Test 2: Exit code is 1 for readonly violation (bash compatibility)
77
-    $FORTSH_BIN -c 'readonly VAR=test; VAR=other' >/dev/null 2>&1
77
+    $SHELL_BIN -c 'readonly VAR=test; VAR=other' >/dev/null 2>&1
7878
     if [ $? -eq 1 ]; then
7979
         pass "P0-1.2: Readonly violation returns exit code 1"
8080
     else
@@ -82,7 +82,7 @@ test_p0_readonly_enforcement() {
8282
     fi
8383
 
8484
     # Test 3: Command after readonly violation should not execute
85
-    output=$($FORTSH_BIN -c 'readonly VAR=test; VAR=other; echo SHOULD_NOT_PRINT' 2>&1)
85
+    output=$($SHELL_BIN -c 'readonly VAR=test; VAR=other; echo SHOULD_NOT_PRINT' 2>&1)
8686
     if ! echo "$output" | grep -q "SHOULD_NOT_PRINT"; then
8787
         pass "P0-1.3: Commands after readonly violation do not execute"
8888
     else
@@ -95,7 +95,7 @@ test_p0_readonly_enforcement() {
9595
     # Value preservation is implicitly tested by P0-1.1 (error occurs) and P0-1.3 (execution stops).
9696
 
9797
     # Test 5: Multiple readonly violations
98
-    $FORTSH_BIN -c 'readonly A=1; readonly B=2; A=x; B=y' >/dev/null 2>&1
98
+    $SHELL_BIN -c 'readonly A=1; readonly B=2; A=x; B=y' >/dev/null 2>&1
9999
     if [ $? -eq 1 ]; then
100100
         pass "P0-1.5: Multiple readonly violations handled correctly"
101101
     else
@@ -107,7 +107,7 @@ test_p0_set_u() {
107107
     section "P0-2: set -u (nounset option)"
108108
 
109109
     # Test 1: Undefined variable in parameter expansion
110
-    output=$($FORTSH_BIN -c 'set -u; echo ${UNDEFINED_VAR}' 2>&1)
110
+    output=$($SHELL_BIN -c 'set -u; echo ${UNDEFINED_VAR}' 2>&1)
111111
     if echo "$output" | grep -q "unbound variable"; then
112112
         pass "P0-2.1: set -u detects undefined variable in \${VAR}"
113113
     else
@@ -115,7 +115,7 @@ test_p0_set_u() {
115115
     fi
116116
 
117117
     # Test 2: Undefined variable in simple expansion
118
-    output=$($FORTSH_BIN -c 'set -u; echo $UNDEFINED_SIMPLE' 2>&1)
118
+    output=$($SHELL_BIN -c 'set -u; echo $UNDEFINED_SIMPLE' 2>&1)
119119
     if echo "$output" | grep -q "unbound variable"; then
120120
         pass "P0-2.2: set -u detects undefined variable in \$VAR"
121121
     else
@@ -124,9 +124,9 @@ test_p0_set_u() {
124124
 
125125
     # Test 3: Non-interactive shell exits on unbound variable
126126
     # Bash uses exit code 127 for expansion errors (matching bash behavior)
127
-    $FORTSH_BIN -c 'set -u; echo $UNDEF; echo SHOULD_NOT_PRINT' >/dev/null 2>&1
127
+    $SHELL_BIN -c 'set -u; echo $UNDEF; echo SHOULD_NOT_PRINT' >/dev/null 2>&1
128128
     exit_code=$?
129
-    output=$($FORTSH_BIN -c 'set -u; echo $UNDEF; echo SHOULD_NOT_PRINT' 2>&1)
129
+    output=$($SHELL_BIN -c 'set -u; echo $UNDEF; echo SHOULD_NOT_PRINT' 2>&1)
130130
     if [ $exit_code -eq 127 ] && ! echo "$output" | grep -q "SHOULD_NOT_PRINT"; then
131131
         pass "P0-2.3: Non-interactive shell exits on unbound variable"
132132
     else
@@ -134,7 +134,7 @@ test_p0_set_u() {
134134
     fi
135135
 
136136
     # Test 4: Defined variable works with set -u
137
-    output=$($FORTSH_BIN -c 'set -u; VAR=value; echo $VAR' 2>&1)
137
+    output=$($SHELL_BIN -c 'set -u; VAR=value; echo $VAR' 2>&1)
138138
     if echo "$output" | grep -q "value"; then
139139
         pass "P0-2.4: Defined variables work correctly with set -u"
140140
     else
@@ -142,7 +142,7 @@ test_p0_set_u() {
142142
     fi
143143
 
144144
     # Test 5: set +u disables the option
145
-    output=$($FORTSH_BIN -c 'set -u; set +u; echo $UNDEFINED_AFTER_DISABLE' 2>&1)
145
+    output=$($SHELL_BIN -c 'set -u; set +u; echo $UNDEFINED_AFTER_DISABLE' 2>&1)
146146
     if ! echo "$output" | grep -q "unbound variable"; then
147147
         pass "P0-2.5: set +u correctly disables nounset option"
148148
     else
@@ -150,7 +150,7 @@ test_p0_set_u() {
150150
     fi
151151
 
152152
     # Test 6: Special variables always defined ($?, $$, etc.)
153
-    output=$($FORTSH_BIN -c 'set -u; echo $? $$ $0' 2>&1)
153
+    output=$($SHELL_BIN -c 'set -u; echo $? $$ $0' 2>&1)
154154
     if ! echo "$output" | grep -q "unbound variable"; then
155155
         pass "P0-2.6: Special variables don't trigger set -u"
156156
     else
@@ -162,7 +162,7 @@ test_p0_trap_exit() {
162162
     section "P0-3: trap EXIT Execution"
163163
 
164164
     # Test 1: EXIT trap executes on exit builtin
165
-    output=$($FORTSH_BIN -c 'trap "echo TRAPPED" EXIT; exit 0' 2>&1)
165
+    output=$($SHELL_BIN -c 'trap "echo TRAPPED" EXIT; exit 0' 2>&1)
166166
     if echo "$output" | grep -q "TRAPPED"; then
167167
         pass "P0-3.1: EXIT trap executes on exit builtin"
168168
     else
@@ -170,7 +170,7 @@ test_p0_trap_exit() {
170170
     fi
171171
 
172172
     # Test 2: EXIT trap preserves exit code
173
-    $FORTSH_BIN -c 'trap "echo cleanup" EXIT; exit 42' >/dev/null 2>&1
173
+    $SHELL_BIN -c 'trap "echo cleanup" EXIT; exit 42' >/dev/null 2>&1
174174
     if [ $? -eq 42 ]; then
175175
         pass "P0-3.2: EXIT trap preserves original exit code"
176176
     else
@@ -178,7 +178,7 @@ test_p0_trap_exit() {
178178
     fi
179179
 
180180
     # Test 3: EXIT trap executes on natural shell exit
181
-    output=$(echo 'trap "echo CLEANUP" EXIT; echo done' | $FORTSH_BIN 2>&1)
181
+    output=$(echo 'trap "echo CLEANUP" EXIT; echo done' | $SHELL_BIN 2>&1)
182182
     if echo "$output" | grep -q "CLEANUP"; then
183183
         pass "P0-3.3: EXIT trap executes on natural shell termination"
184184
     else
@@ -186,7 +186,7 @@ test_p0_trap_exit() {
186186
     fi
187187
 
188188
     # Test 4: EXIT trap executes only once
189
-    output=$($FORTSH_BIN -c 'trap "echo ONCE" EXIT; exit 0' 2>&1)
189
+    output=$($SHELL_BIN -c 'trap "echo ONCE" EXIT; exit 0' 2>&1)
190190
     count=$(echo "$output" | grep -c "ONCE")
191191
     if [ "$count" -eq 1 ]; then
192192
         pass "P0-3.4: EXIT trap executes exactly once"
@@ -195,7 +195,7 @@ test_p0_trap_exit() {
195195
     fi
196196
 
197197
     # Test 5: EXIT trap can access variables
198
-    output=$($FORTSH_BIN -c 'VAR=value; trap "echo \$VAR" EXIT; exit 0' 2>&1)
198
+    output=$($SHELL_BIN -c 'VAR=value; trap "echo \$VAR" EXIT; exit 0' 2>&1)
199199
     if echo "$output" | grep -q "value"; then
200200
         pass "P0-3.5: EXIT trap can access shell variables"
201201
     else
@@ -203,7 +203,7 @@ test_p0_trap_exit() {
203203
     fi
204204
 
205205
     # Test 6: EXIT trap with non-zero exit from command
206
-    $FORTSH_BIN -c 'trap "echo cleanup" EXIT; false' >/dev/null 2>&1
206
+    $SHELL_BIN -c 'trap "echo cleanup" EXIT; false' >/dev/null 2>&1
207207
     if [ $? -eq 1 ]; then
208208
         pass "P0-3.6: EXIT trap preserves command failure exit code"
209209
     else
@@ -221,7 +221,7 @@ test_p1_exit_code_126() {
221221
     # Test 1: Non-executable file returns 126
222222
     touch /tmp/fortsh_test_nonexec
223223
     chmod 644 /tmp/fortsh_test_nonexec
224
-    $FORTSH_BIN -c '/tmp/fortsh_test_nonexec' >/dev/null 2>&1
224
+    $SHELL_BIN -c '/tmp/fortsh_test_nonexec' >/dev/null 2>&1
225225
     exit_code=$?
226226
     rm -f /tmp/fortsh_test_nonexec
227227
 
@@ -232,7 +232,7 @@ test_p1_exit_code_126() {
232232
     fi
233233
 
234234
     # Test 2: Non-existent file still returns 127
235
-    $FORTSH_BIN -c '/nonexistent/command/path' >/dev/null 2>&1
235
+    $SHELL_BIN -c '/nonexistent/command/path' >/dev/null 2>&1
236236
     if [ $? -eq 127 ]; then
237237
         pass "P1-1.2: Non-existent command returns exit code 127"
238238
     else
@@ -243,7 +243,7 @@ test_p1_exit_code_126() {
243243
     echo '#!/bin/sh' > /tmp/fortsh_test_exec
244244
     echo 'exit 5' >> /tmp/fortsh_test_exec
245245
     chmod 755 /tmp/fortsh_test_exec
246
-    $FORTSH_BIN -c '/tmp/fortsh_test_exec' >/dev/null 2>&1
246
+    $SHELL_BIN -c '/tmp/fortsh_test_exec' >/dev/null 2>&1
247247
     exit_code=$?
248248
     rm -f /tmp/fortsh_test_exec
249249
 
@@ -259,7 +259,7 @@ test_p1_set_c_noclobber() {
259259
 
260260
     # Test 1: set -C prevents overwriting existing files
261261
     echo "original" > /tmp/fortsh_test_noclobber
262
-    $FORTSH_BIN -c 'set -C; echo new > /tmp/fortsh_test_noclobber' >/dev/null 2>&1
262
+    $SHELL_BIN -c 'set -C; echo new > /tmp/fortsh_test_noclobber' >/dev/null 2>&1
263263
     exit_code=$?
264264
     content=$(cat /tmp/fortsh_test_noclobber 2>/dev/null)
265265
     rm -f /tmp/fortsh_test_noclobber
@@ -272,7 +272,7 @@ test_p1_set_c_noclobber() {
272272
 
273273
     # Test 2: set -C allows writing to new files
274274
     rm -f /tmp/fortsh_test_noclobber_new
275
-    $FORTSH_BIN -c 'set -C; echo content > /tmp/fortsh_test_noclobber_new' >/dev/null 2>&1
275
+    $SHELL_BIN -c 'set -C; echo content > /tmp/fortsh_test_noclobber_new' >/dev/null 2>&1
276276
     if [ -f /tmp/fortsh_test_noclobber_new ]; then
277277
         pass "P1-2.2: set -C allows writing to non-existent files"
278278
         rm -f /tmp/fortsh_test_noclobber_new
@@ -282,7 +282,7 @@ test_p1_set_c_noclobber() {
282282
 
283283
     # Test 3: >| forces overwrite even with noclobber
284284
     echo "original" > /tmp/fortsh_test_force
285
-    $FORTSH_BIN -c 'set -C; echo forced >| /tmp/fortsh_test_force' >/dev/null 2>&1
285
+    $SHELL_BIN -c 'set -C; echo forced >| /tmp/fortsh_test_force' >/dev/null 2>&1
286286
     content=$(cat /tmp/fortsh_test_force 2>/dev/null)
287287
     rm -f /tmp/fortsh_test_force
288288
 
@@ -294,7 +294,7 @@ test_p1_set_c_noclobber() {
294294
 
295295
     # Test 4: set +C disables noclobber
296296
     echo "original" > /tmp/fortsh_test_disable
297
-    $FORTSH_BIN -c 'set -C; set +C; echo new > /tmp/fortsh_test_disable' >/dev/null 2>&1
297
+    $SHELL_BIN -c 'set -C; set +C; echo new > /tmp/fortsh_test_disable' >/dev/null 2>&1
298298
     content=$(cat /tmp/fortsh_test_disable 2>/dev/null)
299299
     rm -f /tmp/fortsh_test_disable
300300
 
@@ -309,7 +309,7 @@ test_p1_trap_removal() {
309309
     section "P1-3: trap - SIGNAL (Trap Removal)"
310310
 
311311
     # Test 1: trap - INT removes INT trap
312
-    output=$($FORTSH_BIN -c 'trap "echo caught" INT; trap - INT; kill -INT $$' 2>&1)
312
+    output=$($SHELL_BIN -c 'trap "echo caught" INT; trap - INT; kill -INT $$' 2>&1)
313313
     if ! echo "$output" | grep -q "caught"; then
314314
         pass "P1-3.1: trap - INT removes INT trap"
315315
     else
@@ -317,7 +317,7 @@ test_p1_trap_removal() {
317317
     fi
318318
 
319319
     # Test 2: trap - TERM removes TERM trap
320
-    $FORTSH_BIN -c 'trap "echo term" TERM; trap - TERM; exit 0' >/dev/null 2>&1
320
+    $SHELL_BIN -c 'trap "echo term" TERM; trap - TERM; exit 0' >/dev/null 2>&1
321321
     if [ $? -eq 0 ]; then
322322
         pass "P1-3.2: trap - TERM removes TERM trap"
323323
     else
@@ -325,7 +325,7 @@ test_p1_trap_removal() {
325325
     fi
326326
 
327327
     # Test 3: trap - EXIT removes EXIT trap
328
-    output=$($FORTSH_BIN -c 'trap "echo exit" EXIT; trap - EXIT; exit 0' 2>&1)
328
+    output=$($SHELL_BIN -c 'trap "echo exit" EXIT; trap - EXIT; exit 0' 2>&1)
329329
     if ! echo "$output" | grep -q "exit"; then
330330
         pass "P1-3.3: trap - EXIT removes EXIT trap"
331331
     else
@@ -333,7 +333,7 @@ test_p1_trap_removal() {
333333
     fi
334334
 
335335
     # Test 4: Listing traps after removal
336
-    output=$($FORTSH_BIN -c 'trap "echo test" INT; trap - INT; trap' 2>&1)
336
+    output=$($SHELL_BIN -c 'trap "echo test" INT; trap - INT; trap' 2>&1)
337337
     if ! echo "$output" | grep -q "INT"; then
338338
         pass "P1-3.4: Removed traps don't appear in trap listing"
339339
     else
@@ -345,7 +345,7 @@ test_p1_set_e_conditionals() {
345345
     section "P1-4: set -e in Conditional Contexts"
346346
 
347347
     # Test 1: set -e doesn't exit on false in if condition
348
-    output=$($FORTSH_BIN -c 'set -e; if false; then echo no; else echo YES; fi' 2>&1)
348
+    output=$($SHELL_BIN -c 'set -e; if false; then echo no; else echo YES; fi' 2>&1)
349349
     if echo "$output" | grep -q "YES"; then
350350
         pass "P1-4.1: set -e doesn't exit on false in if condition"
351351
     else
@@ -353,7 +353,7 @@ test_p1_set_e_conditionals() {
353353
     fi
354354
 
355355
     # Test 2: set -e doesn't exit on false in while condition
356
-    output=$($FORTSH_BIN -c 'set -e; count=0; while false; do count=$((count+1)); done; echo AFTER' 2>&1)
356
+    output=$($SHELL_BIN -c 'set -e; count=0; while false; do count=$((count+1)); done; echo AFTER' 2>&1)
357357
     if echo "$output" | grep -q "AFTER"; then
358358
         pass "P1-4.2: set -e doesn't exit on false in while condition"
359359
     else
@@ -361,7 +361,7 @@ test_p1_set_e_conditionals() {
361361
     fi
362362
 
363363
     # Test 3: set -e exits on command failure outside conditionals
364
-    $FORTSH_BIN -c 'set -e; false; echo SHOULD_NOT_PRINT' >/dev/null 2>&1
364
+    $SHELL_BIN -c 'set -e; false; echo SHOULD_NOT_PRINT' >/dev/null 2>&1
365365
     exit_code=$?
366366
     if [ $exit_code -ne 0 ]; then
367367
         pass "P1-4.3: set -e exits on command failure outside conditionals"
@@ -370,7 +370,7 @@ test_p1_set_e_conditionals() {
370370
     fi
371371
 
372372
     # Test 4: set -e with && and || operators
373
-    output=$($FORTSH_BIN -c 'set -e; false || echo AFTER_OR' 2>&1)
373
+    output=$($SHELL_BIN -c 'set -e; false || echo AFTER_OR' 2>&1)
374374
     if echo "$output" | grep -q "AFTER_OR"; then
375375
         pass "P1-4.4: set -e doesn't exit on false before ||"
376376
     else
@@ -378,7 +378,7 @@ test_p1_set_e_conditionals() {
378378
     fi
379379
 
380380
     # Test 5: set -e in until loop
381
-    output=$($FORTSH_BIN -c 'set -e; count=0; until [ $count -eq 1 ]; do count=1; done; echo DONE' 2>&1)
381
+    output=$($SHELL_BIN -c 'set -e; count=0; until [ $count -eq 1 ]; do count=1; done; echo DONE' 2>&1)
382382
     if echo "$output" | grep -q "DONE"; then
383383
         pass "P1-4.5: set -e doesn't exit on false in until condition"
384384
     else
@@ -394,7 +394,7 @@ test_p2_background_pid() {
394394
     section "P2-1: \$! (Background Process PID)"
395395
 
396396
     # Test 1: $! contains PID of last background job
397
-    output=$($FORTSH_BIN -c 'sleep 0.1 & echo $!' 2>&1)
397
+    output=$($SHELL_BIN -c 'sleep 0.1 & echo $!' 2>&1)
398398
     if echo "$output" | grep -qE '^[0-9]+$'; then
399399
         pass "P2-1.1: \$! expands to numeric PID"
400400
     else
@@ -402,7 +402,7 @@ test_p2_background_pid() {
402402
     fi
403403
 
404404
     # Test 2: $! updates after each background job
405
-    output=$($FORTSH_BIN -c 'sleep 0.1 & pid1=$!; sleep 0.1 & pid2=$!; if [ "$pid1" != "$pid2" ]; then echo DIFFERENT; fi' 2>&1)
405
+    output=$($SHELL_BIN -c 'sleep 0.1 & pid1=$!; sleep 0.1 & pid2=$!; if [ "$pid1" != "$pid2" ]; then echo DIFFERENT; fi' 2>&1)
406406
     if echo "$output" | grep -q "DIFFERENT"; then
407407
         pass "P2-1.2: \$! updates for each background job"
408408
     else
@@ -410,7 +410,7 @@ test_p2_background_pid() {
410410
     fi
411411
 
412412
     # Test 3: $! is empty/zero before any background jobs
413
-    output=$($FORTSH_BIN -c 'echo "|$!|"' 2>&1)
413
+    output=$($SHELL_BIN -c 'echo "|$!|"' 2>&1)
414414
     if echo "$output" | grep -qE '\|[0-9]*\|'; then
415415
         pass "P2-1.3: \$! has valid value before background jobs"
416416
     else
@@ -423,7 +423,7 @@ test_p2_dot_with_args() {
423423
 
424424
     # Test 1: Source script with positional parameters
425425
     echo 'echo "arg1=$1 arg2=$2"' > /tmp/fortsh_test_source
426
-    output=$($FORTSH_BIN -c '. /tmp/fortsh_test_source hello world' 2>&1)
426
+    output=$($SHELL_BIN -c '. /tmp/fortsh_test_source hello world' 2>&1)
427427
     rm -f /tmp/fortsh_test_source
428428
 
429429
     if echo "$output" | grep -q "arg1=hello arg2=world"; then
@@ -434,7 +434,7 @@ test_p2_dot_with_args() {
434434
 
435435
     # Test 2: Source script preserves caller's variables
436436
     echo 'SOURCED_VAR=from_script' > /tmp/fortsh_test_source2
437
-    output=$($FORTSH_BIN -c '. /tmp/fortsh_test_source2; echo $SOURCED_VAR' 2>&1)
437
+    output=$($SHELL_BIN -c '. /tmp/fortsh_test_source2; echo $SOURCED_VAR' 2>&1)
438438
     rm -f /tmp/fortsh_test_source2
439439
 
440440
     if echo "$output" | grep -q "from_script"; then
@@ -445,7 +445,7 @@ test_p2_dot_with_args() {
445445
 
446446
     # Test 3: Source with absolute path
447447
     echo 'echo sourced' > /tmp/fortsh_abs_source
448
-    output=$($FORTSH_BIN -c '. /tmp/fortsh_abs_source' 2>&1)
448
+    output=$($SHELL_BIN -c '. /tmp/fortsh_abs_source' 2>&1)
449449
     rm -f /tmp/fortsh_abs_source
450450
 
451451
     if echo "$output" | grep -q "sourced"; then
@@ -459,7 +459,7 @@ test_p2_readonly_unset() {
459459
     section "P2-3: Readonly Unset Prevention"
460460
 
461461
     # Test 1: Cannot unset readonly variable
462
-    output=$($FORTSH_BIN -c 'readonly VAR=test; unset VAR' 2>&1)
462
+    output=$($SHELL_BIN -c 'readonly VAR=test; unset VAR' 2>&1)
463463
     if echo "$output" | grep -qE '(readonly|cannot unset)'; then
464464
         pass "P2-3.1: unset readonly variable produces error"
465465
     else
@@ -467,7 +467,7 @@ test_p2_readonly_unset() {
467467
     fi
468468
 
469469
     # Test 2: Readonly variable still exists after unset attempt
470
-    output=$($FORTSH_BIN -c 'readonly VAR=value; unset VAR 2>/dev/null; echo $VAR' 2>&1)
470
+    output=$($SHELL_BIN -c 'readonly VAR=value; unset VAR 2>/dev/null; echo $VAR' 2>&1)
471471
     if echo "$output" | grep -q "value"; then
472472
         pass "P2-3.2: Readonly variable survives unset attempt"
473473
     else
@@ -475,7 +475,7 @@ test_p2_readonly_unset() {
475475
     fi
476476
 
477477
     # Test 3: unset returns non-zero for readonly variables
478
-    $FORTSH_BIN -c 'readonly VAR=x; unset VAR' >/dev/null 2>&1
478
+    $SHELL_BIN -c 'readonly VAR=x; unset VAR' >/dev/null 2>&1
479479
     if [ $? -ne 0 ]; then
480480
         pass "P2-3.3: unset readonly variable returns non-zero"
481481
     else
@@ -483,7 +483,7 @@ test_p2_readonly_unset() {
483483
     fi
484484
 
485485
     # Test 4: Can unset non-readonly variables
486
-    output=$($FORTSH_BIN -c 'VAR=test; unset VAR; echo "|$VAR|"' 2>&1)
486
+    output=$($SHELL_BIN -c 'VAR=test; unset VAR; echo "|$VAR|"' 2>&1)
487487
     if echo "$output" | grep -q "||"; then
488488
         pass "P2-3.4: unset works for non-readonly variables"
489489
     else
@@ -499,7 +499,7 @@ test_additional_builtins() {
499499
     section "BONUS: Additional Builtin Tests"
500500
 
501501
     # Test shift builtin
502
-    output=$($FORTSH_BIN -c 'set -- a b c; shift; echo $1' 2>&1)
502
+    output=$($SHELL_BIN -c 'set -- a b c; shift; echo $1' 2>&1)
503503
     if echo "$output" | grep -q "b"; then
504504
         pass "BONUS-1: shift builtin works correctly"
505505
     else
@@ -507,7 +507,7 @@ test_additional_builtins() {
507507
     fi
508508
 
509509
     # Test times builtin
510
-    output=$($FORTSH_BIN -c 'times' 2>&1)
510
+    output=$($SHELL_BIN -c 'times' 2>&1)
511511
     if echo "$output" | grep -qE '[0-9]'; then
512512
         pass "BONUS-2: times builtin produces output"
513513
     else
@@ -515,7 +515,7 @@ test_additional_builtins() {
515515
     fi
516516
 
517517
     # Test hash builtin
518
-    output=$($FORTSH_BIN -c 'hash' 2>&1)
518
+    output=$($SHELL_BIN -c 'hash' 2>&1)
519519
     if [ $? -eq 0 ]; then
520520
         pass "BONUS-3: hash builtin executes without error"
521521
     else
@@ -523,7 +523,7 @@ test_additional_builtins() {
523523
     fi
524524
 
525525
     # Test type builtin
526
-    output=$($FORTSH_BIN -c 'type echo' 2>&1)
526
+    output=$($SHELL_BIN -c 'type echo' 2>&1)
527527
     if echo "$output" | grep -qiE '(builtin|command)'; then
528528
         pass "BONUS-4: type builtin identifies commands"
529529
     else
@@ -531,7 +531,7 @@ test_additional_builtins() {
531531
     fi
532532
 
533533
     # Test umask builtin
534
-    output=$($FORTSH_BIN -c 'umask' 2>&1)
534
+    output=$($SHELL_BIN -c 'umask' 2>&1)
535535
     if echo "$output" | grep -qE '^[0-9]{4}$'; then
536536
         pass "BONUS-5: umask builtin displays mask"
537537
     else
@@ -539,7 +539,7 @@ test_additional_builtins() {
539539
     fi
540540
 
541541
     # Test getopts builtin
542
-    output=$($FORTSH_BIN -c 'getopts "a:b" opt -a value; echo $opt' 2>&1)
542
+    output=$($SHELL_BIN -c 'getopts "a:b" opt -a value; echo $opt' 2>&1)
543543
     if echo "$output" | grep -q "a"; then
544544
         pass "BONUS-6: getopts builtin parses options"
545545
     else
@@ -551,7 +551,7 @@ test_edge_cases() {
551551
     section "BONUS: Edge Cases"
552552
 
553553
     # Test empty command
554
-    $FORTSH_BIN -c '' >/dev/null 2>&1
554
+    $SHELL_BIN -c '' >/dev/null 2>&1
555555
     if [ $? -eq 0 ]; then
556556
         pass "EDGE-1: Empty command succeeds"
557557
     else
@@ -560,7 +560,7 @@ test_edge_cases() {
560560
 
561561
     # Test semicolon alone
562562
     # POSIX: Semicolon alone is a syntax error (exit code 2), not success
563
-    $FORTSH_BIN -c ';' >/dev/null 2>&1
563
+    $SHELL_BIN -c ';' >/dev/null 2>&1
564564
     if [ $? -eq 2 ]; then
565565
         pass "EDGE-2: Semicolon alone is syntax error"
566566
     else
@@ -568,7 +568,7 @@ test_edge_cases() {
568568
     fi
569569
 
570570
     # Test comment handling
571
-    output=$($FORTSH_BIN -c 'echo visible # this is comment' 2>&1)
571
+    output=$($SHELL_BIN -c 'echo visible # this is comment' 2>&1)
572572
     if echo "$output" | grep -q "visible" && ! echo "$output" | grep -q "comment"; then
573573
         pass "EDGE-3: Comments are ignored correctly"
574574
     else
@@ -576,7 +576,7 @@ test_edge_cases() {
576576
     fi
577577
 
578578
     # Test multiple semicolons
579
-    output=$($FORTSH_BIN -c 'echo a;; echo b' 2>&1)
579
+    output=$($SHELL_BIN -c 'echo a;; echo b' 2>&1)
580580
     if echo "$output" | grep -q "b"; then
581581
         pass "EDGE-4: Multiple semicolons handled"
582582
     else
@@ -592,14 +592,14 @@ main() {
592592
     echo "=========================================="
593593
     echo "POSIX Compliance - Builtin Test Suite"
594594
     echo "=========================================="
595
-    echo "Testing: $FORTSH_BIN"
595
+    echo "Testing: $SHELL_BIN"
596596
     echo "Date: $(date)"
597597
     echo ""
598598
 
599599
     # Verify fortsh exists
600
-    if [ ! -x "$FORTSH_BIN" ]; then
601
-        echo -e "${RED}ERROR: fortsh binary not found or not executable: $FORTSH_BIN${NC}"
602
-        echo "Please build fortsh or set FORTSH_BIN environment variable"
600
+    if [ ! -x "$SHELL_BIN" ]; then
601
+        echo -e "${RED}ERROR: shell binary not found or not executable: $SHELL_BIN${NC}"
602
+        echo "Please build fortsh or set SHELL_BIN environment variable"
603603
         exit 1
604604
     fi
605605
 
suites/posix/posix_compliance_charclass.shmodified
@@ -24,12 +24,12 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 
2929
 # Check if fortsh exists
30
-if [ ! -x "$FORTSH_BIN" ]; then
31
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
+if [ ! -x "$SHELL_BIN" ]; then
31
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
32
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3333
     exit 1
3434
 fi
3535
 
@@ -101,7 +101,7 @@ setup_test_files
101101
 section "341. POSIX CHARACTER CLASS [:alpha:]"
102102
 # =====================================
103103
 
104
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [[:alpha:]]*' 2>&1)
104
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [[:alpha:]]*' 2>&1)
105105
 # Should match files starting with alphabetic characters
106106
 if echo "$result" | grep -q "file1.txt\|FileA.txt"; then
107107
     pass "[:alpha:] matches alphabetic characters"
@@ -109,7 +109,7 @@ else
109109
     fail "[:alpha:] matches alphabetic characters" "files starting with letters" "$result"
110110
 fi
111111
 
112
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && for f in [[:alpha:]]*.txt; do echo "$f"; done | head -1' 2>&1)
112
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && for f in [[:alpha:]]*.txt; do echo "$f"; done | head -1' 2>&1)
113113
 if [ -n "$result" ] && [ "$result" != '[[:alpha:]]*.txt' ]; then
114114
     pass "[:alpha:] in loop context"
115115
 else
@@ -120,14 +120,14 @@ fi
120120
 section "342. POSIX CHARACTER CLASS [:digit:]"
121121
 # =====================================
122122
 
123
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo data_[[:digit:]]*.csv' 2>&1)
123
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo data_[[:digit:]]*.csv' 2>&1)
124124
 if echo "$result" | grep -q "data_0"; then
125125
     pass "[:digit:] matches numeric characters"
126126
 else
127127
     fail "[:digit:] matches numeric characters" "data_0*.csv files" "$result"
128128
 fi
129129
 
130
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo *[[:digit:]][[:digit:]].csv' 2>&1)
130
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo *[[:digit:]][[:digit:]].csv' 2>&1)
131131
 if echo "$result" | grep -q "data_"; then
132132
     pass "[:digit:][:digit:] matches two digits"
133133
 else
@@ -138,7 +138,7 @@ fi
138138
 section "343. POSIX CHARACTER CLASS [:alnum:]"
139139
 # =====================================
140140
 
141
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [[:alnum:]]*.txt' 2>&1)
141
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [[:alnum:]]*.txt' 2>&1)
142142
 if echo "$result" | grep -q "file"; then
143143
     pass "[:alnum:] matches alphanumeric characters"
144144
 else
@@ -149,14 +149,14 @@ fi
149149
 section "344. POSIX CHARACTER CLASS [:upper:]"
150150
 # =====================================
151151
 
152
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [[:upper:]]*.TXT' 2>&1)
152
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [[:upper:]]*.TXT' 2>&1)
153153
 if echo "$result" | grep -q "UPPER.TXT\|File"; then
154154
     pass "[:upper:] matches uppercase characters"
155155
 else
156156
     fail "[:upper:] matches uppercase characters" "uppercase files" "$result"
157157
 fi
158158
 
159
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [[:upper:]][[:upper:]][[:upper:]]*.TXT' 2>&1)
159
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [[:upper:]][[:upper:]][[:upper:]]*.TXT' 2>&1)
160160
 if echo "$result" | grep -q "UPPER.TXT\|ABC"; then
161161
     pass "[:upper:] repeated matches multiple uppercase"
162162
 else
@@ -167,7 +167,7 @@ fi
167167
 section "345. POSIX CHARACTER CLASS [:lower:]"
168168
 # =====================================
169169
 
170
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [[:lower:]]*.txt' 2>&1)
170
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [[:lower:]]*.txt' 2>&1)
171171
 if echo "$result" | grep -q "file\|lower"; then
172172
     pass "[:lower:] matches lowercase characters"
173173
 else
@@ -179,7 +179,7 @@ section "346. POSIX CHARACTER CLASS [:space:]"
179179
 # =====================================
180180
 
181181
 # [:space:] in variable content
182
-result=$("$FORTSH_BIN" -c 'x="hello world"; case "$x" in *[[:space:]]*) echo "has space";; esac' 2>&1)
182
+result=$("$SHELL_BIN" -c 'x="hello world"; case "$x" in *[[:space:]]*) echo "has space";; esac' 2>&1)
183183
 if [ "$result" = "has space" ]; then
184184
     pass "[:space:] matches space in case pattern"
185185
 else
@@ -191,7 +191,7 @@ section "347. POSIX CHARACTER CLASS [:blank:]"
191191
 # =====================================
192192
 
193193
 # [:blank:] matches space and tab only
194
-result=$("$FORTSH_BIN" -c 'x="a	b"; case "$x" in *[[:blank:]]*) echo "has blank";; esac' 2>&1)
194
+result=$("$SHELL_BIN" -c 'x="a	b"; case "$x" in *[[:blank:]]*) echo "has blank";; esac' 2>&1)
195195
 if [ "$result" = "has blank" ]; then
196196
     pass "[:blank:] matches tab character"
197197
 else
@@ -202,14 +202,14 @@ fi
202202
 section "348. POSIX CHARACTER CLASS [:xdigit:]"
203203
 # =====================================
204204
 
205
-result=$("$FORTSH_BIN" -c 'case "a1b2c3" in [[:xdigit:]]*) echo "starts with hex";; esac' 2>&1)
205
+result=$("$SHELL_BIN" -c 'case "a1b2c3" in [[:xdigit:]]*) echo "starts with hex";; esac' 2>&1)
206206
 if [ "$result" = "starts with hex" ]; then
207207
     pass "[:xdigit:] matches hexadecimal digits"
208208
 else
209209
     fail "[:xdigit:] matches hexadecimal digits" "starts with hex" "$result"
210210
 fi
211211
 
212
-result=$("$FORTSH_BIN" -c 'case "DEADBEEF" in [[:xdigit:]]*) echo "valid hex";; esac' 2>&1)
212
+result=$("$SHELL_BIN" -c 'case "DEADBEEF" in [[:xdigit:]]*) echo "valid hex";; esac' 2>&1)
213213
 if [ "$result" = "valid hex" ]; then
214214
     pass "[:xdigit:] matches uppercase hex"
215215
 else
@@ -220,14 +220,14 @@ fi
220220
 section "349. POSIX CHARACTER CLASS [:punct:]"
221221
 # =====================================
222222
 
223
-result=$("$FORTSH_BIN" -c 'case "hello!" in *[[:punct:]]) echo "ends with punct";; esac' 2>&1)
223
+result=$("$SHELL_BIN" -c 'case "hello!" in *[[:punct:]]) echo "ends with punct";; esac' 2>&1)
224224
 if [ "$result" = "ends with punct" ]; then
225225
     pass "[:punct:] matches punctuation"
226226
 else
227227
     fail "[:punct:] matches punctuation" "ends with punct" "$result"
228228
 fi
229229
 
230
-result=$("$FORTSH_BIN" -c 'case "@#$%" in [[:punct:]]*) echo "starts with punct";; esac' 2>&1)
230
+result=$("$SHELL_BIN" -c 'case "@#$%" in [[:punct:]]*) echo "starts with punct";; esac' 2>&1)
231231
 if [ "$result" = "starts with punct" ]; then
232232
     pass "[:punct:] matches special characters"
233233
 else
@@ -238,7 +238,7 @@ fi
238238
 section "350. POSIX CHARACTER CLASS [:print:]"
239239
 # =====================================
240240
 
241
-result=$("$FORTSH_BIN" -c 'case "hello" in [[:print:]]*) echo "printable";; esac' 2>&1)
241
+result=$("$SHELL_BIN" -c 'case "hello" in [[:print:]]*) echo "printable";; esac' 2>&1)
242242
 if [ "$result" = "printable" ]; then
243243
     pass "[:print:] matches printable characters"
244244
 else
@@ -249,7 +249,7 @@ fi
249249
 section "351. POSIX CHARACTER CLASS [:graph:]"
250250
 # =====================================
251251
 
252
-result=$("$FORTSH_BIN" -c 'case "abc123" in [[:graph:]]*) echo "graphical";; esac' 2>&1)
252
+result=$("$SHELL_BIN" -c 'case "abc123" in [[:graph:]]*) echo "graphical";; esac' 2>&1)
253253
 if [ "$result" = "graphical" ]; then
254254
     pass "[:graph:] matches graphical characters"
255255
 else
@@ -261,14 +261,14 @@ section "352. POSIX BRACKET NEGATION [^...] and [!...]"
261261
 # =====================================
262262
 
263263
 # Note: POSIX uses [!...] for negation, [^...] is bash extension
264
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [!A-Z]*.txt' 2>&1)
264
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [!A-Z]*.txt' 2>&1)
265265
 if echo "$result" | grep -q "file\|lower"; then
266266
     pass "[!...] negation matches non-uppercase (POSIX standard)"
267267
 else
268268
     fail "[!...] negation matches non-uppercase (POSIX standard)" "lowercase files" "$result"
269269
 fi
270270
 
271
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [!0-9]*.txt' 2>&1)
271
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [!0-9]*.txt' 2>&1)
272272
 if echo "$result" | grep -q "file\|File"; then
273273
     pass "[!...] negation matches non-digits"
274274
 else
@@ -279,21 +279,21 @@ fi
279279
 section "353. POSIX RANGE EXPRESSIONS"
280280
 # =====================================
281281
 
282
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo file[1-3].txt' 2>&1)
282
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo file[1-3].txt' 2>&1)
283283
 if echo "$result" | grep -q "file1.txt\|file2.txt\|file3.txt"; then
284284
     pass "[1-3] range matches digits 1-3"
285285
 else
286286
     fail "[1-3] range matches digits 1-3" "file1-3.txt" "$result"
287287
 fi
288288
 
289
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo File[A-C].txt' 2>&1)
289
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo File[A-C].txt' 2>&1)
290290
 if echo "$result" | grep -q "FileA.txt\|FileB.txt\|FileC.txt"; then
291291
     pass "[A-C] range matches uppercase A-C"
292292
 else
293293
     fail "[A-C] range matches uppercase A-C" "FileA-C.txt" "$result"
294294
 fi
295295
 
296
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [a-z]*.txt' 2>&1)
296
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [a-z]*.txt' 2>&1)
297297
 if echo "$result" | grep -q "file\|lower"; then
298298
     pass "[a-z] range matches lowercase"
299299
 else
@@ -304,14 +304,14 @@ fi
304304
 section "354. COMBINED CHARACTER CLASSES"
305305
 # =====================================
306306
 
307
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [[:alpha:][:digit:]]*.txt' 2>&1)
307
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [[:alpha:][:digit:]]*.txt' 2>&1)
308308
 if echo "$result" | grep -q "file\|File"; then
309309
     pass "[[:alpha:][:digit:]] combined classes"
310310
 else
311311
     fail "[[:alpha:][:digit:]] combined classes" "alphanumeric start" "$result"
312312
 fi
313313
 
314
-result=$("$FORTSH_BIN" -c 'case "test123" in [[:alpha:]][[:alpha:]][[:alpha:]][[:alpha:]][[:digit:]][[:digit:]][[:digit:]]) echo "matched";; esac' 2>&1)
314
+result=$("$SHELL_BIN" -c 'case "test123" in [[:alpha:]][[:alpha:]][[:alpha:]][[:alpha:]][[:digit:]][[:digit:]][[:digit:]]) echo "matched";; esac' 2>&1)
315315
 if [ "$result" = "matched" ]; then
316316
     pass "Combined classes in exact pattern"
317317
 else
@@ -322,7 +322,7 @@ fi
322322
 section "355. CHARACTER CLASS IN CASE STATEMENTS"
323323
 # =====================================
324324
 
325
-result=$("$FORTSH_BIN" -c '
325
+result=$("$SHELL_BIN" -c '
326326
 for word in hello WORLD 123 test!; do
327327
     case "$word" in
328328
         [[:upper:]]*) echo "$word: upper" ;;
@@ -343,7 +343,7 @@ section "356. CHARACTER CLASS EDGE CASES"
343343
 # =====================================
344344
 
345345
 # Literal hyphen at start
346
-result=$("$FORTSH_BIN" -c 'case "-test" in [-a]*) echo "matched";; esac' 2>&1)
346
+result=$("$SHELL_BIN" -c 'case "-test" in [-a]*) echo "matched";; esac' 2>&1)
347347
 if [ "$result" = "matched" ]; then
348348
     pass "Literal hyphen at bracket start"
349349
 else
@@ -351,7 +351,7 @@ else
351351
 fi
352352
 
353353
 # Literal bracket
354
-result=$("$FORTSH_BIN" -c 'case "[test]" in \[*) echo "matched";; esac' 2>&1)
354
+result=$("$SHELL_BIN" -c 'case "[test]" in \[*) echo "matched";; esac' 2>&1)
355355
 if [ "$result" = "matched" ]; then
356356
     pass "Escaped bracket in pattern"
357357
 else
@@ -359,7 +359,7 @@ else
359359
 fi
360360
 
361361
 # Empty class should not match
362
-result=$("$FORTSH_BIN" -c 'case "test" in []) echo "empty";; *) echo "star";; esac' 2>&1)
362
+result=$("$SHELL_BIN" -c 'case "test" in []) echo "empty";; *) echo "star";; esac' 2>&1)
363363
 if [ "$result" = "star" ]; then
364364
     pass "Empty bracket expression fallthrough"
365365
 else
@@ -370,14 +370,14 @@ fi
370370
 section "357. CHARACTER CLASS WITH GLOB PATTERNS"
371371
 # =====================================
372372
 
373
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo *[[:digit:]].*' 2>&1)
373
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo *[[:digit:]].*' 2>&1)
374374
 if echo "$result" | grep -q "data_0\|file"; then
375375
     pass "Character class with glob wildcards"
376376
 else
377377
     fail "Character class with glob wildcards" "digit-containing files" "$result"
378378
 fi
379379
 
380
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && echo [[:alpha:]]?[[:alpha:]]?[[:alpha:]]*.txt' 2>&1)
380
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && echo [[:alpha:]]?[[:alpha:]]?[[:alpha:]]*.txt' 2>&1)
381381
 if echo "$result" | grep -q "file\|File\|lower"; then
382382
     pass "Character class with ? wildcards"
383383
 else
suites/posix/posix_compliance_control.shmodified
1041 lines changed — click to load
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -74,14 +74,14 @@ section() {
7474
 section "411. SUBSHELL EXECUTION ( )"
7575
 # =====================================
7676
 
77
-result=$("$FORTSH_BIN" -c '(echo hello)' 2>&1)
77
+result=$("$SHELL_BIN" -c '(echo hello)' 2>&1)
7878
 if [ "$result" = "hello" ]; then
7979
     pass "Basic subshell execution"
8080
 else
8181
     fail "Basic subshell execution" "hello" "$result"
8282
 fi
8383
 
84
-result=$("$FORTSH_BIN" -c 'x=outer; (x=inner; echo $x); echo $x' 2>&1)
84
+result=$("$SHELL_BIN" -c 'x=outer; (x=inner; echo $x); echo $x' 2>&1)
8585
 expected=$(printf "inner\nouter")
8686
 if [ "$result" = "$expected" ]; then
8787
     pass "Subshell variable isolation"
@@ -89,7 +89,7 @@ else
8989
     fail "Subshell variable isolation" "$expected" "$result"
9090
 fi
9191
 
92
-result=$("$FORTSH_BIN" -c '(cd /tmp; pwd); pwd' 2>&1)
92
+result=$("$SHELL_BIN" -c '(cd /tmp; pwd); pwd' 2>&1)
9393
 # Should show /tmp then original dir
9494
 if echo "$result" | head -1 | grep -q "/tmp"; then
9595
     pass "Subshell cd isolation"
@@ -97,14 +97,14 @@ else
9797
     fail "Subshell cd isolation" "/tmp then original" "$result"
9898
 fi
9999
 
100
-result=$("$FORTSH_BIN" -c '(exit 42); echo $?' 2>&1)
100
+result=$("$SHELL_BIN" -c '(exit 42); echo $?' 2>&1)
101101
 if [ "$result" = "42" ]; then
102102
     pass "Subshell exit status propagation"
103103
 else
104104
     fail "Subshell exit status propagation" "42" "$result"
105105
 fi
106106
 
107
-result=$("$FORTSH_BIN" -c '(echo a; echo b; echo c)' 2>&1)
107
+result=$("$SHELL_BIN" -c '(echo a; echo b; echo c)' 2>&1)
108108
 expected=$(printf "a\nb\nc")
109109
 if [ "$result" = "$expected" ]; then
110110
     pass "Subshell with multiple commands"
@@ -116,14 +116,14 @@ fi
116116
 section "412. BRACE GROUP { }"
117117
 # =====================================
118118
 
119
-result=$("$FORTSH_BIN" -c '{ echo hello; }' 2>&1)
119
+result=$("$SHELL_BIN" -c '{ echo hello; }' 2>&1)
120120
 if [ "$result" = "hello" ]; then
121121
     pass "Basic brace group"
122122
 else
123123
     fail "Basic brace group" "hello" "$result"
124124
 fi
125125
 
126
-result=$("$FORTSH_BIN" -c 'x=outer; { x=inner; echo $x; }; echo $x' 2>&1)
126
+result=$("$SHELL_BIN" -c 'x=outer; { x=inner; echo $x; }; echo $x' 2>&1)
127127
 expected=$(printf "inner\ninner")
128128
 if [ "$result" = "$expected" ]; then
129129
     pass "Brace group shares variable scope"
@@ -131,7 +131,7 @@ else
131131
     fail "Brace group shares variable scope" "$expected" "$result"
132132
 fi
133133
 
134
-result=$("$FORTSH_BIN" -c '{ echo a; echo b; echo c; }' 2>&1)
134
+result=$("$SHELL_BIN" -c '{ echo a; echo b; echo c; }' 2>&1)
135135
 expected=$(printf "a\nb\nc")
136136
 if [ "$result" = "$expected" ]; then
137137
     pass "Brace group with multiple commands"
@@ -139,7 +139,7 @@ else
139139
     fail "Brace group with multiple commands" "$expected" "$result"
140140
 fi
141141
 
142
-result=$("$FORTSH_BIN" -c '{ false; }; echo $?' 2>&1)
142
+result=$("$SHELL_BIN" -c '{ false; }; echo $?' 2>&1)
143143
 if [ "$result" = "1" ]; then
144144
     pass "Brace group exit status"
145145
 else
@@ -150,7 +150,7 @@ fi
150150
 section "413. BREAK WITH COUNT"
151151
 # =====================================
152152
 
153
-result=$("$FORTSH_BIN" -c '
153
+result=$("$SHELL_BIN" -c '
154154
 for i in 1 2 3; do
155155
     for j in a b c; do
156156
         if [ "$j" = "b" ]; then
@@ -166,7 +166,7 @@ else
166166
     fail "break exits inner loop" "$expected" "$result"
167167
 fi
168168
 
169
-result=$("$FORTSH_BIN" -c '
169
+result=$("$SHELL_BIN" -c '
170170
 for i in 1 2 3; do
171171
     for j in a b c; do
172172
         if [ "$j" = "b" ]; then
@@ -181,7 +181,7 @@ else
181181
     fail "break 2 exits both loops" "1a" "$result"
182182
 fi
183183
 
184
-result=$("$FORTSH_BIN" -c '
184
+result=$("$SHELL_BIN" -c '
185185
 for i in 1 2 3; do
186186
     break
187187
     echo "not reached"
@@ -197,7 +197,7 @@ fi
197197
 section "414. CONTINUE WITH COUNT"
198198
 # =====================================
199199
 
200
-result=$("$FORTSH_BIN" -c '
200
+result=$("$SHELL_BIN" -c '
201201
 for i in 1 2 3; do
202202
     if [ "$i" = "2" ]; then
203203
         continue
@@ -211,7 +211,7 @@ else
211211
     fail "continue skips iteration" "$expected" "$result"
212212
 fi
213213
 
214
-result=$("$FORTSH_BIN" -c '
214
+result=$("$SHELL_BIN" -c '
215215
 for i in 1 2; do
216216
     for j in a b c; do
217217
         if [ "$j" = "b" ]; then
@@ -232,7 +232,7 @@ fi
232232
 section "415. WHILE LOOP"
233233
 # =====================================
234234
 
235
-result=$("$FORTSH_BIN" -c 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
235
+result=$("$SHELL_BIN" -c 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
236236
 expected=$(printf "0\n1\n2")
237237
 if [ "$result" = "$expected" ]; then
238238
     pass "Basic while loop"
@@ -240,14 +240,14 @@ else
240240
     fail "Basic while loop" "$expected" "$result"
241241
 fi
242242
 
243
-result=$("$FORTSH_BIN" -c 'while false; do echo no; done; echo done' 2>&1)
243
+result=$("$SHELL_BIN" -c 'while false; do echo no; done; echo done' 2>&1)
244244
 if [ "$result" = "done" ]; then
245245
     pass "While with false condition"
246246
 else
247247
     fail "While with false condition" "done" "$result"
248248
 fi
249249
 
250
-result=$("$FORTSH_BIN" -c '
250
+result=$("$SHELL_BIN" -c '
251251
 i=0
252252
 while [ $i -lt 5 ]; do
253253
     i=$((i+1))
@@ -265,7 +265,7 @@ fi
265265
 section "416. UNTIL LOOP"
266266
 # =====================================
267267
 
268
-result=$("$FORTSH_BIN" -c 'i=0; until [ $i -ge 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
268
+result=$("$SHELL_BIN" -c 'i=0; until [ $i -ge 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
269269
 expected=$(printf "0\n1\n2")
270270
 if [ "$result" = "$expected" ]; then
271271
     pass "Basic until loop"
@@ -273,7 +273,7 @@ else
273273
     fail "Basic until loop" "$expected" "$result"
274274
 fi
275275
 
276
-result=$("$FORTSH_BIN" -c 'until true; do echo no; done; echo done' 2>&1)
276
+result=$("$SHELL_BIN" -c 'until true; do echo no; done; echo done' 2>&1)
277277
 if [ "$result" = "done" ]; then
278278
     pass "Until with true condition"
279279
 else
@@ -284,21 +284,21 @@ fi
284284
 section "417. PIPELINE EXIT STATUS"
285285
 # =====================================
286286
 
287
-result=$("$FORTSH_BIN" -c 'true | false; echo $?' 2>&1)
287
+result=$("$SHELL_BIN" -c 'true | false; echo $?' 2>&1)
288288
 if [ "$result" = "1" ]; then
289289
     pass "Pipeline exit status is last command"
290290
 else
291291
     fail "Pipeline exit status is last command" "1" "$result"
292292
 fi
293293
 
294
-result=$("$FORTSH_BIN" -c 'false | true; echo $?' 2>&1)
294
+result=$("$SHELL_BIN" -c 'false | true; echo $?' 2>&1)
295295
 if [ "$result" = "0" ]; then
296296
     pass "Pipeline with false then true"
297297
 else
298298
     fail "Pipeline with false then true" "0" "$result"
299299
 fi
300300
 
301
-result=$("$FORTSH_BIN" -c 'echo hello | cat | cat; echo $?' 2>&1)
301
+result=$("$SHELL_BIN" -c 'echo hello | cat | cat; echo $?' 2>&1)
302302
 expected=$(printf "hello\n0")
303303
 if [ "$result" = "$expected" ]; then
304304
     pass "Multi-stage pipeline"
@@ -310,35 +310,35 @@ fi
310310
 section "418. AND-OR LISTS"
311311
 # =====================================
312312
 
313
-result=$("$FORTSH_BIN" -c 'true && echo yes' 2>&1)
313
+result=$("$SHELL_BIN" -c 'true && echo yes' 2>&1)
314314
 if [ "$result" = "yes" ]; then
315315
     pass "&& executes on success"
316316
 else
317317
     fail "&& executes on success" "yes" "$result"
318318
 fi
319319
 
320
-result=$("$FORTSH_BIN" -c 'false && echo yes; echo done' 2>&1)
320
+result=$("$SHELL_BIN" -c 'false && echo yes; echo done' 2>&1)
321321
 if [ "$result" = "done" ]; then
322322
     pass "&& skips on failure"
323323
 else
324324
     fail "&& skips on failure" "done" "$result"
325325
 fi
326326
 
327
-result=$("$FORTSH_BIN" -c 'false || echo fallback' 2>&1)
327
+result=$("$SHELL_BIN" -c 'false || echo fallback' 2>&1)
328328
 if [ "$result" = "fallback" ]; then
329329
     pass "|| executes on failure"
330330
 else
331331
     fail "|| executes on failure" "fallback" "$result"
332332
 fi
333333
 
334
-result=$("$FORTSH_BIN" -c 'true || echo no; echo done' 2>&1)
334
+result=$("$SHELL_BIN" -c 'true || echo no; echo done' 2>&1)
335335
 if [ "$result" = "done" ]; then
336336
     pass "|| skips on success"
337337
 else
338338
     fail "|| skips on success" "done" "$result"
339339
 fi
340340
 
341
-result=$("$FORTSH_BIN" -c 'true && echo a && echo b' 2>&1)
341
+result=$("$SHELL_BIN" -c 'true && echo a && echo b' 2>&1)
342342
 expected=$(printf "a\nb")
343343
 if [ "$result" = "$expected" ]; then
344344
     pass "Chained && operators"
@@ -346,14 +346,14 @@ else
346346
     fail "Chained && operators" "$expected" "$result"
347347
 fi
348348
 
349
-result=$("$FORTSH_BIN" -c 'false || false || echo third' 2>&1)
349
+result=$("$SHELL_BIN" -c 'false || false || echo third' 2>&1)
350350
 if [ "$result" = "third" ]; then
351351
     pass "Chained || operators"
352352
 else
353353
     fail "Chained || operators" "third" "$result"
354354
 fi
355355
 
356
-result=$("$FORTSH_BIN" -c 'false || true && echo mixed' 2>&1)
356
+result=$("$SHELL_BIN" -c 'false || true && echo mixed' 2>&1)
357357
 if [ "$result" = "mixed" ]; then
358358
     pass "Mixed && and ||"
359359
 else
@@ -364,21 +364,21 @@ fi
364364
 section "419. NEGATION WITH !"
365365
 # =====================================
366366
 
367
-result=$("$FORTSH_BIN" -c '! false; echo $?' 2>&1)
367
+result=$("$SHELL_BIN" -c '! false; echo $?' 2>&1)
368368
 if [ "$result" = "0" ]; then
369369
     pass "! false returns 0"
370370
 else
371371
     fail "! false returns 0" "0" "$result"
372372
 fi
373373
 
374
-result=$("$FORTSH_BIN" -c '! true; echo $?' 2>&1)
374
+result=$("$SHELL_BIN" -c '! true; echo $?' 2>&1)
375375
 if [ "$result" = "1" ]; then
376376
     pass "! true returns 1"
377377
 else
378378
     fail "! true returns 1" "1" "$result"
379379
 fi
380380
 
381
-result=$("$FORTSH_BIN" -c '! echo hello >/dev/null; echo $?' 2>&1)
381
+result=$("$SHELL_BIN" -c '! echo hello >/dev/null; echo $?' 2>&1)
382382
 if [ "$result" = "1" ]; then
383383
     pass "! negates command exit status"
384384
 else
@@ -396,14 +396,14 @@ mkdir -p "$TEST_DIR"
396396
 echo 'SOURCED_VAR=hello' > "$TEST_DIR/sourceme.sh"
397397
 echo 'sourced_func() { echo "from func"; }' >> "$TEST_DIR/sourceme.sh"
398398
 
399
-result=$("$FORTSH_BIN" -c '. '"$TEST_DIR"'/sourceme.sh; echo $SOURCED_VAR' 2>&1)
399
+result=$("$SHELL_BIN" -c '. '"$TEST_DIR"'/sourceme.sh; echo $SOURCED_VAR' 2>&1)
400400
 if [ "$result" = "hello" ]; then
401401
     pass ". sources file and sets variable"
402402
 else
403403
     fail ". sources file and sets variable" "hello" "$result"
404404
 fi
405405
 
406
-result=$("$FORTSH_BIN" -c '. '"$TEST_DIR"'/sourceme.sh; sourced_func' 2>&1)
406
+result=$("$SHELL_BIN" -c '. '"$TEST_DIR"'/sourceme.sh; sourced_func' 2>&1)
407407
 if echo "$result" | grep -q "from func"; then
408408
     pass ". sources file and defines function"
409409
 else
@@ -412,7 +412,7 @@ fi
412412
 
413413
 # Test source with arguments
414414
 echo 'echo "arg1=$1 arg2=$2"' > "$TEST_DIR/withargs.sh"
415
-result=$("$FORTSH_BIN" -c '. '"$TEST_DIR"'/withargs.sh foo bar' 2>&1)
415
+result=$("$SHELL_BIN" -c '. '"$TEST_DIR"'/withargs.sh foo bar' 2>&1)
416416
 if [ "$result" = "arg1=foo arg2=bar" ]; then
417417
     pass ". passes arguments to sourced script"
418418
 else
@@ -425,7 +425,7 @@ rm -rf "$TEST_DIR"
425425
 section "421. EXEC BUILTIN"
426426
 # =====================================
427427
 
428
-result=$("$FORTSH_BIN" -c 'exec echo replaced' 2>&1)
428
+result=$("$SHELL_BIN" -c 'exec echo replaced' 2>&1)
429429
 if [ "$result" = "replaced" ]; then
430430
     pass "exec replaces shell with command"
431431
 else
@@ -433,7 +433,7 @@ else
433433
 fi
434434
 
435435
 # exec without command just does redirections
436
-result=$("$FORTSH_BIN" -c 'exec 2>/dev/null; echo hello' 2>&1)
436
+result=$("$SHELL_BIN" -c 'exec 2>/dev/null; echo hello' 2>&1)
437437
 if [ "$result" = "hello" ]; then
438438
     pass "exec without command continues shell"
439439
 else
@@ -444,28 +444,28 @@ fi
444444
 section "422. EVAL BUILTIN"
445445
 # =====================================
446446
 
447
-result=$("$FORTSH_BIN" -c 'cmd="echo hello"; eval $cmd' 2>&1)
447
+result=$("$SHELL_BIN" -c 'cmd="echo hello"; eval $cmd' 2>&1)
448448
 if [ "$result" = "hello" ]; then
449449
     pass "eval executes string as command"
450450
 else
451451
     fail "eval executes string as command" "hello" "$result"
452452
 fi
453453
 
454
-result=$("$FORTSH_BIN" -c 'x=world; eval echo "hello $x"' 2>&1)
454
+result=$("$SHELL_BIN" -c 'x=world; eval echo "hello $x"' 2>&1)
455455
 if [ "$result" = "hello world" ]; then
456456
     pass "eval with variable expansion"
457457
 else
458458
     fail "eval with variable expansion" "hello world" "$result"
459459
 fi
460460
 
461
-result=$("$FORTSH_BIN" -c 'eval "x=5; echo \$x"' 2>&1)
461
+result=$("$SHELL_BIN" -c 'eval "x=5; echo \$x"' 2>&1)
462462
 if [ "$result" = "5" ]; then
463463
     pass "eval with multiple commands"
464464
 else
465465
     fail "eval with multiple commands" "5" "$result"
466466
 fi
467467
 
468
-result=$("$FORTSH_BIN" -c 'var=x; eval "$var=42"; echo $x' 2>&1)
468
+result=$("$SHELL_BIN" -c 'var=x; eval "$var=42"; echo $x' 2>&1)
469469
 if [ "$result" = "42" ]; then
470470
     pass "eval for indirect assignment"
471471
 else
@@ -476,21 +476,21 @@ fi
476476
 section "423. RETURN FROM FUNCTION"
477477
 # =====================================
478478
 
479
-result=$("$FORTSH_BIN" -c 'f() { return 0; echo no; }; f; echo $?' 2>&1)
479
+result=$("$SHELL_BIN" -c 'f() { return 0; echo no; }; f; echo $?' 2>&1)
480480
 if [ "$result" = "0" ]; then
481481
     pass "return 0 from function"
482482
 else
483483
     fail "return 0 from function" "0" "$result"
484484
 fi
485485
 
486
-result=$("$FORTSH_BIN" -c 'f() { return 42; }; f; echo $?' 2>&1)
486
+result=$("$SHELL_BIN" -c 'f() { return 42; }; f; echo $?' 2>&1)
487487
 if [ "$result" = "42" ]; then
488488
     pass "return with status code"
489489
 else
490490
     fail "return with status code" "42" "$result"
491491
 fi
492492
 
493
-result=$("$FORTSH_BIN" -c 'f() { echo before; return; echo after; }; f' 2>&1)
493
+result=$("$SHELL_BIN" -c 'f() { echo before; return; echo after; }; f' 2>&1)
494494
 if [ "$result" = "before" ]; then
495495
     pass "return without value"
496496
 else
@@ -501,7 +501,7 @@ fi
501501
 section "424. FUNCTION LOCAL VARIABLES"
502502
 # =====================================
503503
 
504
-result=$("$FORTSH_BIN" -c 'x=global; f() { local x=local; echo $x; }; f; echo $x' 2>&1)
504
+result=$("$SHELL_BIN" -c 'x=global; f() { local x=local; echo $x; }; f; echo $x' 2>&1)
505505
 expected=$(printf "local\nglobal")
506506
 if [ "$result" = "$expected" ]; then
507507
     pass "local variable in function"
@@ -509,21 +509,21 @@ else
509509
     fail "local variable in function" "$expected" "$result"
510510
 fi
511511
 
512
-result=$("$FORTSH_BIN" -c 'f() { local x=1; g() { echo $x; }; g; }; f' 2>&1)
512
+result=$("$SHELL_BIN" -c 'f() { local x=1; g() { echo $x; }; g; }; f' 2>&1)
513513
 if [ "$result" = "1" ]; then
514514
     pass "local visible in nested function"
515515
 else
516516
     fail "local visible in nested function" "1" "$result"
517517
 fi
518518
 
519
-result=$("$FORTSH_BIN" -c 'f() { local a=1 b=2; echo $a $b; }; f' 2>&1)
519
+result=$("$SHELL_BIN" -c 'f() { local a=1 b=2; echo $a $b; }; f' 2>&1)
520520
 if [ "$result" = "1 2" ]; then
521521
     pass "local multiple variables"
522522
 else
523523
     fail "local multiple variables" "1 2" "$result"
524524
 fi
525525
 
526
-result=$("$FORTSH_BIN" -c 'f() { local x; x=set; echo $x; }; f' 2>&1)
526
+result=$("$SHELL_BIN" -c 'f() { local x; x=set; echo $x; }; f' 2>&1)
527527
 if [ "$result" = "set" ]; then
528528
     pass "local without initial value"
529529
 else
@@ -534,7 +534,7 @@ fi
534534
 section "425. FUNCTION RECURSION"
535535
 # =====================================
536536
 
537
-result=$("$FORTSH_BIN" -c '
537
+result=$("$SHELL_BIN" -c '
538538
 factorial() {
539539
     if [ $1 -le 1 ]; then
540540
         echo 1
@@ -550,7 +550,7 @@ else
550550
     fail "Recursive function (factorial)" "120" "$result"
551551
 fi
552552
 
553
-result=$("$FORTSH_BIN" -c '
553
+result=$("$SHELL_BIN" -c '
554554
 count=0
555555
 recurse() {
556556
     count=$((count + 1))
@@ -570,35 +570,35 @@ fi
570570
 section "426. FUNCTION ARGUMENTS"
571571
 # =====================================
572572
 
573
-result=$("$FORTSH_BIN" -c 'f() { echo $1 $2 $3; }; f a b c' 2>&1)
573
+result=$("$SHELL_BIN" -c 'f() { echo $1 $2 $3; }; f a b c' 2>&1)
574574
 if [ "$result" = "a b c" ]; then
575575
     pass "Function positional parameters"
576576
 else
577577
     fail "Function positional parameters" "a b c" "$result"
578578
 fi
579579
 
580
-result=$("$FORTSH_BIN" -c 'f() { echo $#; }; f a b c d e' 2>&1)
580
+result=$("$SHELL_BIN" -c 'f() { echo $#; }; f a b c d e' 2>&1)
581581
 if [ "$result" = "5" ]; then
582582
     pass "Function \$# count"
583583
 else
584584
     fail "Function \$# count" "5" "$result"
585585
 fi
586586
 
587
-result=$("$FORTSH_BIN" -c 'f() { echo "$@"; }; f "a b" c' 2>&1)
587
+result=$("$SHELL_BIN" -c 'f() { echo "$@"; }; f "a b" c' 2>&1)
588588
 if [ "$result" = "a b c" ]; then
589589
     pass "Function \$@ expansion"
590590
 else
591591
     fail "Function \$@ expansion" "a b c" "$result"
592592
 fi
593593
 
594
-result=$("$FORTSH_BIN" -c 'f() { shift; echo $1; }; f a b c' 2>&1)
594
+result=$("$SHELL_BIN" -c 'f() { shift; echo $1; }; f a b c' 2>&1)
595595
 if [ "$result" = "b" ]; then
596596
     pass "shift in function"
597597
 else
598598
     fail "shift in function" "b" "$result"
599599
 fi
600600
 
601
-result=$("$FORTSH_BIN" -c 'f() { set -- x y z; echo $1; }; f a b; echo done' 2>&1)
601
+result=$("$SHELL_BIN" -c 'f() { set -- x y z; echo $1; }; f a b; echo done' 2>&1)
602602
 expected=$(printf "x\ndone")
603603
 if [ "$result" = "$expected" ]; then
604604
     pass "set -- in function is local"
@@ -610,14 +610,14 @@ fi
610610
 section "427. FUNCTION OVERRIDE"
611611
 # =====================================
612612
 
613
-result=$("$FORTSH_BIN" -c 'f() { echo first; }; f() { echo second; }; f' 2>&1)
613
+result=$("$SHELL_BIN" -c 'f() { echo first; }; f() { echo second; }; f' 2>&1)
614614
 if [ "$result" = "second" ]; then
615615
     pass "Function redefinition"
616616
 else
617617
     fail "Function redefinition" "second" "$result"
618618
 fi
619619
 
620
-result=$("$FORTSH_BIN" -c 'f() { echo orig; }; g() { f; }; f() { echo new; }; g' 2>&1)
620
+result=$("$SHELL_BIN" -c 'f() { echo orig; }; g() { f; }; f() { echo new; }; g' 2>&1)
621621
 if [ "$result" = "new" ]; then
622622
     pass "Function sees redefined function"
623623
 else
@@ -628,7 +628,7 @@ fi
628628
 section "428. UNSET FUNCTION"
629629
 # =====================================
630630
 
631
-result=$("$FORTSH_BIN" -c 'f() { echo hi; }; unset -f f; f 2>/dev/null; echo $?' 2>&1)
631
+result=$("$SHELL_BIN" -c 'f() { echo hi; }; unset -f f; f 2>/dev/null; echo $?' 2>&1)
632632
 if echo "$result" | grep -qE "127|1"; then
633633
     pass "unset -f removes function"
634634
 else
@@ -639,21 +639,21 @@ fi
639639
 section "429. COLON BUILTIN"
640640
 # =====================================
641641
 
642
-result=$("$FORTSH_BIN" -c ':; echo $?' 2>&1)
642
+result=$("$SHELL_BIN" -c ':; echo $?' 2>&1)
643643
 if [ "$result" = "0" ]; then
644644
     pass ": returns 0"
645645
 else
646646
     fail ": returns 0" "0" "$result"
647647
 fi
648648
 
649
-result=$("$FORTSH_BIN" -c ': this is ignored; echo ok' 2>&1)
649
+result=$("$SHELL_BIN" -c ': this is ignored; echo ok' 2>&1)
650650
 if [ "$result" = "ok" ]; then
651651
     pass ": ignores arguments"
652652
 else
653653
     fail ": ignores arguments" "ok" "$result"
654654
 fi
655655
 
656
-result=$("$FORTSH_BIN" -c ': ${x:=default}; echo $x' 2>&1)
656
+result=$("$SHELL_BIN" -c ': ${x:=default}; echo $x' 2>&1)
657657
 if [ "$result" = "default" ]; then
658658
     pass ": for side effects in expansion"
659659
 else
@@ -664,14 +664,14 @@ fi
664664
 section "426. TRUE AND FALSE BUILTINS"
665665
 # =====================================
666666
 
667
-result=$("$FORTSH_BIN" -c 'true; echo $?' 2>&1)
667
+result=$("$SHELL_BIN" -c 'true; echo $?' 2>&1)
668668
 if [ "$result" = "0" ]; then
669669
     pass "true returns 0"
670670
 else
671671
     fail "true returns 0" "0" "$result"
672672
 fi
673673
 
674
-result=$("$FORTSH_BIN" -c 'false; echo $?' 2>&1)
674
+result=$("$SHELL_BIN" -c 'false; echo $?' 2>&1)
675675
 if [ "$result" = "1" ]; then
676676
     pass "false returns 1"
677677
 else
@@ -682,14 +682,14 @@ fi
682682
 section "427. EXIT BUILTIN"
683683
 # =====================================
684684
 
685
-result=$("$FORTSH_BIN" -c 'exit 0; echo no' 2>&1)
685
+result=$("$SHELL_BIN" -c 'exit 0; echo no' 2>&1)
686686
 if [ -z "$result" ]; then
687687
     pass "exit 0 terminates immediately"
688688
 else
689689
     fail "exit 0 terminates immediately" "(empty)" "$result"
690690
 fi
691691
 
692
-result=$("$FORTSH_BIN" -c 'exit 42' 2>&1)
692
+result=$("$SHELL_BIN" -c 'exit 42' 2>&1)
693693
 code=$?
694694
 if [ $code -eq 42 ]; then
695695
     pass "exit with specific code"
@@ -697,7 +697,7 @@ else
697697
     fail "exit with specific code" "42" "$code"
698698
 fi
699699
 
700
-result=$("$FORTSH_BIN" -c 'false; exit' 2>&1)
700
+result=$("$SHELL_BIN" -c 'false; exit' 2>&1)
701701
 code=$?
702702
 if [ $code -eq 1 ]; then
703703
     pass "exit without arg uses last status"
@@ -710,7 +710,7 @@ section "430. CASE STATEMENT PATTERNS"
710710
 # =====================================
711711
 
712712
 # Simple exact match
713
-result=$("$FORTSH_BIN" -c 'case "hello" in hello) echo yes;; esac' 2>&1)
713
+result=$("$SHELL_BIN" -c 'case "hello" in hello) echo yes;; esac' 2>&1)
714714
 if [ "$result" = "yes" ]; then
715715
     pass "case exact match"
716716
 else
@@ -718,7 +718,7 @@ else
718718
 fi
719719
 
720720
 # Glob pattern match
721
-result=$("$FORTSH_BIN" -c 'case "hello" in h*) echo yes;; esac' 2>&1)
721
+result=$("$SHELL_BIN" -c 'case "hello" in h*) echo yes;; esac' 2>&1)
722722
 if [ "$result" = "yes" ]; then
723723
     pass "case glob pattern"
724724
 else
@@ -726,7 +726,7 @@ else
726726
 fi
727727
 
728728
 # Question mark match
729
-result=$("$FORTSH_BIN" -c 'case "cat" in c?t) echo yes;; esac' 2>&1)
729
+result=$("$SHELL_BIN" -c 'case "cat" in c?t) echo yes;; esac' 2>&1)
730730
 if [ "$result" = "yes" ]; then
731731
     pass "case ? pattern"
732732
 else
@@ -734,7 +734,7 @@ else
734734
 fi
735735
 
736736
 # Bracket pattern
737
-result=$("$FORTSH_BIN" -c 'case "b" in [abc]) echo yes;; esac' 2>&1)
737
+result=$("$SHELL_BIN" -c 'case "b" in [abc]) echo yes;; esac' 2>&1)
738738
 if [ "$result" = "yes" ]; then
739739
     pass "case [abc] bracket pattern"
740740
 else
@@ -742,7 +742,7 @@ else
742742
 fi
743743
 
744744
 # Multiple patterns with |
745
-result=$("$FORTSH_BIN" -c 'case "two" in one|two|three) echo yes;; esac' 2>&1)
745
+result=$("$SHELL_BIN" -c 'case "two" in one|two|three) echo yes;; esac' 2>&1)
746746
 if [ "$result" = "yes" ]; then
747747
     pass "case multiple patterns with |"
748748
 else
@@ -750,7 +750,7 @@ else
750750
 fi
751751
 
752752
 # Default pattern *
753
-result=$("$FORTSH_BIN" -c 'case "xyz" in abc) echo no;; *) echo default;; esac' 2>&1)
753
+result=$("$SHELL_BIN" -c 'case "xyz" in abc) echo no;; *) echo default;; esac' 2>&1)
754754
 if [ "$result" = "default" ]; then
755755
     pass "case * default pattern"
756756
 else
@@ -758,7 +758,7 @@ else
758758
 fi
759759
 
760760
 # No match produces nothing
761
-result=$("$FORTSH_BIN" -c 'case "x" in y) echo no;; z) echo also no;; esac; echo done' 2>&1)
761
+result=$("$SHELL_BIN" -c 'case "x" in y) echo no;; z) echo also no;; esac; echo done' 2>&1)
762762
 if [ "$result" = "done" ]; then
763763
     pass "case no match produces empty"
764764
 else
@@ -766,7 +766,7 @@ else
766766
 fi
767767
 
768768
 # Variable in word
769
-result=$("$FORTSH_BIN" -c 'x=hello; case "$x" in hello) echo yes;; esac' 2>&1)
769
+result=$("$SHELL_BIN" -c 'x=hello; case "$x" in hello) echo yes;; esac' 2>&1)
770770
 if [ "$result" = "yes" ]; then
771771
     pass "case with variable in word"
772772
 else
@@ -774,7 +774,7 @@ else
774774
 fi
775775
 
776776
 # Variable in pattern
777
-result=$("$FORTSH_BIN" -c 'pat="hel*"; case "hello" in $pat) echo yes;; *) echo no;; esac' 2>&1)
777
+result=$("$SHELL_BIN" -c 'pat="hel*"; case "hello" in $pat) echo yes;; *) echo no;; esac' 2>&1)
778778
 if [ "$result" = "yes" ]; then
779779
     pass "case with variable in pattern"
780780
 else
@@ -782,7 +782,7 @@ else
782782
 fi
783783
 
784784
 # Quoted pattern (literal)
785
-result=$("$FORTSH_BIN" -c 'case "h*" in "h*") echo yes;; esac' 2>&1)
785
+result=$("$SHELL_BIN" -c 'case "h*" in "h*") echo yes;; esac' 2>&1)
786786
 if [ "$result" = "yes" ]; then
787787
     pass "case quoted pattern is literal"
788788
 else
@@ -794,7 +794,7 @@ section "431. NESTED CONTROL STRUCTURES"
794794
 # =====================================
795795
 
796796
 # if inside for
797
-result=$("$FORTSH_BIN" -c 'for i in 1 2 3; do if [ $i -eq 2 ]; then echo found; fi; done' 2>&1)
797
+result=$("$SHELL_BIN" -c 'for i in 1 2 3; do if [ $i -eq 2 ]; then echo found; fi; done' 2>&1)
798798
 if [ "$result" = "found" ]; then
799799
     pass "if inside for loop"
800800
 else
@@ -802,7 +802,7 @@ else
802802
 fi
803803
 
804804
 # case inside while
805
-result=$("$FORTSH_BIN" -c 'i=0; while [ $i -lt 3 ]; do case $i in 1) echo one;; esac; i=$((i+1)); done' 2>&1)
805
+result=$("$SHELL_BIN" -c 'i=0; while [ $i -lt 3 ]; do case $i in 1) echo one;; esac; i=$((i+1)); done' 2>&1)
806806
 if [ "$result" = "one" ]; then
807807
     pass "case inside while loop"
808808
 else
@@ -810,7 +810,7 @@ else
810810
 fi
811811
 
812812
 # for inside if
813
-result=$("$FORTSH_BIN" -c 'if true; then for i in a b; do echo $i; done; fi' 2>&1)
813
+result=$("$SHELL_BIN" -c 'if true; then for i in a b; do echo $i; done; fi' 2>&1)
814814
 expected=$(printf "a\nb")
815815
 if [ "$result" = "$expected" ]; then
816816
     pass "for inside if"
@@ -819,7 +819,7 @@ else
819819
 fi
820820
 
821821
 # Deeply nested
822
-result=$("$FORTSH_BIN" -c '
822
+result=$("$SHELL_BIN" -c '
823823
 for i in 1; do
824824
     for j in 2; do
825825
         for k in 3; do
@@ -838,7 +838,7 @@ section "432. WHILE AND UNTIL LOOPS"
838838
 # =====================================
839839
 
840840
 # while with counter
841
-result=$("$FORTSH_BIN" -c 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
841
+result=$("$SHELL_BIN" -c 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
842842
 expected=$(printf "0\n1\n2")
843843
 if [ "$result" = "$expected" ]; then
844844
     pass "while loop with counter"
@@ -847,7 +847,7 @@ else
847847
 fi
848848
 
849849
 # until loop
850
-result=$("$FORTSH_BIN" -c 'i=0; until [ $i -ge 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
850
+result=$("$SHELL_BIN" -c 'i=0; until [ $i -ge 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
851851
 expected=$(printf "0\n1\n2")
852852
 if [ "$result" = "$expected" ]; then
853853
     pass "until loop"
@@ -856,7 +856,7 @@ else
856856
 fi
857857
 
858858
 # while with compound condition
859
-result=$("$FORTSH_BIN" -c 'i=0; while [ $i -lt 5 ] && [ $i -ne 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
859
+result=$("$SHELL_BIN" -c 'i=0; while [ $i -lt 5 ] && [ $i -ne 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
860860
 expected=$(printf "0\n1\n2")
861861
 if [ "$result" = "$expected" ]; then
862862
     pass "while with compound condition"
@@ -865,7 +865,7 @@ else
865865
 fi
866866
 
867867
 # Empty while body (using :)
868
-result=$("$FORTSH_BIN" -c 'i=0; while [ $i -lt 3 ]; do : ; i=$((i+1)); done; echo $i' 2>&1)
868
+result=$("$SHELL_BIN" -c 'i=0; while [ $i -lt 3 ]; do : ; i=$((i+1)); done; echo $i' 2>&1)
869869
 if [ "$result" = "3" ]; then
870870
     pass "while with empty body (colon)"
871871
 else
@@ -877,7 +877,7 @@ section "433. BREAK AND CONTINUE"
877877
 # =====================================
878878
 
879879
 # break in while
880
-result=$("$FORTSH_BIN" -c 'i=0; while true; do i=$((i+1)); [ $i -ge 3 ] && break; done; echo $i' 2>&1)
880
+result=$("$SHELL_BIN" -c 'i=0; while true; do i=$((i+1)); [ $i -ge 3 ] && break; done; echo $i' 2>&1)
881881
 if [ "$result" = "3" ]; then
882882
     pass "break in while loop"
883883
 else
@@ -885,7 +885,7 @@ else
885885
 fi
886886
 
887887
 # continue in for
888
-result=$("$FORTSH_BIN" -c 'for i in 1 2 3 4 5; do [ $i -eq 3 ] && continue; echo $i; done' 2>&1)
888
+result=$("$SHELL_BIN" -c 'for i in 1 2 3 4 5; do [ $i -eq 3 ] && continue; echo $i; done' 2>&1)
889889
 expected=$(printf "1\n2\n4\n5")
890890
 if [ "$result" = "$expected" ]; then
891891
     pass "continue in for loop"
@@ -894,7 +894,7 @@ else
894894
 fi
895895
 
896896
 # break N for nested loops
897
-result=$("$FORTSH_BIN" -c '
897
+result=$("$SHELL_BIN" -c '
898898
 for i in 1 2; do
899899
     for j in a b; do
900900
         echo "$i$j"
@@ -910,7 +910,7 @@ else
910910
 fi
911911
 
912912
 # continue N for nested loops
913
-result=$("$FORTSH_BIN" -c '
913
+result=$("$SHELL_BIN" -c '
914914
 for i in 1 2; do
915915
     for j in a b; do
916916
         [ "$i$j" = "1a" ] && continue 2
@@ -929,7 +929,7 @@ section "434. FOR LOOP VARIATIONS"
929929
 # =====================================
930930
 
931931
 # for without in (uses positional params)
932
-result=$("$FORTSH_BIN" -c 'set -- a b c; for x; do echo $x; done' 2>&1)
932
+result=$("$SHELL_BIN" -c 'set -- a b c; for x; do echo $x; done' 2>&1)
933933
 expected=$(printf "a\nb\nc")
934934
 if [ "$result" = "$expected" ]; then
935935
     pass "for without 'in' uses \$@"
@@ -939,7 +939,7 @@ fi
939939
 
940940
 # for with glob pattern
941941
 # Create temp files for glob test
942
-result=$("$FORTSH_BIN" -c 'cd /tmp && touch _testglob_a _testglob_b && for f in _testglob_*; do echo $f; done | wc -l && rm -f _testglob_*' 2>&1 | head -1)
942
+result=$("$SHELL_BIN" -c 'cd /tmp && touch _testglob_a _testglob_b && for f in _testglob_*; do echo $f; done | wc -l && rm -f _testglob_*' 2>&1 | head -1)
943943
 if [ "$result" -eq 2 ] 2>/dev/null; then
944944
     pass "for with glob expansion"
945945
 else
@@ -947,7 +947,7 @@ else
947947
 fi
948948
 
949949
 # for with command substitution
950
-result=$("$FORTSH_BIN" -c 'for x in $(echo a b c); do echo $x; done' 2>&1)
950
+result=$("$SHELL_BIN" -c 'for x in $(echo a b c); do echo $x; done' 2>&1)
951951
 expected=$(printf "a\nb\nc")
952952
 if [ "$result" = "$expected" ]; then
953953
     pass "for with command substitution"
@@ -956,7 +956,7 @@ else
956956
 fi
957957
 
958958
 # for with quoted string (single iteration)
959
-result=$("$FORTSH_BIN" -c 'for x in "a b c"; do echo "[$x]"; done' 2>&1)
959
+result=$("$SHELL_BIN" -c 'for x in "a b c"; do echo "[$x]"; done' 2>&1)
960960
 if [ "$result" = "[a b c]" ]; then
961961
     pass "for with quoted string (single iteration)"
962962
 else
@@ -968,7 +968,7 @@ section "435. WHILE LOOP VARIATIONS"
968968
 # =====================================
969969
 
970970
 # while with pipeline
971
-result=$("$FORTSH_BIN" -c 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done | wc -l' 2>&1)
971
+result=$("$SHELL_BIN" -c 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done | wc -l' 2>&1)
972972
 if [ "$result" -eq 3 ] 2>/dev/null; then
973973
     pass "while loop with pipeline"
974974
 else
@@ -976,7 +976,7 @@ else
976976
 fi
977977
 
978978
 # while with command substitution condition
979
-result=$("$FORTSH_BIN" -c 'X=yes; while [ "$X" = "yes" ]; do echo once; X=no; done' 2>&1)
979
+result=$("$SHELL_BIN" -c 'X=yes; while [ "$X" = "yes" ]; do echo once; X=no; done' 2>&1)
980980
 if [ "$result" = "once" ]; then
981981
     pass "while with variable condition"
982982
 else
@@ -984,7 +984,7 @@ else
984984
 fi
985985
 
986986
 # infinite while with break
987
-result=$("$FORTSH_BIN" -c 'i=0; while true; do i=$((i+1)); [ $i -ge 5 ] && break; done; echo $i' 2>&1)
987
+result=$("$SHELL_BIN" -c 'i=0; while true; do i=$((i+1)); [ $i -ge 5 ] && break; done; echo $i' 2>&1)
988988
 if [ "$result" = "5" ]; then
989989
     pass "infinite while with break"
990990
 else
@@ -996,7 +996,7 @@ section "436. UNTIL LOOP VARIATIONS"
996996
 # =====================================
997997
 
998998
 # until basic
999
-result=$("$FORTSH_BIN" -c 'i=0; until [ $i -ge 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
999
+result=$("$SHELL_BIN" -c 'i=0; until [ $i -ge 3 ]; do echo $i; i=$((i+1)); done' 2>&1)
10001000
 expected=$(printf "0\n1\n2")
10011001
 if [ "$result" = "$expected" ]; then
10021002
     pass "until loop basic"
@@ -1005,7 +1005,7 @@ else
10051005
 fi
10061006
 
10071007
 # until with break
1008
-result=$("$FORTSH_BIN" -c 'i=0; until false; do i=$((i+1)); [ $i -ge 3 ] && break; done; echo $i' 2>&1)
1008
+result=$("$SHELL_BIN" -c 'i=0; until false; do i=$((i+1)); [ $i -ge 3 ] && break; done; echo $i' 2>&1)
10091009
 if [ "$result" = "3" ]; then
10101010
     pass "until with break"
10111011
 else
@@ -1017,7 +1017,7 @@ section "437. IF STATEMENT VARIATIONS"
10171017
 # =====================================
10181018
 
10191019
 # if with command
1020
-result=$("$FORTSH_BIN" -c 'if true; then echo yes; fi' 2>&1)
1020
+result=$("$SHELL_BIN" -c 'if true; then echo yes; fi' 2>&1)
10211021
 if [ "$result" = "yes" ]; then
10221022
     pass "if with true command"
10231023
 else
@@ -1025,7 +1025,7 @@ else
10251025
 fi
10261026
 
10271027
 # if with test
1028
-result=$("$FORTSH_BIN" -c 'X=5; if [ $X -gt 3 ]; then echo big; fi' 2>&1)
1028
+result=$("$SHELL_BIN" -c 'X=5; if [ $X -gt 3 ]; then echo big; fi' 2>&1)
10291029
 if [ "$result" = "big" ]; then
10301030
     pass "if with test condition"
10311031
 else
@@ -1033,7 +1033,7 @@ else
10331033
 fi
10341034
 
10351035
 # if-else
1036
-result=$("$FORTSH_BIN" -c 'if false; then echo no; else echo yes; fi' 2>&1)
1036
+result=$("$SHELL_BIN" -c 'if false; then echo no; else echo yes; fi' 2>&1)
10371037
 if [ "$result" = "yes" ]; then
10381038
     pass "if-else statement"
10391039
 else
@@ -1041,7 +1041,7 @@ else
10411041
 fi
10421042
 
10431043
 # if-elif-else
1044
-result=$("$FORTSH_BIN" -c 'X=2; if [ $X -eq 1 ]; then echo one; elif [ $X -eq 2 ]; then echo two; else echo other; fi' 2>&1)
1044
+result=$("$SHELL_BIN" -c 'X=2; if [ $X -eq 1 ]; then echo one; elif [ $X -eq 2 ]; then echo two; else echo other; fi' 2>&1)
10451045
 if [ "$result" = "two" ]; then
10461046
     pass "if-elif-else statement"
10471047
 else
@@ -1049,7 +1049,7 @@ else
10491049
 fi
10501050
 
10511051
 # nested if
1052
-result=$("$FORTSH_BIN" -c 'X=1; Y=2; if [ $X -eq 1 ]; then if [ $Y -eq 2 ]; then echo both; fi; fi' 2>&1)
1052
+result=$("$SHELL_BIN" -c 'X=1; Y=2; if [ $X -eq 1 ]; then if [ $Y -eq 2 ]; then echo both; fi; fi' 2>&1)
10531053
 if [ "$result" = "both" ]; then
10541054
     pass "nested if statement"
10551055
 else
@@ -1061,7 +1061,7 @@ section "438. CASE STATEMENT VARIATIONS"
10611061
 # =====================================
10621062
 
10631063
 # case with character class
1064
-result=$("$FORTSH_BIN" -c 'x=5; case $x in [0-9]) echo digit;; esac' 2>&1)
1064
+result=$("$SHELL_BIN" -c 'x=5; case $x in [0-9]) echo digit;; esac' 2>&1)
10651065
 if [ "$result" = "digit" ]; then
10661066
     pass "case with character class"
10671067
 else
@@ -1069,7 +1069,7 @@ else
10691069
 fi
10701070
 
10711071
 # case with negation
1072
-result=$("$FORTSH_BIN" -c 'x=x; case $x in [!0-9]) echo not_digit;; esac' 2>&1)
1072
+result=$("$SHELL_BIN" -c 'x=x; case $x in [!0-9]) echo not_digit;; esac' 2>&1)
10731073
 if [ "$result" = "not_digit" ]; then
10741074
     pass "case with negation"
10751075
 else
@@ -1077,7 +1077,7 @@ else
10771077
 fi
10781078
 
10791079
 # case with question mark
1080
-result=$("$FORTSH_BIN" -c 'x=ab; case $x in ??) echo two_chars;; esac' 2>&1)
1080
+result=$("$SHELL_BIN" -c 'x=ab; case $x in ??) echo two_chars;; esac' 2>&1)
10811081
 if [ "$result" = "two_chars" ]; then
10821082
     pass "case with question mark pattern"
10831083
 else
@@ -1085,7 +1085,7 @@ else
10851085
 fi
10861086
 
10871087
 # case fall-through (first match wins)
1088
-result=$("$FORTSH_BIN" -c 'x=a; case $x in a) echo first;; a) echo second;; esac' 2>&1)
1088
+result=$("$SHELL_BIN" -c 'x=a; case $x in a) echo first;; a) echo second;; esac' 2>&1)
10891089
 if [ "$result" = "first" ]; then
10901090
     pass "case first match wins"
10911091
 else
@@ -1097,7 +1097,7 @@ section "439. BRACE GROUP VARIATIONS"
10971097
 # =====================================
10981098
 
10991099
 # brace group in pipeline
1100
-result=$("$FORTSH_BIN" -c '{ echo a; echo b; } | wc -l' 2>&1)
1100
+result=$("$SHELL_BIN" -c '{ echo a; echo b; } | wc -l' 2>&1)
11011101
 if [ "$result" -eq 2 ] 2>/dev/null; then
11021102
     pass "brace group in pipeline"
11031103
 else
@@ -1105,7 +1105,7 @@ else
11051105
 fi
11061106
 
11071107
 # brace group with redirection
1108
-result=$("$FORTSH_BIN" -c '{ echo test; } > /tmp/brace_test_$$; cat /tmp/brace_test_$$; rm /tmp/brace_test_$$' 2>&1)
1108
+result=$("$SHELL_BIN" -c '{ echo test; } > /tmp/brace_test_$$; cat /tmp/brace_test_$$; rm /tmp/brace_test_$$' 2>&1)
11091109
 if [ "$result" = "test" ]; then
11101110
     pass "brace group with redirection"
11111111
 else
@@ -1113,7 +1113,7 @@ else
11131113
 fi
11141114
 
11151115
 # brace group preserves variables
1116
-result=$("$FORTSH_BIN" -c 'X=1; { X=2; }; echo $X' 2>&1)
1116
+result=$("$SHELL_BIN" -c 'X=1; { X=2; }; echo $X' 2>&1)
11171117
 if [ "$result" = "2" ]; then
11181118
     pass "brace group preserves variable changes"
11191119
 else
@@ -1125,7 +1125,7 @@ section "440. SUBSHELL VARIATIONS"
11251125
 # =====================================
11261126
 
11271127
 # subshell in pipeline
1128
-result=$("$FORTSH_BIN" -c '(echo a; echo b) | wc -l' 2>&1)
1128
+result=$("$SHELL_BIN" -c '(echo a; echo b) | wc -l' 2>&1)
11291129
 if [ "$result" -eq 2 ] 2>/dev/null; then
11301130
     pass "subshell in pipeline"
11311131
 else
@@ -1133,7 +1133,7 @@ else
11331133
 fi
11341134
 
11351135
 # subshell isolates variables
1136
-result=$("$FORTSH_BIN" -c 'X=1; (X=2); echo $X' 2>&1)
1136
+result=$("$SHELL_BIN" -c 'X=1; (X=2); echo $X' 2>&1)
11371137
 if [ "$result" = "1" ]; then
11381138
     pass "subshell isolates variable changes"
11391139
 else
@@ -1142,7 +1142,7 @@ fi
11421142
 
11431143
 # Note: (( )) is arithmetic syntax in bash, not nested subshell
11441144
 # Both bash and fortsh correctly treat this as arithmetic and error
1145
-"$FORTSH_BIN" -c '((echo deep))' >/dev/null 2>&1
1145
+"$SHELL_BIN" -c '((echo deep))' >/dev/null 2>&1
11461146
 fortsh_exit=$?
11471147
 "$BASH_REF" -c '((echo deep))' >/dev/null 2>&1
11481148
 bash_exit=$?
@@ -1157,7 +1157,7 @@ section "441. COMPOUND LIST VARIATIONS"
11571157
 # =====================================
11581158
 
11591159
 # semicolon separated
1160
-result=$("$FORTSH_BIN" -c 'echo a; echo b; echo c' 2>&1)
1160
+result=$("$SHELL_BIN" -c 'echo a; echo b; echo c' 2>&1)
11611161
 expected=$(printf "a\nb\nc")
11621162
 if [ "$result" = "$expected" ]; then
11631163
     pass "semicolon separated commands"
@@ -1166,7 +1166,7 @@ else
11661166
 fi
11671167
 
11681168
 # newline separated
1169
-result=$("$FORTSH_BIN" -c 'echo a
1169
+result=$("$SHELL_BIN" -c 'echo a
11701170
 echo b
11711171
 echo c' 2>&1)
11721172
 expected=$(printf "a\nb\nc")
@@ -1181,7 +1181,7 @@ section "442. LOGICAL OPERATORS VARIATIONS"
11811181
 # =====================================
11821182
 
11831183
 # && chain
1184
-result=$("$FORTSH_BIN" -c 'true && true && echo success' 2>&1)
1184
+result=$("$SHELL_BIN" -c 'true && true && echo success' 2>&1)
11851185
 if [ "$result" = "success" ]; then
11861186
     pass "&& chain all true"
11871187
 else
@@ -1189,7 +1189,7 @@ else
11891189
 fi
11901190
 
11911191
 # && short-circuit
1192
-result=$("$FORTSH_BIN" -c 'false && echo never' 2>&1)
1192
+result=$("$SHELL_BIN" -c 'false && echo never' 2>&1)
11931193
 if [ -z "$result" ]; then
11941194
     pass "&& short-circuits on false"
11951195
 else
@@ -1197,7 +1197,7 @@ else
11971197
 fi
11981198
 
11991199
 # || chain
1200
-result=$("$FORTSH_BIN" -c 'false || false || echo fallback' 2>&1)
1200
+result=$("$SHELL_BIN" -c 'false || false || echo fallback' 2>&1)
12011201
 if [ "$result" = "fallback" ]; then
12021202
     pass "|| chain with fallback"
12031203
 else
@@ -1205,7 +1205,7 @@ else
12051205
 fi
12061206
 
12071207
 # || short-circuit
1208
-result=$("$FORTSH_BIN" -c 'true || echo never' 2>&1)
1208
+result=$("$SHELL_BIN" -c 'true || echo never' 2>&1)
12091209
 if [ -z "$result" ]; then
12101210
     pass "|| short-circuits on true"
12111211
 else
@@ -1213,7 +1213,7 @@ else
12131213
 fi
12141214
 
12151215
 # mixed && and ||
1216
-result=$("$FORTSH_BIN" -c 'false && echo no || echo yes' 2>&1)
1216
+result=$("$SHELL_BIN" -c 'false && echo no || echo yes' 2>&1)
12171217
 if [ "$result" = "yes" ]; then
12181218
     pass "mixed && and ||"
12191219
 else
@@ -1225,14 +1225,14 @@ section "443. NEGATION WITH !"
12251225
 # =====================================
12261226
 
12271227
 # ! negates exit status
1228
-result=$("$FORTSH_BIN" -c '! false && echo success' 2>&1)
1228
+result=$("$SHELL_BIN" -c '! false && echo success' 2>&1)
12291229
 if [ "$result" = "success" ]; then
12301230
     pass "! negates false to true"
12311231
 else
12321232
     fail "! negates false to true" "success" "$result"
12331233
 fi
12341234
 
1235
-result=$("$FORTSH_BIN" -c '! true || echo failed' 2>&1)
1235
+result=$("$SHELL_BIN" -c '! true || echo failed' 2>&1)
12361236
 if [ "$result" = "failed" ]; then
12371237
     pass "! negates true to false"
12381238
 else
@@ -1240,7 +1240,7 @@ else
12401240
 fi
12411241
 
12421242
 # ! with pipeline
1243
-result=$("$FORTSH_BIN" -c '! echo test | grep -q nomatch && echo ok' 2>&1)
1243
+result=$("$SHELL_BIN" -c '! echo test | grep -q nomatch && echo ok' 2>&1)
12441244
 if [ "$result" = "ok" ]; then
12451245
     pass "! with pipeline"
12461246
 else
@@ -1252,7 +1252,7 @@ section "444. FUNCTION DEFINITIONS"
12521252
 # =====================================
12531253
 
12541254
 # function with return
1255
-result=$("$FORTSH_BIN" -c 'f() { return 42; }; f; echo $?' 2>&1)
1255
+result=$("$SHELL_BIN" -c 'f() { return 42; }; f; echo $?' 2>&1)
12561256
 if [ "$result" = "42" ]; then
12571257
     pass "function with return value"
12581258
 else
@@ -1260,7 +1260,7 @@ else
12601260
 fi
12611261
 
12621262
 # function with arguments
1263
-result=$("$FORTSH_BIN" -c 'greet() { echo "Hello, $1"; }; greet World' 2>&1)
1263
+result=$("$SHELL_BIN" -c 'greet() { echo "Hello, $1"; }; greet World' 2>&1)
12641264
 if [ "$result" = "Hello, World" ]; then
12651265
     pass "function with arguments"
12661266
 else
@@ -1268,7 +1268,7 @@ else
12681268
 fi
12691269
 
12701270
 # function calling function
1271
-result=$("$FORTSH_BIN" -c 'a() { b; }; b() { echo called; }; a' 2>&1)
1271
+result=$("$SHELL_BIN" -c 'a() { b; }; b() { echo called; }; a' 2>&1)
12721272
 if [ "$result" = "called" ]; then
12731273
     pass "function calling function"
12741274
 else
@@ -1280,7 +1280,7 @@ section "445. EXIT AND RETURN"
12801280
 # =====================================
12811281
 
12821282
 # exit from subshell
1283
-result=$("$FORTSH_BIN" -c '(exit 7); echo $?' 2>&1)
1283
+result=$("$SHELL_BIN" -c '(exit 7); echo $?' 2>&1)
12841284
 if [ "$result" = "7" ]; then
12851285
     pass "exit from subshell"
12861286
 else
@@ -1288,7 +1288,7 @@ else
12881288
 fi
12891289
 
12901290
 # return from function
1291
-result=$("$FORTSH_BIN" -c 'f() { echo before; return; echo after; }; f' 2>&1)
1291
+result=$("$SHELL_BIN" -c 'f() { echo before; return; echo after; }; f' 2>&1)
12921292
 if [ "$result" = "before" ]; then
12931293
     pass "return stops function execution"
12941294
 else
@@ -1296,7 +1296,7 @@ else
12961296
 fi
12971297
 
12981298
 # return default value
1299
-result=$("$FORTSH_BIN" -c 'f() { true; return; }; f; echo $?' 2>&1)
1299
+result=$("$SHELL_BIN" -c 'f() { true; return; }; f; echo $?' 2>&1)
13001300
 if [ "$result" = "0" ]; then
13011301
     pass "return with no value uses last exit status"
13021302
 else
suites/posix/posix_compliance_coverage.shmodified
@@ -2,7 +2,7 @@
22
 # POSIX Compliance Coverage Tests - Filling Identified Gaps
33
 # These tests cover edge cases and behaviors not covered by other test suites
44
 
5
-FORTSH_BIN="${FORTSH_BIN:-./bin/fortsh}"
5
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
66
 BASH_REF="${BASH_REF:-bash}"
77
 
88
 # Colors
@@ -70,7 +70,7 @@ compare_posix_output() {
7070
     posix_output=$(FORTSH_RC_FILE=/dev/null "$BASH_REF" -c "$test_cmd" 2>&1 | normalize_output)
7171
     posix_exit=$?
7272
 
73
-    fortsh_output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1 | normalize_output)
73
+    fortsh_output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1 | normalize_output)
7474
     fortsh_exit=$?
7575
 
7676
     if [ "$posix_output" = "$fortsh_output" ] && [ "$posix_exit" = "$fortsh_exit" ]; then
@@ -94,7 +94,7 @@ compare_posix_error() {
9494
     posix_output=$(FORTSH_RC_FILE=/dev/null "$BASH_REF" -c "$test_cmd" 2>&1)
9595
     posix_exit=$?
9696
 
97
-    fortsh_output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1)
97
+    fortsh_output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1)
9898
     fortsh_exit=$?
9999
 
100100
     posix_norm=$(normalize_error "$posix_output")
@@ -112,7 +112,7 @@ test_accepts() {
112112
     test_name="$1"
113113
     test_cmd="$2"
114114
 
115
-    if FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" >/dev/null 2>&1; then
115
+    if FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" >/dev/null 2>&1; then
116116
         pass "$test_name"
117117
     else
118118
         fail "$test_name" "should succeed" "failed or not implemented"
@@ -124,7 +124,7 @@ test_fails() {
124124
     test_name="$1"
125125
     test_cmd="$2"
126126
 
127
-    if ! FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" >/dev/null 2>&1; then
127
+    if ! FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" >/dev/null 2>&1; then
128128
         pass "$test_name"
129129
     else
130130
         fail "$test_name" "should fail" "succeeded unexpectedly"
@@ -229,7 +229,7 @@ test_trap_behavior() {
229229
     test_cmd="$2"
230230
     expected_pattern="$3"
231231
 
232
-    output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1)
232
+    output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1)
233233
 
234234
     if echo "$output" | grep -qE "$expected_pattern"; then
235235
         pass "$test_name"
@@ -336,7 +336,7 @@ compare_posix_output "5-stage pipeline" 'echo test | cat | cat | cat | cat | cat
336336
 # Pipeline timing can produce non-deterministic pipe errors — filter them out
337337
 TEST_NUM=$((TEST_NUM + 1))
338338
 _pf_expected=$(FORTSH_RC_FILE=/dev/null "$BASH_REF" -c 'echo ok | false | cat; echo $?' 2>&1 | grep -v 'Broken pipe' | normalize_output)
339
-_pf_actual=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c 'echo ok | false | cat; echo $?' 2>&1 | grep -v 'Broken pipe' | normalize_output)
339
+_pf_actual=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c 'echo ok | false | cat; echo $?' 2>&1 | grep -v 'Broken pipe' | normalize_output)
340340
 if [ "$_pf_expected" = "$_pf_actual" ]; then pass "pipeline with failures"
341341
 else fail "pipeline with failures" "$_pf_expected" "$_pf_actual"; fi
342342
 
@@ -359,7 +359,7 @@ test_alias_behavior() {
359359
     test_cmd="$2"
360360
     expected_pattern="$3"
361361
 
362
-    output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1)
362
+    output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1)
363363
 
364364
     if echo "$output" | grep -qiE "$expected_pattern"; then
365365
         pass "$test_name"
suites/posix/posix_compliance_extended.shmodified
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -82,7 +82,7 @@ compare_posix_output() {
8282
     "$BASH_REF" -c "$command" > "$posix_file" 2>&1 || true
8383
 
8484
     # Run in fortsh
85
-    "$FORTSH_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
85
+    "$SHELL_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
8686
 
8787
     # Compare outputs
8888
     if diff -q "$posix_file" "$fortsh_file" > /dev/null 2>&1; then
@@ -102,7 +102,7 @@ compare_posix_exit_code() {
102102
     "$BASH_REF" -c "$command" > /dev/null 2>&1
103103
     posix_exit=$?
104104
 
105
-    "$FORTSH_BIN" -c "$command" > /dev/null 2>&1
105
+    "$SHELL_BIN" -c "$command" > /dev/null 2>&1
106106
     fortsh_exit=$?
107107
 
108108
     if [ "$posix_exit" -eq "$fortsh_exit" ]; then
suites/posix/posix_compliance_filetest.shmodified
@@ -24,12 +24,12 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 
2929
 # Check if fortsh exists
30
-if [ ! -x "$FORTSH_BIN" ]; then
31
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
+if [ ! -x "$SHELL_BIN" ]; then
31
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
32
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3333
     exit 1
3434
 fi
3535
 
@@ -102,49 +102,49 @@ setup_test_files
102102
 section "369. FILE EXISTENCE AND TYPE TESTS"
103103
 # =====================================
104104
 
105
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -e regular_file ] && echo yes || echo no' 2>&1)
105
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -e regular_file ] && echo yes || echo no' 2>&1)
106106
 if [ "$result" = "yes" ]; then
107107
     pass "[ -e file ] exists test (regular file)"
108108
 else
109109
     fail "[ -e file ] exists test (regular file)" "yes" "$result"
110110
 fi
111111
 
112
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -e test_dir ] && echo yes || echo no' 2>&1)
112
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -e test_dir ] && echo yes || echo no' 2>&1)
113113
 if [ "$result" = "yes" ]; then
114114
     pass "[ -e dir ] exists test (directory)"
115115
 else
116116
     fail "[ -e dir ] exists test (directory)" "yes" "$result"
117117
 fi
118118
 
119
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -e nonexistent ] && echo yes || echo no' 2>&1)
119
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -e nonexistent ] && echo yes || echo no' 2>&1)
120120
 if [ "$result" = "no" ]; then
121121
     pass "[ -e nonexistent ] returns false"
122122
 else
123123
     fail "[ -e nonexistent ] returns false" "no" "$result"
124124
 fi
125125
 
126
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -f regular_file ] && echo yes || echo no' 2>&1)
126
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -f regular_file ] && echo yes || echo no' 2>&1)
127127
 if [ "$result" = "yes" ]; then
128128
     pass "[ -f file ] regular file test"
129129
 else
130130
     fail "[ -f file ] regular file test" "yes" "$result"
131131
 fi
132132
 
133
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -f test_dir ] && echo yes || echo no' 2>&1)
133
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -f test_dir ] && echo yes || echo no' 2>&1)
134134
 if [ "$result" = "no" ]; then
135135
     pass "[ -f dir ] returns false for directory"
136136
 else
137137
     fail "[ -f dir ] returns false for directory" "no" "$result"
138138
 fi
139139
 
140
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -d test_dir ] && echo yes || echo no' 2>&1)
140
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -d test_dir ] && echo yes || echo no' 2>&1)
141141
 if [ "$result" = "yes" ]; then
142142
     pass "[ -d dir ] directory test"
143143
 else
144144
     fail "[ -d dir ] directory test" "yes" "$result"
145145
 fi
146146
 
147
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -d regular_file ] && echo yes || echo no' 2>&1)
147
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -d regular_file ] && echo yes || echo no' 2>&1)
148148
 if [ "$result" = "no" ]; then
149149
     pass "[ -d file ] returns false for file"
150150
 else
@@ -155,28 +155,28 @@ fi
155155
 section "370. SYMBOLIC LINK TESTS"
156156
 # =====================================
157157
 
158
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -L symlink_file ] && echo yes || echo no' 2>&1)
158
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -L symlink_file ] && echo yes || echo no' 2>&1)
159159
 if [ "$result" = "yes" ]; then
160160
     pass "[ -L symlink ] symbolic link test"
161161
 else
162162
     fail "[ -L symlink ] symbolic link test" "yes" "$result"
163163
 fi
164164
 
165
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -h symlink_file ] && echo yes || echo no' 2>&1)
165
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -h symlink_file ] && echo yes || echo no' 2>&1)
166166
 if [ "$result" = "yes" ]; then
167167
     pass "[ -h symlink ] symbolic link test (alias)"
168168
 else
169169
     fail "[ -h symlink ] symbolic link test (alias)" "yes" "$result"
170170
 fi
171171
 
172
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -L regular_file ] && echo yes || echo no' 2>&1)
172
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -L regular_file ] && echo yes || echo no' 2>&1)
173173
 if [ "$result" = "no" ]; then
174174
     pass "[ -L regular ] returns false for non-symlink"
175175
 else
176176
     fail "[ -L regular ] returns false for non-symlink" "no" "$result"
177177
 fi
178178
 
179
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -L broken_link ] && echo yes || echo no' 2>&1)
179
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -L broken_link ] && echo yes || echo no' 2>&1)
180180
 if [ "$result" = "yes" ]; then
181181
     pass "[ -L broken_link ] true for broken symlink"
182182
 else
@@ -187,28 +187,28 @@ fi
187187
 section "371. FILE PERMISSION TESTS"
188188
 # =====================================
189189
 
190
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -r regular_file ] && echo yes || echo no' 2>&1)
190
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -r regular_file ] && echo yes || echo no' 2>&1)
191191
 if [ "$result" = "yes" ]; then
192192
     pass "[ -r file ] readable test"
193193
 else
194194
     fail "[ -r file ] readable test" "yes" "$result"
195195
 fi
196196
 
197
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -w regular_file ] && echo yes || echo no' 2>&1)
197
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -w regular_file ] && echo yes || echo no' 2>&1)
198198
 if [ "$result" = "yes" ]; then
199199
     pass "[ -w file ] writable test"
200200
 else
201201
     fail "[ -w file ] writable test" "yes" "$result"
202202
 fi
203203
 
204
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -x executable_file ] && echo yes || echo no' 2>&1)
204
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -x executable_file ] && echo yes || echo no' 2>&1)
205205
 if [ "$result" = "yes" ]; then
206206
     pass "[ -x file ] executable test"
207207
 else
208208
     fail "[ -x file ] executable test" "yes" "$result"
209209
 fi
210210
 
211
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -x regular_file ] && echo yes || echo no' 2>&1)
211
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -x regular_file ] && echo yes || echo no' 2>&1)
212212
 if [ "$result" = "no" ]; then
213213
     pass "[ -x non-exec ] returns false"
214214
 else
@@ -219,14 +219,14 @@ fi
219219
 section "372. FILE SIZE TESTS"
220220
 # =====================================
221221
 
222
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -s regular_file ] && echo yes || echo no' 2>&1)
222
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -s regular_file ] && echo yes || echo no' 2>&1)
223223
 if [ "$result" = "yes" ]; then
224224
     pass "[ -s file ] size greater than zero"
225225
 else
226226
     fail "[ -s file ] size greater than zero" "yes" "$result"
227227
 fi
228228
 
229
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -s empty_file ] && echo yes || echo no' 2>&1)
229
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -s empty_file ] && echo yes || echo no' 2>&1)
230230
 if [ "$result" = "no" ]; then
231231
     pass "[ -s empty ] returns false for empty file"
232232
 else
@@ -237,42 +237,42 @@ fi
237237
 section "373. STRING TESTS"
238238
 # =====================================
239239
 
240
-result=$("$FORTSH_BIN" -c '[ -z "" ] && echo yes || echo no' 2>&1)
240
+result=$("$SHELL_BIN" -c '[ -z "" ] && echo yes || echo no' 2>&1)
241241
 if [ "$result" = "yes" ]; then
242242
     pass "[ -z \"\" ] zero length string"
243243
 else
244244
     fail "[ -z \"\" ] zero length string" "yes" "$result"
245245
 fi
246246
 
247
-result=$("$FORTSH_BIN" -c '[ -z "hello" ] && echo yes || echo no' 2>&1)
247
+result=$("$SHELL_BIN" -c '[ -z "hello" ] && echo yes || echo no' 2>&1)
248248
 if [ "$result" = "no" ]; then
249249
     pass "[ -z str ] returns false for non-empty"
250250
 else
251251
     fail "[ -z str ] returns false for non-empty" "no" "$result"
252252
 fi
253253
 
254
-result=$("$FORTSH_BIN" -c '[ -n "hello" ] && echo yes || echo no' 2>&1)
254
+result=$("$SHELL_BIN" -c '[ -n "hello" ] && echo yes || echo no' 2>&1)
255255
 if [ "$result" = "yes" ]; then
256256
     pass "[ -n str ] non-zero length string"
257257
 else
258258
     fail "[ -n str ] non-zero length string" "yes" "$result"
259259
 fi
260260
 
261
-result=$("$FORTSH_BIN" -c '[ -n "" ] && echo yes || echo no' 2>&1)
261
+result=$("$SHELL_BIN" -c '[ -n "" ] && echo yes || echo no' 2>&1)
262262
 if [ "$result" = "no" ]; then
263263
     pass "[ -n \"\" ] returns false for empty"
264264
 else
265265
     fail "[ -n \"\" ] returns false for empty" "no" "$result"
266266
 fi
267267
 
268
-result=$("$FORTSH_BIN" -c '[ "hello" ] && echo yes || echo no' 2>&1)
268
+result=$("$SHELL_BIN" -c '[ "hello" ] && echo yes || echo no' 2>&1)
269269
 if [ "$result" = "yes" ]; then
270270
     pass "[ string ] implicit non-empty test"
271271
 else
272272
     fail "[ string ] implicit non-empty test" "yes" "$result"
273273
 fi
274274
 
275
-result=$("$FORTSH_BIN" -c '[ "" ] && echo yes || echo no' 2>&1)
275
+result=$("$SHELL_BIN" -c '[ "" ] && echo yes || echo no' 2>&1)
276276
 if [ "$result" = "no" ]; then
277277
     pass "[ \"\" ] empty string is false"
278278
 else
@@ -283,28 +283,28 @@ fi
283283
 section "374. STRING COMPARISON TESTS"
284284
 # =====================================
285285
 
286
-result=$("$FORTSH_BIN" -c '[ "abc" = "abc" ] && echo yes || echo no' 2>&1)
286
+result=$("$SHELL_BIN" -c '[ "abc" = "abc" ] && echo yes || echo no' 2>&1)
287287
 if [ "$result" = "yes" ]; then
288288
     pass "[ str = str ] string equality"
289289
 else
290290
     fail "[ str = str ] string equality" "yes" "$result"
291291
 fi
292292
 
293
-result=$("$FORTSH_BIN" -c '[ "abc" = "xyz" ] && echo yes || echo no' 2>&1)
293
+result=$("$SHELL_BIN" -c '[ "abc" = "xyz" ] && echo yes || echo no' 2>&1)
294294
 if [ "$result" = "no" ]; then
295295
     pass "[ str1 = str2 ] returns false for different"
296296
 else
297297
     fail "[ str1 = str2 ] returns false for different" "no" "$result"
298298
 fi
299299
 
300
-result=$("$FORTSH_BIN" -c '[ "abc" != "xyz" ] && echo yes || echo no' 2>&1)
300
+result=$("$SHELL_BIN" -c '[ "abc" != "xyz" ] && echo yes || echo no' 2>&1)
301301
 if [ "$result" = "yes" ]; then
302302
     pass "[ str1 != str2 ] string inequality"
303303
 else
304304
     fail "[ str1 != str2 ] string inequality" "yes" "$result"
305305
 fi
306306
 
307
-result=$("$FORTSH_BIN" -c '[ "abc" != "abc" ] && echo yes || echo no' 2>&1)
307
+result=$("$SHELL_BIN" -c '[ "abc" != "abc" ] && echo yes || echo no' 2>&1)
308308
 if [ "$result" = "no" ]; then
309309
     pass "[ str != str ] returns false for same"
310310
 else
@@ -315,77 +315,77 @@ fi
315315
 section "375. NUMERIC COMPARISON TESTS"
316316
 # =====================================
317317
 
318
-result=$("$FORTSH_BIN" -c '[ 5 -eq 5 ] && echo yes || echo no' 2>&1)
318
+result=$("$SHELL_BIN" -c '[ 5 -eq 5 ] && echo yes || echo no' 2>&1)
319319
 if [ "$result" = "yes" ]; then
320320
     pass "[ n -eq n ] numeric equality"
321321
 else
322322
     fail "[ n -eq n ] numeric equality" "yes" "$result"
323323
 fi
324324
 
325
-result=$("$FORTSH_BIN" -c '[ 5 -eq 3 ] && echo yes || echo no' 2>&1)
325
+result=$("$SHELL_BIN" -c '[ 5 -eq 3 ] && echo yes || echo no' 2>&1)
326326
 if [ "$result" = "no" ]; then
327327
     pass "[ n1 -eq n2 ] returns false for different"
328328
 else
329329
     fail "[ n1 -eq n2 ] returns false for different" "no" "$result"
330330
 fi
331331
 
332
-result=$("$FORTSH_BIN" -c '[ 5 -ne 3 ] && echo yes || echo no' 2>&1)
332
+result=$("$SHELL_BIN" -c '[ 5 -ne 3 ] && echo yes || echo no' 2>&1)
333333
 if [ "$result" = "yes" ]; then
334334
     pass "[ n1 -ne n2 ] numeric inequality"
335335
 else
336336
     fail "[ n1 -ne n2 ] numeric inequality" "yes" "$result"
337337
 fi
338338
 
339
-result=$("$FORTSH_BIN" -c '[ 5 -gt 3 ] && echo yes || echo no' 2>&1)
339
+result=$("$SHELL_BIN" -c '[ 5 -gt 3 ] && echo yes || echo no' 2>&1)
340340
 if [ "$result" = "yes" ]; then
341341
     pass "[ n1 -gt n2 ] greater than"
342342
 else
343343
     fail "[ n1 -gt n2 ] greater than" "yes" "$result"
344344
 fi
345345
 
346
-result=$("$FORTSH_BIN" -c '[ 3 -gt 5 ] && echo yes || echo no' 2>&1)
346
+result=$("$SHELL_BIN" -c '[ 3 -gt 5 ] && echo yes || echo no' 2>&1)
347347
 if [ "$result" = "no" ]; then
348348
     pass "[ n1 -gt n2 ] returns false when not greater"
349349
 else
350350
     fail "[ n1 -gt n2 ] returns false when not greater" "no" "$result"
351351
 fi
352352
 
353
-result=$("$FORTSH_BIN" -c '[ 5 -ge 5 ] && echo yes || echo no' 2>&1)
353
+result=$("$SHELL_BIN" -c '[ 5 -ge 5 ] && echo yes || echo no' 2>&1)
354354
 if [ "$result" = "yes" ]; then
355355
     pass "[ n -ge n ] greater or equal (equal)"
356356
 else
357357
     fail "[ n -ge n ] greater or equal (equal)" "yes" "$result"
358358
 fi
359359
 
360
-result=$("$FORTSH_BIN" -c '[ 5 -ge 3 ] && echo yes || echo no' 2>&1)
360
+result=$("$SHELL_BIN" -c '[ 5 -ge 3 ] && echo yes || echo no' 2>&1)
361361
 if [ "$result" = "yes" ]; then
362362
     pass "[ n1 -ge n2 ] greater or equal (greater)"
363363
 else
364364
     fail "[ n1 -ge n2 ] greater or equal (greater)" "yes" "$result"
365365
 fi
366366
 
367
-result=$("$FORTSH_BIN" -c '[ 3 -lt 5 ] && echo yes || echo no' 2>&1)
367
+result=$("$SHELL_BIN" -c '[ 3 -lt 5 ] && echo yes || echo no' 2>&1)
368368
 if [ "$result" = "yes" ]; then
369369
     pass "[ n1 -lt n2 ] less than"
370370
 else
371371
     fail "[ n1 -lt n2 ] less than" "yes" "$result"
372372
 fi
373373
 
374
-result=$("$FORTSH_BIN" -c '[ 5 -lt 3 ] && echo yes || echo no' 2>&1)
374
+result=$("$SHELL_BIN" -c '[ 5 -lt 3 ] && echo yes || echo no' 2>&1)
375375
 if [ "$result" = "no" ]; then
376376
     pass "[ n1 -lt n2 ] returns false when not less"
377377
 else
378378
     fail "[ n1 -lt n2 ] returns false when not less" "no" "$result"
379379
 fi
380380
 
381
-result=$("$FORTSH_BIN" -c '[ 5 -le 5 ] && echo yes || echo no' 2>&1)
381
+result=$("$SHELL_BIN" -c '[ 5 -le 5 ] && echo yes || echo no' 2>&1)
382382
 if [ "$result" = "yes" ]; then
383383
     pass "[ n -le n ] less or equal (equal)"
384384
 else
385385
     fail "[ n -le n ] less or equal (equal)" "yes" "$result"
386386
 fi
387387
 
388
-result=$("$FORTSH_BIN" -c '[ 3 -le 5 ] && echo yes || echo no' 2>&1)
388
+result=$("$SHELL_BIN" -c '[ 3 -le 5 ] && echo yes || echo no' 2>&1)
389389
 if [ "$result" = "yes" ]; then
390390
     pass "[ n1 -le n2 ] less or equal (less)"
391391
 else
@@ -396,42 +396,42 @@ fi
396396
 section "376. LOGICAL OPERATORS"
397397
 # =====================================
398398
 
399
-result=$("$FORTSH_BIN" -c '[ ! -e /nonexistent ] && echo yes || echo no' 2>&1)
399
+result=$("$SHELL_BIN" -c '[ ! -e /nonexistent ] && echo yes || echo no' 2>&1)
400400
 if [ "$result" = "yes" ]; then
401401
     pass "[ ! expr ] negation"
402402
 else
403403
     fail "[ ! expr ] negation" "yes" "$result"
404404
 fi
405405
 
406
-result=$("$FORTSH_BIN" -c '[ ! -d /tmp ] && echo yes || echo no' 2>&1)
406
+result=$("$SHELL_BIN" -c '[ ! -d /tmp ] && echo yes || echo no' 2>&1)
407407
 if [ "$result" = "no" ]; then
408408
     pass "[ ! expr ] negation of true"
409409
 else
410410
     fail "[ ! expr ] negation of true" "no" "$result"
411411
 fi
412412
 
413
-result=$("$FORTSH_BIN" -c '[ -d /tmp -a -e /tmp ] && echo yes || echo no' 2>&1)
413
+result=$("$SHELL_BIN" -c '[ -d /tmp -a -e /tmp ] && echo yes || echo no' 2>&1)
414414
 if [ "$result" = "yes" ]; then
415415
     pass "[ expr -a expr ] logical AND (both true)"
416416
 else
417417
     fail "[ expr -a expr ] logical AND (both true)" "yes" "$result"
418418
 fi
419419
 
420
-result=$("$FORTSH_BIN" -c '[ -d /tmp -a -e /nonexistent ] && echo yes || echo no' 2>&1)
420
+result=$("$SHELL_BIN" -c '[ -d /tmp -a -e /nonexistent ] && echo yes || echo no' 2>&1)
421421
 if [ "$result" = "no" ]; then
422422
     pass "[ expr -a expr ] logical AND (one false)"
423423
 else
424424
     fail "[ expr -a expr ] logical AND (one false)" "no" "$result"
425425
 fi
426426
 
427
-result=$("$FORTSH_BIN" -c '[ -e /nonexistent -o -d /tmp ] && echo yes || echo no' 2>&1)
427
+result=$("$SHELL_BIN" -c '[ -e /nonexistent -o -d /tmp ] && echo yes || echo no' 2>&1)
428428
 if [ "$result" = "yes" ]; then
429429
     pass "[ expr -o expr ] logical OR (one true)"
430430
 else
431431
     fail "[ expr -o expr ] logical OR (one true)" "yes" "$result"
432432
 fi
433433
 
434
-result=$("$FORTSH_BIN" -c '[ -e /nonexistent -o -e /alsononexistent ] && echo yes || echo no' 2>&1)
434
+result=$("$SHELL_BIN" -c '[ -e /nonexistent -o -e /alsononexistent ] && echo yes || echo no' 2>&1)
435435
 if [ "$result" = "no" ]; then
436436
     pass "[ expr -o expr ] logical OR (both false)"
437437
 else
@@ -447,21 +447,21 @@ touch "$TEST_DIR/older_file"
447447
 sleep 1
448448
 touch "$TEST_DIR/newer_file"
449449
 
450
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ newer_file -nt older_file ] && echo yes || echo no' 2>&1)
450
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ newer_file -nt older_file ] && echo yes || echo no' 2>&1)
451451
 if [ "$result" = "yes" ]; then
452452
     pass "[ f1 -nt f2 ] newer than test"
453453
 else
454454
     fail "[ f1 -nt f2 ] newer than test" "yes" "$result"
455455
 fi
456456
 
457
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ older_file -ot newer_file ] && echo yes || echo no' 2>&1)
457
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ older_file -ot newer_file ] && echo yes || echo no' 2>&1)
458458
 if [ "$result" = "yes" ]; then
459459
     pass "[ f1 -ot f2 ] older than test"
460460
 else
461461
     fail "[ f1 -ot f2 ] older than test" "yes" "$result"
462462
 fi
463463
 
464
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ regular_file -ef regular_file ] && echo yes || echo no' 2>&1)
464
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ regular_file -ef regular_file ] && echo yes || echo no' 2>&1)
465465
 if [ "$result" = "yes" ]; then
466466
     pass "[ f -ef f ] same file test"
467467
 else
@@ -472,21 +472,21 @@ fi
472472
 section "378. TEST COMMAND FORM"
473473
 # =====================================
474474
 
475
-result=$("$FORTSH_BIN" -c 'test -d /tmp && echo yes || echo no' 2>&1)
475
+result=$("$SHELL_BIN" -c 'test -d /tmp && echo yes || echo no' 2>&1)
476476
 if [ "$result" = "yes" ]; then
477477
     pass "test -d dir (test command form)"
478478
 else
479479
     fail "test -d dir (test command form)" "yes" "$result"
480480
 fi
481481
 
482
-result=$("$FORTSH_BIN" -c 'test "hello" = "hello" && echo yes || echo no' 2>&1)
482
+result=$("$SHELL_BIN" -c 'test "hello" = "hello" && echo yes || echo no' 2>&1)
483483
 if [ "$result" = "yes" ]; then
484484
     pass "test str = str (test command form)"
485485
 else
486486
     fail "test str = str (test command form)" "yes" "$result"
487487
 fi
488488
 
489
-result=$("$FORTSH_BIN" -c 'test 5 -gt 3 && echo yes || echo no' 2>&1)
489
+result=$("$SHELL_BIN" -c 'test 5 -gt 3 && echo yes || echo no' 2>&1)
490490
 if [ "$result" = "yes" ]; then
491491
     pass "test n1 -gt n2 (test command form)"
492492
 else
@@ -499,7 +499,7 @@ section "379. SPECIAL FILE TYPES"
499499
 
500500
 # Named pipe test (if created successfully)
501501
 if [ -p "$TEST_DIR/named_pipe" ]; then
502
-    result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -p named_pipe ] && echo yes || echo no' 2>&1)
502
+    result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -p named_pipe ] && echo yes || echo no' 2>&1)
503503
     if [ "$result" = "yes" ]; then
504504
         pass "[ -p fifo ] named pipe test"
505505
     else
@@ -509,7 +509,7 @@ else
509509
     skip "[ -p fifo ] named pipe test" "mkfifo not available"
510510
 fi
511511
 
512
-result=$("$FORTSH_BIN" -c 'cd '"$TEST_DIR"' && [ -p regular_file ] && echo yes || echo no' 2>&1)
512
+result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -p regular_file ] && echo yes || echo no' 2>&1)
513513
 if [ "$result" = "no" ]; then
514514
     pass "[ -p regular ] returns false for non-pipe"
515515
 else
@@ -517,7 +517,7 @@ else
517517
 fi
518518
 
519519
 # Terminal test
520
-result=$("$FORTSH_BIN" -c '[ -t 0 ] && echo yes || echo no' 2>&1)
520
+result=$("$SHELL_BIN" -c '[ -t 0 ] && echo yes || echo no' 2>&1)
521521
 # Since we're running non-interactively, stdin is not a terminal
522522
 if [ "$result" = "no" ]; then
523523
     pass "[ -t 0 ] non-terminal stdin"
@@ -529,35 +529,35 @@ fi
529529
 section "380. EDGE CASES"
530530
 # =====================================
531531
 
532
-result=$("$FORTSH_BIN" -c '[ ] && echo yes || echo no' 2>&1)
532
+result=$("$SHELL_BIN" -c '[ ] && echo yes || echo no' 2>&1)
533533
 if [ "$result" = "no" ]; then
534534
     pass "[ ] empty test returns false"
535535
 else
536536
     fail "[ ] empty test returns false" "no" "$result"
537537
 fi
538538
 
539
-result=$("$FORTSH_BIN" -c 'x=""; [ -n "$x" ] && echo yes || echo no' 2>&1)
539
+result=$("$SHELL_BIN" -c 'x=""; [ -n "$x" ] && echo yes || echo no' 2>&1)
540540
 if [ "$result" = "no" ]; then
541541
     pass "[ -n \"\$empty\" ] with empty variable"
542542
 else
543543
     fail "[ -n \"\$empty\" ] with empty variable" "no" "$result"
544544
 fi
545545
 
546
-result=$("$FORTSH_BIN" -c 'x="hello"; [ -n "$x" ] && echo yes || echo no' 2>&1)
546
+result=$("$SHELL_BIN" -c 'x="hello"; [ -n "$x" ] && echo yes || echo no' 2>&1)
547547
 if [ "$result" = "yes" ]; then
548548
     pass "[ -n \"\$var\" ] with non-empty variable"
549549
 else
550550
     fail "[ -n \"\$var\" ] with non-empty variable" "yes" "$result"
551551
 fi
552552
 
553
-result=$("$FORTSH_BIN" -c '[ "=" = "=" ] && echo yes || echo no' 2>&1)
553
+result=$("$SHELL_BIN" -c '[ "=" = "=" ] && echo yes || echo no' 2>&1)
554554
 if [ "$result" = "yes" ]; then
555555
     pass "[ \"=\" = \"=\" ] equals sign as string"
556556
 else
557557
     fail "[ \"=\" = \"=\" ] equals sign as string" "yes" "$result"
558558
 fi
559559
 
560
-result=$("$FORTSH_BIN" -c '[ "-n" = "-n" ] && echo yes || echo no' 2>&1)
560
+result=$("$SHELL_BIN" -c '[ "-n" = "-n" ] && echo yes || echo no' 2>&1)
561561
 if [ "$result" = "yes" ]; then
562562
     pass "[ \"-n\" = \"-n\" ] operator as string"
563563
 else
@@ -568,42 +568,42 @@ fi
568568
 section "381. COMPLEX TEST EXPRESSIONS"
569569
 # =====================================
570570
 
571
-result=$("$FORTSH_BIN" -c '[ 1 -eq 1 -a 2 -eq 2 ] && echo yes || echo no' 2>&1)
571
+result=$("$SHELL_BIN" -c '[ 1 -eq 1 -a 2 -eq 2 ] && echo yes || echo no' 2>&1)
572572
 if [ "$result" = "yes" ]; then
573573
     pass "[ a -a b ] both true"
574574
 else
575575
     fail "[ a -a b ] both true" "yes" "$result"
576576
 fi
577577
 
578
-result=$("$FORTSH_BIN" -c '[ 1 -eq 1 -a 2 -eq 3 ] && echo yes || echo no' 2>&1)
578
+result=$("$SHELL_BIN" -c '[ 1 -eq 1 -a 2 -eq 3 ] && echo yes || echo no' 2>&1)
579579
 if [ "$result" = "no" ]; then
580580
     pass "[ a -a b ] second false"
581581
 else
582582
     fail "[ a -a b ] second false" "no" "$result"
583583
 fi
584584
 
585
-result=$("$FORTSH_BIN" -c '[ 1 -eq 2 -o 2 -eq 2 ] && echo yes || echo no' 2>&1)
585
+result=$("$SHELL_BIN" -c '[ 1 -eq 2 -o 2 -eq 2 ] && echo yes || echo no' 2>&1)
586586
 if [ "$result" = "yes" ]; then
587587
     pass "[ a -o b ] second true"
588588
 else
589589
     fail "[ a -o b ] second true" "yes" "$result"
590590
 fi
591591
 
592
-result=$("$FORTSH_BIN" -c '[ 1 -eq 2 -o 3 -eq 4 ] && echo yes || echo no' 2>&1)
592
+result=$("$SHELL_BIN" -c '[ 1 -eq 2 -o 3 -eq 4 ] && echo yes || echo no' 2>&1)
593593
 if [ "$result" = "no" ]; then
594594
     pass "[ a -o b ] both false"
595595
 else
596596
     fail "[ a -o b ] both false" "no" "$result"
597597
 fi
598598
 
599
-result=$("$FORTSH_BIN" -c '[ ! 1 -eq 2 ] && echo yes || echo no' 2>&1)
599
+result=$("$SHELL_BIN" -c '[ ! 1 -eq 2 ] && echo yes || echo no' 2>&1)
600600
 if [ "$result" = "yes" ]; then
601601
     pass "[ ! expr ] negates false"
602602
 else
603603
     fail "[ ! expr ] negates false" "yes" "$result"
604604
 fi
605605
 
606
-result=$("$FORTSH_BIN" -c '[ ! 1 -eq 1 ] && echo yes || echo no' 2>&1)
606
+result=$("$SHELL_BIN" -c '[ ! 1 -eq 1 ] && echo yes || echo no' 2>&1)
607607
 if [ "$result" = "no" ]; then
608608
     pass "[ ! expr ] negates true"
609609
 else
@@ -614,14 +614,14 @@ fi
614614
 section "382. PARENTHESES IN TEST"
615615
 # =====================================
616616
 
617
-result=$("$FORTSH_BIN" -c '[ \( 1 -eq 1 \) ] && echo yes || echo no' 2>&1)
617
+result=$("$SHELL_BIN" -c '[ \( 1 -eq 1 \) ] && echo yes || echo no' 2>&1)
618618
 if [ "$result" = "yes" ]; then
619619
     pass "[ \\( expr \\) ] parentheses"
620620
 else
621621
     fail "[ \\( expr \\) ] parentheses" "yes" "$result"
622622
 fi
623623
 
624
-result=$("$FORTSH_BIN" -c '[ \( 1 -eq 1 -o 2 -eq 3 \) -a 3 -eq 3 ] && echo yes || echo no' 2>&1)
624
+result=$("$SHELL_BIN" -c '[ \( 1 -eq 1 -o 2 -eq 3 \) -a 3 -eq 3 ] && echo yes || echo no' 2>&1)
625625
 if [ "$result" = "yes" ]; then
626626
     pass "[ \\( a -o b \\) -a c ] complex grouping"
627627
 else
@@ -632,28 +632,28 @@ fi
632632
 section "383. STRING LENGTH COMPARISONS"
633633
 # =====================================
634634
 
635
-result=$("$FORTSH_BIN" -c '[ -z "" ] && echo yes || echo no' 2>&1)
635
+result=$("$SHELL_BIN" -c '[ -z "" ] && echo yes || echo no' 2>&1)
636636
 if [ "$result" = "yes" ]; then
637637
     pass "[ -z \"\" ] empty string is zero length"
638638
 else
639639
     fail "[ -z \"\" ] empty string is zero length" "yes" "$result"
640640
 fi
641641
 
642
-result=$("$FORTSH_BIN" -c '[ -z "x" ] && echo yes || echo no' 2>&1)
642
+result=$("$SHELL_BIN" -c '[ -z "x" ] && echo yes || echo no' 2>&1)
643643
 if [ "$result" = "no" ]; then
644644
     pass "[ -z \"x\" ] non-empty has length"
645645
 else
646646
     fail "[ -z \"x\" ] non-empty has length" "no" "$result"
647647
 fi
648648
 
649
-result=$("$FORTSH_BIN" -c '[ -n "" ] && echo yes || echo no' 2>&1)
649
+result=$("$SHELL_BIN" -c '[ -n "" ] && echo yes || echo no' 2>&1)
650650
 if [ "$result" = "no" ]; then
651651
     pass "[ -n \"\" ] empty has no length"
652652
 else
653653
     fail "[ -n \"\" ] empty has no length" "no" "$result"
654654
 fi
655655
 
656
-result=$("$FORTSH_BIN" -c '[ -n "abc" ] && echo yes || echo no' 2>&1)
656
+result=$("$SHELL_BIN" -c '[ -n "abc" ] && echo yes || echo no' 2>&1)
657657
 if [ "$result" = "yes" ]; then
658658
     pass "[ -n \"abc\" ] string has length"
659659
 else
@@ -664,28 +664,28 @@ fi
664664
 section "384. NUMERIC EDGE CASES"
665665
 # =====================================
666666
 
667
-result=$("$FORTSH_BIN" -c '[ 0 -eq 0 ] && echo yes || echo no' 2>&1)
667
+result=$("$SHELL_BIN" -c '[ 0 -eq 0 ] && echo yes || echo no' 2>&1)
668668
 if [ "$result" = "yes" ]; then
669669
     pass "[ 0 -eq 0 ] zero equals zero"
670670
 else
671671
     fail "[ 0 -eq 0 ] zero equals zero" "yes" "$result"
672672
 fi
673673
 
674
-result=$("$FORTSH_BIN" -c '[ -5 -lt 0 ] && echo yes || echo no' 2>&1)
674
+result=$("$SHELL_BIN" -c '[ -5 -lt 0 ] && echo yes || echo no' 2>&1)
675675
 if [ "$result" = "yes" ]; then
676676
     pass "[ -5 -lt 0 ] negative less than zero"
677677
 else
678678
     fail "[ -5 -lt 0 ] negative less than zero" "yes" "$result"
679679
 fi
680680
 
681
-result=$("$FORTSH_BIN" -c '[ -10 -gt -20 ] && echo yes || echo no' 2>&1)
681
+result=$("$SHELL_BIN" -c '[ -10 -gt -20 ] && echo yes || echo no' 2>&1)
682682
 if [ "$result" = "yes" ]; then
683683
     pass "[ -10 -gt -20 ] negative comparisons"
684684
 else
685685
     fail "[ -10 -gt -20 ] negative comparisons" "yes" "$result"
686686
 fi
687687
 
688
-result=$("$FORTSH_BIN" -c '[ 999999 -gt 1 ] && echo yes || echo no' 2>&1)
688
+result=$("$SHELL_BIN" -c '[ 999999 -gt 1 ] && echo yes || echo no' 2>&1)
689689
 if [ "$result" = "yes" ]; then
690690
     pass "[ large -gt 1 ] large numbers"
691691
 else
@@ -696,21 +696,21 @@ fi
696696
 section "385. STRING VS NUMERIC"
697697
 # =====================================
698698
 
699
-result=$("$FORTSH_BIN" -c '[ "10" = "10" ] && echo yes || echo no' 2>&1)
699
+result=$("$SHELL_BIN" -c '[ "10" = "10" ] && echo yes || echo no' 2>&1)
700700
 if [ "$result" = "yes" ]; then
701701
     pass "[ \"10\" = \"10\" ] string comparison"
702702
 else
703703
     fail "[ \"10\" = \"10\" ] string comparison" "yes" "$result"
704704
 fi
705705
 
706
-result=$("$FORTSH_BIN" -c '[ "10" = "010" ] && echo yes || echo no' 2>&1)
706
+result=$("$SHELL_BIN" -c '[ "10" = "010" ] && echo yes || echo no' 2>&1)
707707
 if [ "$result" = "no" ]; then
708708
     pass "[ \"10\" = \"010\" ] string differs from numeric"
709709
 else
710710
     fail "[ \"10\" = \"010\" ] string differs from numeric" "no" "$result"
711711
 fi
712712
 
713
-result=$("$FORTSH_BIN" -c '[ 10 -eq 010 ] && echo yes || echo no' 2>&1)
713
+result=$("$SHELL_BIN" -c '[ 10 -eq 010 ] && echo yes || echo no' 2>&1)
714714
 # Numeric comparison - may or may not treat 010 as octal
715715
 if [ "$result" = "yes" ] || [ "$result" = "no" ]; then
716716
     pass "[ 10 -eq 010 ] numeric comparison"
@@ -722,14 +722,14 @@ fi
722722
 section "386. FILE TEST WITH VARIABLES"
723723
 # =====================================
724724
 
725
-result=$("$FORTSH_BIN" -c 'f='"$TEST_DIR"'/regular_file; [ -f "$f" ] && echo yes || echo no' 2>&1)
725
+result=$("$SHELL_BIN" -c 'f='"$TEST_DIR"'/regular_file; [ -f "$f" ] && echo yes || echo no' 2>&1)
726726
 if [ "$result" = "yes" ]; then
727727
     pass "[ -f \"\$var\" ] variable as filename"
728728
 else
729729
     fail "[ -f \"\$var\" ] variable as filename" "yes" "$result"
730730
 fi
731731
 
732
-result=$("$FORTSH_BIN" -c 'd='"$TEST_DIR"'; [ -d "$d" ] && echo yes || echo no' 2>&1)
732
+result=$("$SHELL_BIN" -c 'd='"$TEST_DIR"'; [ -d "$d" ] && echo yes || echo no' 2>&1)
733733
 if [ "$result" = "yes" ]; then
734734
     pass "[ -d \"\$var\" ] variable as dirname"
735735
 else
@@ -740,21 +740,21 @@ fi
740740
 section "387. EMPTY OPERAND HANDLING"
741741
 # =====================================
742742
 
743
-result=$("$FORTSH_BIN" -c 'unset x; [ -n "$x" ] && echo yes || echo no' 2>&1)
743
+result=$("$SHELL_BIN" -c 'unset x; [ -n "$x" ] && echo yes || echo no' 2>&1)
744744
 if [ "$result" = "no" ]; then
745745
     pass "[ -n \"\$unset\" ] unset variable"
746746
 else
747747
     fail "[ -n \"\$unset\" ] unset variable" "no" "$result"
748748
 fi
749749
 
750
-result=$("$FORTSH_BIN" -c 'unset x; [ -z "$x" ] && echo yes || echo no' 2>&1)
750
+result=$("$SHELL_BIN" -c 'unset x; [ -z "$x" ] && echo yes || echo no' 2>&1)
751751
 if [ "$result" = "yes" ]; then
752752
     pass "[ -z \"\$unset\" ] unset is zero length"
753753
 else
754754
     fail "[ -z \"\$unset\" ] unset is zero length" "yes" "$result"
755755
 fi
756756
 
757
-result=$("$FORTSH_BIN" -c 'unset x; [ "$x" = "" ] && echo yes || echo no' 2>&1)
757
+result=$("$SHELL_BIN" -c 'unset x; [ "$x" = "" ] && echo yes || echo no' 2>&1)
758758
 if [ "$result" = "yes" ]; then
759759
     pass "[ \"\$unset\" = \"\" ] unset equals empty"
760760
 else
@@ -765,42 +765,42 @@ fi
765765
 section "388. NUMERIC COMPARISON OPERATORS"
766766
 # =====================================
767767
 
768
-result=$("$FORTSH_BIN" -c '[ 5 -eq 5 ] && echo yes || echo no' 2>&1)
768
+result=$("$SHELL_BIN" -c '[ 5 -eq 5 ] && echo yes || echo no' 2>&1)
769769
 if [ "$result" = "yes" ]; then
770770
     pass "[ 5 -eq 5 ] equals"
771771
 else
772772
     fail "[ 5 -eq 5 ] equals" "yes" "$result"
773773
 fi
774774
 
775
-result=$("$FORTSH_BIN" -c '[ 5 -ne 3 ] && echo yes || echo no' 2>&1)
775
+result=$("$SHELL_BIN" -c '[ 5 -ne 3 ] && echo yes || echo no' 2>&1)
776776
 if [ "$result" = "yes" ]; then
777777
     pass "[ 5 -ne 3 ] not equals"
778778
 else
779779
     fail "[ 5 -ne 3 ] not equals" "yes" "$result"
780780
 fi
781781
 
782
-result=$("$FORTSH_BIN" -c '[ 10 -gt 5 ] && echo yes || echo no' 2>&1)
782
+result=$("$SHELL_BIN" -c '[ 10 -gt 5 ] && echo yes || echo no' 2>&1)
783783
 if [ "$result" = "yes" ]; then
784784
     pass "[ 10 -gt 5 ] greater than"
785785
 else
786786
     fail "[ 10 -gt 5 ] greater than" "yes" "$result"
787787
 fi
788788
 
789
-result=$("$FORTSH_BIN" -c '[ 10 -ge 10 ] && echo yes || echo no' 2>&1)
789
+result=$("$SHELL_BIN" -c '[ 10 -ge 10 ] && echo yes || echo no' 2>&1)
790790
 if [ "$result" = "yes" ]; then
791791
     pass "[ 10 -ge 10 ] greater or equal"
792792
 else
793793
     fail "[ 10 -ge 10 ] greater or equal" "yes" "$result"
794794
 fi
795795
 
796
-result=$("$FORTSH_BIN" -c '[ 3 -lt 5 ] && echo yes || echo no' 2>&1)
796
+result=$("$SHELL_BIN" -c '[ 3 -lt 5 ] && echo yes || echo no' 2>&1)
797797
 if [ "$result" = "yes" ]; then
798798
     pass "[ 3 -lt 5 ] less than"
799799
 else
800800
     fail "[ 3 -lt 5 ] less than" "yes" "$result"
801801
 fi
802802
 
803
-result=$("$FORTSH_BIN" -c '[ 3 -le 3 ] && echo yes || echo no' 2>&1)
803
+result=$("$SHELL_BIN" -c '[ 3 -le 3 ] && echo yes || echo no' 2>&1)
804804
 if [ "$result" = "yes" ]; then
805805
     pass "[ 3 -le 3 ] less or equal"
806806
 else
@@ -811,21 +811,21 @@ fi
811811
 section "389. NEGATIVE NUMBER TESTS"
812812
 # =====================================
813813
 
814
-result=$("$FORTSH_BIN" -c '[ -5 -lt 0 ] && echo yes || echo no' 2>&1)
814
+result=$("$SHELL_BIN" -c '[ -5 -lt 0 ] && echo yes || echo no' 2>&1)
815815
 if [ "$result" = "yes" ]; then
816816
     pass "[ -5 -lt 0 ] negative less than zero"
817817
 else
818818
     fail "[ -5 -lt 0 ] negative less than zero" "yes" "$result"
819819
 fi
820820
 
821
-result=$("$FORTSH_BIN" -c '[ -10 -lt -5 ] && echo yes || echo no' 2>&1)
821
+result=$("$SHELL_BIN" -c '[ -10 -lt -5 ] && echo yes || echo no' 2>&1)
822822
 if [ "$result" = "yes" ]; then
823823
     pass "[ -10 -lt -5 ] negative comparison"
824824
 else
825825
     fail "[ -10 -lt -5 ] negative comparison" "yes" "$result"
826826
 fi
827827
 
828
-result=$("$FORTSH_BIN" -c '[ -5 -eq -5 ] && echo yes || echo no' 2>&1)
828
+result=$("$SHELL_BIN" -c '[ -5 -eq -5 ] && echo yes || echo no' 2>&1)
829829
 if [ "$result" = "yes" ]; then
830830
     pass "[ -5 -eq -5 ] negative equality"
831831
 else
@@ -836,28 +836,28 @@ fi
836836
 section "390. STRING TESTS"
837837
 # =====================================
838838
 
839
-result=$("$FORTSH_BIN" -c '[ "hello" = "hello" ] && echo yes || echo no' 2>&1)
839
+result=$("$SHELL_BIN" -c '[ "hello" = "hello" ] && echo yes || echo no' 2>&1)
840840
 if [ "$result" = "yes" ]; then
841841
     pass "[ \"hello\" = \"hello\" ] string equality"
842842
 else
843843
     fail "[ \"hello\" = \"hello\" ] string equality" "yes" "$result"
844844
 fi
845845
 
846
-result=$("$FORTSH_BIN" -c '[ "hello" != "world" ] && echo yes || echo no' 2>&1)
846
+result=$("$SHELL_BIN" -c '[ "hello" != "world" ] && echo yes || echo no' 2>&1)
847847
 if [ "$result" = "yes" ]; then
848848
     pass "[ \"hello\" != \"world\" ] string inequality"
849849
 else
850850
     fail "[ \"hello\" != \"world\" ] string inequality" "yes" "$result"
851851
 fi
852852
 
853
-result=$("$FORTSH_BIN" -c '[ "abc" \< "def" ] && echo yes || echo no' 2>&1)
853
+result=$("$SHELL_BIN" -c '[ "abc" \< "def" ] && echo yes || echo no' 2>&1)
854854
 if [ "$result" = "yes" ]; then
855855
     pass "[ \"abc\" < \"def\" ] string less than"
856856
 else
857857
     fail "[ \"abc\" < \"def\" ] string less than" "yes" "$result"
858858
 fi
859859
 
860
-result=$("$FORTSH_BIN" -c '[ "xyz" \> "abc" ] && echo yes || echo no' 2>&1)
860
+result=$("$SHELL_BIN" -c '[ "xyz" \> "abc" ] && echo yes || echo no' 2>&1)
861861
 if [ "$result" = "yes" ]; then
862862
     pass "[ \"xyz\" > \"abc\" ] string greater than"
863863
 else
@@ -870,14 +870,14 @@ section "391. FILE PERMISSION TESTS"
870870
 
871871
 touch "$TEST_DIR/readable.txt"
872872
 chmod 644 "$TEST_DIR/readable.txt"
873
-result=$("$FORTSH_BIN" -c '[ -r "'"$TEST_DIR"'/readable.txt" ] && echo yes || echo no' 2>&1)
873
+result=$("$SHELL_BIN" -c '[ -r "'"$TEST_DIR"'/readable.txt" ] && echo yes || echo no' 2>&1)
874874
 if [ "$result" = "yes" ]; then
875875
     pass "[ -r file ] readable file"
876876
 else
877877
     fail "[ -r file ] readable file" "yes" "$result"
878878
 fi
879879
 
880
-result=$("$FORTSH_BIN" -c '[ -w "'"$TEST_DIR"'/readable.txt" ] && echo yes || echo no' 2>&1)
880
+result=$("$SHELL_BIN" -c '[ -w "'"$TEST_DIR"'/readable.txt" ] && echo yes || echo no' 2>&1)
881881
 if [ "$result" = "yes" ]; then
882882
     pass "[ -w file ] writable file"
883883
 else
@@ -888,21 +888,21 @@ fi
888888
 section "392. TEST BUILTIN vs [ COMMAND"
889889
 # =====================================
890890
 
891
-result=$("$FORTSH_BIN" -c 'test -f /etc/passwd && echo yes || echo no' 2>&1)
891
+result=$("$SHELL_BIN" -c 'test -f /etc/passwd && echo yes || echo no' 2>&1)
892892
 if [ "$result" = "yes" ]; then
893893
     pass "test -f /etc/passwd"
894894
 else
895895
     fail "test -f /etc/passwd" "yes" "$result"
896896
 fi
897897
 
898
-result=$("$FORTSH_BIN" -c 'test 5 -eq 5 && echo yes || echo no' 2>&1)
898
+result=$("$SHELL_BIN" -c 'test 5 -eq 5 && echo yes || echo no' 2>&1)
899899
 if [ "$result" = "yes" ]; then
900900
     pass "test 5 -eq 5"
901901
 else
902902
     fail "test 5 -eq 5" "yes" "$result"
903903
 fi
904904
 
905
-result=$("$FORTSH_BIN" -c 'test "hello" = "hello" && echo yes || echo no' 2>&1)
905
+result=$("$SHELL_BIN" -c 'test "hello" = "hello" && echo yes || echo no' 2>&1)
906906
 if [ "$result" = "yes" ]; then
907907
     pass "test string equality"
908908
 else
@@ -913,21 +913,21 @@ fi
913913
 section "393. COMBINED LOGICAL TESTS"
914914
 # =====================================
915915
 
916
-result=$("$FORTSH_BIN" -c '[ 5 -gt 3 ] && [ 10 -gt 5 ] && echo yes || echo no' 2>&1)
916
+result=$("$SHELL_BIN" -c '[ 5 -gt 3 ] && [ 10 -gt 5 ] && echo yes || echo no' 2>&1)
917917
 if [ "$result" = "yes" ]; then
918918
     pass "[ ] && [ ] both true"
919919
 else
920920
     fail "[ ] && [ ] both true" "yes" "$result"
921921
 fi
922922
 
923
-result=$("$FORTSH_BIN" -c '[ 5 -lt 3 ] || [ 10 -gt 5 ] && echo yes || echo no' 2>&1)
923
+result=$("$SHELL_BIN" -c '[ 5 -lt 3 ] || [ 10 -gt 5 ] && echo yes || echo no' 2>&1)
924924
 if [ "$result" = "yes" ]; then
925925
     pass "[ ] || [ ] one true"
926926
 else
927927
     fail "[ ] || [ ] one true" "yes" "$result"
928928
 fi
929929
 
930
-result=$("$FORTSH_BIN" -c '! [ 5 -lt 3 ] && echo yes || echo no' 2>&1)
930
+result=$("$SHELL_BIN" -c '! [ 5 -lt 3 ] && echo yes || echo no' 2>&1)
931931
 if [ "$result" = "yes" ]; then
932932
     pass "! [ ] negation"
933933
 else
@@ -938,28 +938,28 @@ fi
938938
 section "394. FILE TYPE TESTS"
939939
 # =====================================
940940
 
941
-result=$("$FORTSH_BIN" -c '[ -f /etc/passwd ] && echo yes || echo no' 2>&1)
941
+result=$("$SHELL_BIN" -c '[ -f /etc/passwd ] && echo yes || echo no' 2>&1)
942942
 if [ "$result" = "yes" ]; then
943943
     pass "[ -f /etc/passwd ] regular file"
944944
 else
945945
     fail "[ -f /etc/passwd ] regular file" "yes" "$result"
946946
 fi
947947
 
948
-result=$("$FORTSH_BIN" -c '[ -d /tmp ] && echo yes || echo no' 2>&1)
948
+result=$("$SHELL_BIN" -c '[ -d /tmp ] && echo yes || echo no' 2>&1)
949949
 if [ "$result" = "yes" ]; then
950950
     pass "[ -d /tmp ] directory"
951951
 else
952952
     fail "[ -d /tmp ] directory" "yes" "$result"
953953
 fi
954954
 
955
-result=$("$FORTSH_BIN" -c '[ -e /etc/passwd ] && echo yes || echo no' 2>&1)
955
+result=$("$SHELL_BIN" -c '[ -e /etc/passwd ] && echo yes || echo no' 2>&1)
956956
 if [ "$result" = "yes" ]; then
957957
     pass "[ -e /etc/passwd ] exists"
958958
 else
959959
     fail "[ -e /etc/passwd ] exists" "yes" "$result"
960960
 fi
961961
 
962
-result=$("$FORTSH_BIN" -c '[ -e /nonexistent/path ] && echo yes || echo no' 2>&1)
962
+result=$("$SHELL_BIN" -c '[ -e /nonexistent/path ] && echo yes || echo no' 2>&1)
963963
 if [ "$result" = "no" ]; then
964964
     pass "[ -e /nonexistent ] does not exist"
965965
 else
@@ -971,7 +971,7 @@ section "395. FILE SIZE TESTS"
971971
 # =====================================
972972
 
973973
 echo "content" > "$TEST_DIR/nonempty.txt"
974
-result=$("$FORTSH_BIN" -c '[ -s "'"$TEST_DIR"'/nonempty.txt" ] && echo yes || echo no' 2>&1)
974
+result=$("$SHELL_BIN" -c '[ -s "'"$TEST_DIR"'/nonempty.txt" ] && echo yes || echo no' 2>&1)
975975
 if [ "$result" = "yes" ]; then
976976
     pass "[ -s file ] non-empty file"
977977
 else
@@ -979,7 +979,7 @@ else
979979
 fi
980980
 
981981
 : > "$TEST_DIR/empty.txt"
982
-result=$("$FORTSH_BIN" -c '[ -s "'"$TEST_DIR"'/empty.txt" ] && echo yes || echo no' 2>&1)
982
+result=$("$SHELL_BIN" -c '[ -s "'"$TEST_DIR"'/empty.txt" ] && echo yes || echo no' 2>&1)
983983
 if [ "$result" = "no" ]; then
984984
     pass "[ -s file ] empty file is false"
985985
 else
@@ -991,14 +991,14 @@ section "396. SYMLINK TESTS"
991991
 # =====================================
992992
 
993993
 ln -sf /etc/passwd "$TEST_DIR/link_to_passwd" 2>/dev/null || true
994
-result=$("$FORTSH_BIN" -c '[ -L "'"$TEST_DIR"'/link_to_passwd" ] && echo yes || echo no' 2>&1)
994
+result=$("$SHELL_BIN" -c '[ -L "'"$TEST_DIR"'/link_to_passwd" ] && echo yes || echo no' 2>&1)
995995
 if [ "$result" = "yes" ]; then
996996
     pass "[ -L symlink ] is symlink"
997997
 else
998998
     fail "[ -L symlink ] is symlink" "yes" "$result"
999999
 fi
10001000
 
1001
-result=$("$FORTSH_BIN" -c '[ -h "'"$TEST_DIR"'/link_to_passwd" ] && echo yes || echo no' 2>&1)
1001
+result=$("$SHELL_BIN" -c '[ -h "'"$TEST_DIR"'/link_to_passwd" ] && echo yes || echo no' 2>&1)
10021002
 if [ "$result" = "yes" ]; then
10031003
     pass "[ -h symlink ] is symlink (alternate)"
10041004
 else
@@ -1009,14 +1009,14 @@ fi
10091009
 section "397. SPECIAL FILE TESTS"
10101010
 # =====================================
10111011
 
1012
-result=$("$FORTSH_BIN" -c '[ -c /dev/null ] && echo yes || echo no' 2>&1)
1012
+result=$("$SHELL_BIN" -c '[ -c /dev/null ] && echo yes || echo no' 2>&1)
10131013
 if [ "$result" = "yes" ]; then
10141014
     pass "[ -c /dev/null ] character device"
10151015
 else
10161016
     fail "[ -c /dev/null ] character device" "yes" "$result"
10171017
 fi
10181018
 
1019
-result=$("$FORTSH_BIN" -c '[ -p /dev/null ] && echo yes || echo no' 2>&1)
1019
+result=$("$SHELL_BIN" -c '[ -p /dev/null ] && echo yes || echo no' 2>&1)
10201020
 if [ "$result" = "no" ]; then
10211021
     pass "[ -p /dev/null ] not a pipe"
10221022
 else
@@ -1027,7 +1027,7 @@ fi
10271027
 section "398. TERMINAL TESTS"
10281028
 # =====================================
10291029
 
1030
-result=$("$FORTSH_BIN" -c '[ -t 1 ] && echo tty || echo not_tty' 2>&1)
1030
+result=$("$SHELL_BIN" -c '[ -t 1 ] && echo tty || echo not_tty' 2>&1)
10311031
 # When running in a script, stdout is typically not a tty
10321032
 if echo "$result" | grep -qE "(tty|not_tty)"; then
10331033
     pass "[ -t 1 ] terminal test runs"
@@ -1039,14 +1039,14 @@ fi
10391039
 section "399. COMPOUND EXPRESSION PRECEDENCE"
10401040
 # =====================================
10411041
 
1042
-result=$("$FORTSH_BIN" -c '[ 1 -eq 1 ] && [ 2 -eq 2 ] && [ 3 -eq 3 ] && echo yes || echo no' 2>&1)
1042
+result=$("$SHELL_BIN" -c '[ 1 -eq 1 ] && [ 2 -eq 2 ] && [ 3 -eq 3 ] && echo yes || echo no' 2>&1)
10431043
 if [ "$result" = "yes" ]; then
10441044
     pass "Multiple && chain"
10451045
 else
10461046
     fail "Multiple && chain" "yes" "$result"
10471047
 fi
10481048
 
1049
-result=$("$FORTSH_BIN" -c '[ 1 -eq 2 ] || [ 2 -eq 2 ] && echo yes || echo no' 2>&1)
1049
+result=$("$SHELL_BIN" -c '[ 1 -eq 2 ] || [ 2 -eq 2 ] && echo yes || echo no' 2>&1)
10501050
 if [ "$result" = "yes" ]; then
10511051
     pass "|| then && precedence"
10521052
 else
@@ -1057,28 +1057,28 @@ fi
10571057
 section "400. EDGE CASE EXPRESSIONS"
10581058
 # =====================================
10591059
 
1060
-result=$("$FORTSH_BIN" -c '[ "" ] && echo yes || echo no' 2>&1)
1060
+result=$("$SHELL_BIN" -c '[ "" ] && echo yes || echo no' 2>&1)
10611061
 if [ "$result" = "no" ]; then
10621062
     pass "[ \"\" ] empty string is false"
10631063
 else
10641064
     fail "[ \"\" ] empty string is false" "no" "$result"
10651065
 fi
10661066
 
1067
-result=$("$FORTSH_BIN" -c '[ "x" ] && echo yes || echo no' 2>&1)
1067
+result=$("$SHELL_BIN" -c '[ "x" ] && echo yes || echo no' 2>&1)
10681068
 if [ "$result" = "yes" ]; then
10691069
     pass "[ \"x\" ] non-empty string is true"
10701070
 else
10711071
     fail "[ \"x\" ] non-empty string is true" "yes" "$result"
10721072
 fi
10731073
 
1074
-result=$("$FORTSH_BIN" -c '[ 0 ] && echo yes || echo no' 2>&1)
1074
+result=$("$SHELL_BIN" -c '[ 0 ] && echo yes || echo no' 2>&1)
10751075
 if [ "$result" = "yes" ]; then
10761076
     pass "[ 0 ] zero string is true (not numeric)"
10771077
 else
10781078
     fail "[ 0 ] zero string is true (not numeric)" "yes" "$result"
10791079
 fi
10801080
 
1081
-result=$("$FORTSH_BIN" -c '[ ! "" ] && echo yes || echo no' 2>&1)
1081
+result=$("$SHELL_BIN" -c '[ ! "" ] && echo yes || echo no' 2>&1)
10821082
 if [ "$result" = "yes" ]; then
10831083
     pass "[ ! \"\" ] negated empty is true"
10841084
 else
suites/posix/posix_compliance_gaps.shmodified
@@ -40,13 +40,13 @@ DEBUG_INFO=""
4040
 
4141
 # Get script directory (POSIX way)
4242
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
43
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
43
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
4444
 BASH_REF="${BASH_REF:-bash}"
4545
 
4646
 # Check if fortsh exists
47
-if [ ! -x "$FORTSH_BIN" ]; then
48
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
49
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
47
+if [ ! -x "$SHELL_BIN" ]; then
48
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
49
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
5050
     exit 1
5151
 fi
5252
 
@@ -103,7 +103,7 @@ compare_posix_output() {
103103
     "$BASH_REF" -c "$command" 2>&1 | normalize_output > "$posix_file" || true
104104
 
105105
     # Run in fortsh
106
-    "$FORTSH_BIN" -c "$command" 2>&1 | normalize_output > "$fortsh_file" || true
106
+    "$SHELL_BIN" -c "$command" 2>&1 | normalize_output > "$fortsh_file" || true
107107
 
108108
     # Compare outputs
109109
     if diff -q "$posix_file" "$fortsh_file" > /dev/null 2>&1; then
@@ -132,7 +132,7 @@ compare_posix_error() {
132132
     "$BASH_REF" -c "$command" > "$posix_file" 2>&1 || true
133133
 
134134
     # Run in fortsh
135
-    "$FORTSH_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
135
+    "$SHELL_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
136136
 
137137
     # Normalize error messages before comparison
138138
     posix_norm=$(normalize_error "$(cat "$posix_file")")
@@ -155,7 +155,7 @@ compare_posix_exit_code() {
155155
     "$BASH_REF" -c "$command" > /dev/null 2>&1
156156
     posix_exit=$?
157157
 
158
-    "$FORTSH_BIN" -c "$command" > /dev/null 2>&1
158
+    "$SHELL_BIN" -c "$command" > /dev/null 2>&1
159159
     fortsh_exit=$?
160160
 
161161
     if [ "$posix_exit" -eq "$fortsh_exit" ]; then
suites/posix/posix_compliance_heredoc.shmodified
@@ -24,12 +24,12 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 
2929
 # Check if fortsh exists
30
-if [ ! -x "$FORTSH_BIN" ]; then
31
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
+if [ ! -x "$SHELL_BIN" ]; then
31
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
32
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3333
     exit 1
3434
 fi
3535
 
@@ -73,7 +73,7 @@ section() {
7373
 section "396. BASIC HERE-DOCUMENT"
7474
 # =====================================
7575
 
76
-result=$("$FORTSH_BIN" -c 'cat <<EOF
76
+result=$("$SHELL_BIN" -c 'cat <<EOF
7777
 hello world
7878
 EOF' 2>&1)
7979
 if [ "$result" = "hello world" ]; then
@@ -82,7 +82,7 @@ else
8282
     fail "Basic here-document" "hello world" "$result"
8383
 fi
8484
 
85
-result=$("$FORTSH_BIN" -c 'cat <<END
85
+result=$("$SHELL_BIN" -c 'cat <<END
8686
 line one
8787
 line two
8888
 END' 2>&1)
@@ -93,7 +93,7 @@ else
9393
     fail "Here-document multiple lines" "$expected" "$result"
9494
 fi
9595
 
96
-result=$("$FORTSH_BIN" -c 'x=world; cat <<EOF
96
+result=$("$SHELL_BIN" -c 'x=world; cat <<EOF
9797
 hello $x
9898
 EOF' 2>&1)
9999
 if [ "$result" = "hello world" ]; then
@@ -102,7 +102,7 @@ else
102102
     fail "Here-document with variable expansion" "hello world" "$result"
103103
 fi
104104
 
105
-result=$("$FORTSH_BIN" -c 'cat <<EOF
105
+result=$("$SHELL_BIN" -c 'cat <<EOF
106106
 result: $(echo test)
107107
 EOF' 2>&1)
108108
 if [ "$result" = "result: test" ]; then
@@ -115,7 +115,7 @@ fi
115115
 section "397. QUOTED HERE-DOCUMENT DELIMITER"
116116
 # =====================================
117117
 
118
-result=$("$FORTSH_BIN" -c 'x=world; cat <<"EOF"
118
+result=$("$SHELL_BIN" -c 'x=world; cat <<"EOF"
119119
 hello $x
120120
 EOF' 2>&1)
121121
 if [ "$result" = 'hello $x' ]; then
@@ -124,7 +124,7 @@ else
124124
     fail "Quoted delimiter prevents expansion" 'hello $x' "$result"
125125
 fi
126126
 
127
-result=$("$FORTSH_BIN" -c "cat <<'END'
127
+result=$("$SHELL_BIN" -c "cat <<'END'
128128
 test \$(echo foo)
129129
 END" 2>&1)
130130
 if [ "$result" = 'test $(echo foo)' ]; then
@@ -137,7 +137,7 @@ fi
137137
 section "398. HERE-DOCUMENT WITH TAB STRIPPING (<<-)"
138138
 # =====================================
139139
 
140
-result=$("$FORTSH_BIN" -c '	cat <<-EOF
140
+result=$("$SHELL_BIN" -c '	cat <<-EOF
141141
 	hello
142142
 	world
143143
 	EOF' 2>&1)
@@ -148,7 +148,7 @@ else
148148
     fail "<<- strips leading tabs" "$expected" "$result"
149149
 fi
150150
 
151
-result=$("$FORTSH_BIN" -c 'cat <<-END
151
+result=$("$SHELL_BIN" -c 'cat <<-END
152152
 		indented
153153
 	END' 2>&1)
154154
 if [ "$result" = "indented" ]; then
@@ -161,7 +161,7 @@ fi
161161
 section "399. HERE-DOCUMENT TO DIFFERENT COMMANDS"
162162
 # =====================================
163163
 
164
-result=$("$FORTSH_BIN" -c 'wc -l <<EOF
164
+result=$("$SHELL_BIN" -c 'wc -l <<EOF
165165
 one
166166
 two
167167
 three
@@ -195,7 +195,7 @@ else
195195
         return $_to_rc
196196
     }
197197
 fi
198
-result=$(_timeout 2 "$FORTSH_BIN" -c 'read x <<EOF
198
+result=$(_timeout 2 "$SHELL_BIN" -c 'read x <<EOF
199199
 test input
200200
 EOF
201201
 echo "$x"' 2>&1)
@@ -212,35 +212,35 @@ fi
212212
 section "400. PARAMETER EXPANSION ${var:-default}"
213213
 # =====================================
214214
 
215
-result=$("$FORTSH_BIN" -c 'unset x; echo ${x:-default}' 2>&1)
215
+result=$("$SHELL_BIN" -c 'unset x; echo ${x:-default}' 2>&1)
216216
 if [ "$result" = "default" ]; then
217217
     pass "\${var:-default} for unset variable"
218218
 else
219219
     fail "\${var:-default} for unset variable" "default" "$result"
220220
 fi
221221
 
222
-result=$("$FORTSH_BIN" -c 'x=""; echo ${x:-default}' 2>&1)
222
+result=$("$SHELL_BIN" -c 'x=""; echo ${x:-default}' 2>&1)
223223
 if [ "$result" = "default" ]; then
224224
     pass "\${var:-default} for empty variable"
225225
 else
226226
     fail "\${var:-default} for empty variable" "default" "$result"
227227
 fi
228228
 
229
-result=$("$FORTSH_BIN" -c 'x=value; echo ${x:-default}' 2>&1)
229
+result=$("$SHELL_BIN" -c 'x=value; echo ${x:-default}' 2>&1)
230230
 if [ "$result" = "value" ]; then
231231
     pass "\${var:-default} for set variable"
232232
 else
233233
     fail "\${var:-default} for set variable" "value" "$result"
234234
 fi
235235
 
236
-result=$("$FORTSH_BIN" -c 'unset x; echo ${x-default}' 2>&1)
236
+result=$("$SHELL_BIN" -c 'unset x; echo ${x-default}' 2>&1)
237237
 if [ "$result" = "default" ]; then
238238
     pass "\${var-default} for unset (no colon)"
239239
 else
240240
     fail "\${var-default} for unset (no colon)" "default" "$result"
241241
 fi
242242
 
243
-result=$("$FORTSH_BIN" -c 'x=""; echo ${x-default}' 2>&1)
243
+result=$("$SHELL_BIN" -c 'x=""; echo ${x-default}' 2>&1)
244244
 if [ "$result" = "" ]; then
245245
     pass "\${var-default} for empty (no colon)"
246246
 else
@@ -251,21 +251,21 @@ fi
251251
 section "401. PARAMETER EXPANSION ${var:+alternate}"
252252
 # =====================================
253253
 
254
-result=$("$FORTSH_BIN" -c 'x=value; echo ${x:+alternate}' 2>&1)
254
+result=$("$SHELL_BIN" -c 'x=value; echo ${x:+alternate}' 2>&1)
255255
 if [ "$result" = "alternate" ]; then
256256
     pass "\${var:+alternate} for set variable"
257257
 else
258258
     fail "\${var:+alternate} for set variable" "alternate" "$result"
259259
 fi
260260
 
261
-result=$("$FORTSH_BIN" -c 'unset x; echo ${x:+alternate}' 2>&1)
261
+result=$("$SHELL_BIN" -c 'unset x; echo ${x:+alternate}' 2>&1)
262262
 if [ "$result" = "" ]; then
263263
     pass "\${var:+alternate} for unset variable"
264264
 else
265265
     fail "\${var:+alternate} for unset variable" "(empty)" "$result"
266266
 fi
267267
 
268
-result=$("$FORTSH_BIN" -c 'x=""; echo ${x:+alternate}' 2>&1)
268
+result=$("$SHELL_BIN" -c 'x=""; echo ${x:+alternate}' 2>&1)
269269
 if [ "$result" = "" ]; then
270270
     pass "\${var:+alternate} for empty variable"
271271
 else
@@ -276,7 +276,7 @@ fi
276276
 section "402. PARAMETER EXPANSION ${var:=assign}"
277277
 # =====================================
278278
 
279
-result=$("$FORTSH_BIN" -c 'unset x; echo ${x:=assigned}; echo $x' 2>&1)
279
+result=$("$SHELL_BIN" -c 'unset x; echo ${x:=assigned}; echo $x' 2>&1)
280280
 expected=$(printf "assigned\nassigned")
281281
 if [ "$result" = "$expected" ]; then
282282
     pass "\${var:=value} assigns when unset"
@@ -284,7 +284,7 @@ else
284284
     fail "\${var:=value} assigns when unset" "$expected" "$result"
285285
 fi
286286
 
287
-result=$("$FORTSH_BIN" -c 'x=""; echo ${x:=assigned}; echo $x' 2>&1)
287
+result=$("$SHELL_BIN" -c 'x=""; echo ${x:=assigned}; echo $x' 2>&1)
288288
 expected=$(printf "assigned\nassigned")
289289
 if [ "$result" = "$expected" ]; then
290290
     pass "\${var:=value} assigns when empty"
@@ -292,7 +292,7 @@ else
292292
     fail "\${var:=value} assigns when empty" "$expected" "$result"
293293
 fi
294294
 
295
-result=$("$FORTSH_BIN" -c 'x=original; echo ${x:=assigned}; echo $x' 2>&1)
295
+result=$("$SHELL_BIN" -c 'x=original; echo ${x:=assigned}; echo $x' 2>&1)
296296
 expected=$(printf "original\noriginal")
297297
 if [ "$result" = "$expected" ]; then
298298
     pass "\${var:=value} keeps original when set"
@@ -304,14 +304,14 @@ fi
304304
 section "403. PARAMETER EXPANSION ${var:?error}"
305305
 # =====================================
306306
 
307
-result=$("$FORTSH_BIN" -c 'x=value; echo ${x:?error message}' 2>&1)
307
+result=$("$SHELL_BIN" -c 'x=value; echo ${x:?error message}' 2>&1)
308308
 if [ "$result" = "value" ]; then
309309
     pass "\${var:?error} returns value when set"
310310
 else
311311
     fail "\${var:?error} returns value when set" "value" "$result"
312312
 fi
313313
 
314
-result=$("$FORTSH_BIN" -c 'unset x; echo ${x:?custom error}' 2>&1)
314
+result=$("$SHELL_BIN" -c 'unset x; echo ${x:?custom error}' 2>&1)
315315
 if echo "$result" | grep -qi "error\|custom"; then
316316
     pass "\${var:?error} shows error when unset"
317317
 else
@@ -322,21 +322,21 @@ fi
322322
 section "404. PARAMETER EXPANSION ${#var}"
323323
 # =====================================
324324
 
325
-result=$("$FORTSH_BIN" -c 'x=hello; echo ${#x}' 2>&1)
325
+result=$("$SHELL_BIN" -c 'x=hello; echo ${#x}' 2>&1)
326326
 if [ "$result" = "5" ]; then
327327
     pass "\${#var} string length"
328328
 else
329329
     fail "\${#var} string length" "5" "$result"
330330
 fi
331331
 
332
-result=$("$FORTSH_BIN" -c 'x=""; echo ${#x}' 2>&1)
332
+result=$("$SHELL_BIN" -c 'x=""; echo ${#x}' 2>&1)
333333
 if [ "$result" = "0" ]; then
334334
     pass "\${#var} empty string length"
335335
 else
336336
     fail "\${#var} empty string length" "0" "$result"
337337
 fi
338338
 
339
-result=$("$FORTSH_BIN" -c 'x="hello world"; echo ${#x}' 2>&1)
339
+result=$("$SHELL_BIN" -c 'x="hello world"; echo ${#x}' 2>&1)
340340
 if [ "$result" = "11" ]; then
341341
     pass "\${#var} string with space"
342342
 else
@@ -347,21 +347,21 @@ fi
347347
 section "405. PARAMETER EXPANSION ${var%pattern}"
348348
 # =====================================
349349
 
350
-result=$("$FORTSH_BIN" -c 'x="file.txt"; echo ${x%.txt}' 2>&1)
350
+result=$("$SHELL_BIN" -c 'x="file.txt"; echo ${x%.txt}' 2>&1)
351351
 if [ "$result" = "file" ]; then
352352
     pass "\${var%pattern} removes shortest suffix"
353353
 else
354354
     fail "\${var%pattern} removes shortest suffix" "file" "$result"
355355
 fi
356356
 
357
-result=$("$FORTSH_BIN" -c 'x="file.tar.gz"; echo ${x%.*}' 2>&1)
357
+result=$("$SHELL_BIN" -c 'x="file.tar.gz"; echo ${x%.*}' 2>&1)
358358
 if [ "$result" = "file.tar" ]; then
359359
     pass "\${var%.*} removes extension"
360360
 else
361361
     fail "\${var%.*} removes extension" "file.tar" "$result"
362362
 fi
363363
 
364
-result=$("$FORTSH_BIN" -c 'x="file.tar.gz"; echo ${x%%.*}' 2>&1)
364
+result=$("$SHELL_BIN" -c 'x="file.tar.gz"; echo ${x%%.*}' 2>&1)
365365
 if [ "$result" = "file" ]; then
366366
     pass "\${var%%.*} removes all extensions"
367367
 else
@@ -372,21 +372,21 @@ fi
372372
 section "406. PARAMETER EXPANSION ${var#pattern}"
373373
 # =====================================
374374
 
375
-result=$("$FORTSH_BIN" -c 'x="/path/to/file"; echo ${x#*/}' 2>&1)
375
+result=$("$SHELL_BIN" -c 'x="/path/to/file"; echo ${x#*/}' 2>&1)
376376
 if [ "$result" = "path/to/file" ]; then
377377
     pass "\${var#*/} removes shortest prefix"
378378
 else
379379
     fail "\${var#*/} removes shortest prefix" "path/to/file" "$result"
380380
 fi
381381
 
382
-result=$("$FORTSH_BIN" -c 'x="/path/to/file"; echo ${x##*/}' 2>&1)
382
+result=$("$SHELL_BIN" -c 'x="/path/to/file"; echo ${x##*/}' 2>&1)
383383
 if [ "$result" = "file" ]; then
384384
     pass "\${var##*/} basename extraction"
385385
 else
386386
     fail "\${var##*/} basename extraction" "file" "$result"
387387
 fi
388388
 
389
-result=$("$FORTSH_BIN" -c 'x="prefix_name"; echo ${x#prefix_}' 2>&1)
389
+result=$("$SHELL_BIN" -c 'x="prefix_name"; echo ${x#prefix_}' 2>&1)
390390
 if [ "$result" = "name" ]; then
391391
     pass "\${var#prefix} removes literal prefix"
392392
 else
@@ -397,21 +397,21 @@ fi
397397
 section "407. BACKTICK COMMAND SUBSTITUTION"
398398
 # =====================================
399399
 
400
-result=$("$FORTSH_BIN" -c 'echo `echo hello`' 2>&1)
400
+result=$("$SHELL_BIN" -c 'echo `echo hello`' 2>&1)
401401
 if [ "$result" = "hello" ]; then
402402
     pass "Basic backtick substitution"
403403
 else
404404
     fail "Basic backtick substitution" "hello" "$result"
405405
 fi
406406
 
407
-result=$("$FORTSH_BIN" -c 'x=`expr 2 + 3`; echo $x' 2>&1)
407
+result=$("$SHELL_BIN" -c 'x=`expr 2 + 3`; echo $x' 2>&1)
408408
 if [ "$result" = "5" ]; then
409409
     pass "Backtick with expr"
410410
 else
411411
     fail "Backtick with expr" "5" "$result"
412412
 fi
413413
 
414
-result=$("$FORTSH_BIN" -c 'echo `echo \`echo nested\``' 2>&1)
414
+result=$("$SHELL_BIN" -c 'echo `echo \`echo nested\``' 2>&1)
415415
 if [ "$result" = "nested" ]; then
416416
     pass "Nested backtick substitution"
417417
 else
@@ -422,21 +422,21 @@ fi
422422
 section "408. COMMAND SUBSTITUTION EDGE CASES"
423423
 # =====================================
424424
 
425
-result=$("$FORTSH_BIN" -c 'echo "$(echo "inner quotes")"' 2>&1)
425
+result=$("$SHELL_BIN" -c 'echo "$(echo "inner quotes")"' 2>&1)
426426
 if [ "$result" = "inner quotes" ]; then
427427
     pass "\$(...) with inner quotes"
428428
 else
429429
     fail "\$(...) with inner quotes" "inner quotes" "$result"
430430
 fi
431431
 
432
-result=$("$FORTSH_BIN" -c 'echo $(echo $(echo nested))' 2>&1)
432
+result=$("$SHELL_BIN" -c 'echo $(echo $(echo nested))' 2>&1)
433433
 if [ "$result" = "nested" ]; then
434434
     pass "Nested \$(...) substitution"
435435
 else
436436
     fail "Nested \$(...) substitution" "nested" "$result"
437437
 fi
438438
 
439
-result=$("$FORTSH_BIN" -c 'x=$(cat <<EOF
439
+result=$("$SHELL_BIN" -c 'x=$(cat <<EOF
440440
 multi
441441
 line
442442
 EOF
@@ -452,196 +452,196 @@ fi
452452
 section "409. ARITHMETIC EXPANSION"
453453
 # =====================================
454454
 
455
-result=$("$FORTSH_BIN" -c 'echo $((2 + 3))' 2>&1)
455
+result=$("$SHELL_BIN" -c 'echo $((2 + 3))' 2>&1)
456456
 if [ "$result" = "5" ]; then
457457
     pass "\$((...)) addition"
458458
 else
459459
     fail "\$((...)) addition" "5" "$result"
460460
 fi
461461
 
462
-result=$("$FORTSH_BIN" -c 'echo $((10 - 3))' 2>&1)
462
+result=$("$SHELL_BIN" -c 'echo $((10 - 3))' 2>&1)
463463
 if [ "$result" = "7" ]; then
464464
     pass "\$((...)) subtraction"
465465
 else
466466
     fail "\$((...)) subtraction" "7" "$result"
467467
 fi
468468
 
469
-result=$("$FORTSH_BIN" -c 'echo $((4 * 5))' 2>&1)
469
+result=$("$SHELL_BIN" -c 'echo $((4 * 5))' 2>&1)
470470
 if [ "$result" = "20" ]; then
471471
     pass "\$((...)) multiplication"
472472
 else
473473
     fail "\$((...)) multiplication" "20" "$result"
474474
 fi
475475
 
476
-result=$("$FORTSH_BIN" -c 'echo $((20 / 4))' 2>&1)
476
+result=$("$SHELL_BIN" -c 'echo $((20 / 4))' 2>&1)
477477
 if [ "$result" = "5" ]; then
478478
     pass "\$((...)) division"
479479
 else
480480
     fail "\$((...)) division" "5" "$result"
481481
 fi
482482
 
483
-result=$("$FORTSH_BIN" -c 'echo $((17 % 5))' 2>&1)
483
+result=$("$SHELL_BIN" -c 'echo $((17 % 5))' 2>&1)
484484
 if [ "$result" = "2" ]; then
485485
     pass "\$((...)) modulo"
486486
 else
487487
     fail "\$((...)) modulo" "2" "$result"
488488
 fi
489489
 
490
-result=$("$FORTSH_BIN" -c 'x=5; echo $((x * 2))' 2>&1)
490
+result=$("$SHELL_BIN" -c 'x=5; echo $((x * 2))' 2>&1)
491491
 if [ "$result" = "10" ]; then
492492
     pass "\$((...)) with variable (no \$)"
493493
 else
494494
     fail "\$((...)) with variable (no \$)" "10" "$result"
495495
 fi
496496
 
497
-result=$("$FORTSH_BIN" -c 'x=5; echo $(($x * 2))' 2>&1)
497
+result=$("$SHELL_BIN" -c 'x=5; echo $(($x * 2))' 2>&1)
498498
 if [ "$result" = "10" ]; then
499499
     pass "\$((...)) with \$variable"
500500
 else
501501
     fail "\$((...)) with \$variable" "10" "$result"
502502
 fi
503503
 
504
-result=$("$FORTSH_BIN" -c 'echo $(( (2 + 3) * 4 ))' 2>&1)
504
+result=$("$SHELL_BIN" -c 'echo $(( (2 + 3) * 4 ))' 2>&1)
505505
 if [ "$result" = "20" ]; then
506506
     pass "\$((...)) with parentheses"
507507
 else
508508
     fail "\$((...)) with parentheses" "20" "$result"
509509
 fi
510510
 
511
-result=$("$FORTSH_BIN" -c 'echo $((-5 + 3))' 2>&1)
511
+result=$("$SHELL_BIN" -c 'echo $((-5 + 3))' 2>&1)
512512
 if [ "$result" = "-2" ]; then
513513
     pass "\$((...)) negative numbers"
514514
 else
515515
     fail "\$((...)) negative numbers" "-2" "$result"
516516
 fi
517517
 
518
-result=$("$FORTSH_BIN" -c 'echo $((5 > 3))' 2>&1)
518
+result=$("$SHELL_BIN" -c 'echo $((5 > 3))' 2>&1)
519519
 if [ "$result" = "1" ]; then
520520
     pass "\$((...)) greater than comparison"
521521
 else
522522
     fail "\$((...)) greater than comparison" "1" "$result"
523523
 fi
524524
 
525
-result=$("$FORTSH_BIN" -c 'echo $((3 > 5))' 2>&1)
525
+result=$("$SHELL_BIN" -c 'echo $((3 > 5))' 2>&1)
526526
 if [ "$result" = "0" ]; then
527527
     pass "\$((...)) greater than false"
528528
 else
529529
     fail "\$((...)) greater than false" "0" "$result"
530530
 fi
531531
 
532
-result=$("$FORTSH_BIN" -c 'echo $((5 < 10))' 2>&1)
532
+result=$("$SHELL_BIN" -c 'echo $((5 < 10))' 2>&1)
533533
 if [ "$result" = "1" ]; then
534534
     pass "\$((...)) less than comparison"
535535
 else
536536
     fail "\$((...)) less than comparison" "1" "$result"
537537
 fi
538538
 
539
-result=$("$FORTSH_BIN" -c 'echo $((5 == 5))' 2>&1)
539
+result=$("$SHELL_BIN" -c 'echo $((5 == 5))' 2>&1)
540540
 if [ "$result" = "1" ]; then
541541
     pass "\$((...)) equality"
542542
 else
543543
     fail "\$((...)) equality" "1" "$result"
544544
 fi
545545
 
546
-result=$("$FORTSH_BIN" -c 'echo $((5 != 3))' 2>&1)
546
+result=$("$SHELL_BIN" -c 'echo $((5 != 3))' 2>&1)
547547
 if [ "$result" = "1" ]; then
548548
     pass "\$((...)) inequality"
549549
 else
550550
     fail "\$((...)) inequality" "1" "$result"
551551
 fi
552552
 
553
-result=$("$FORTSH_BIN" -c 'echo $((5 >= 5))' 2>&1)
553
+result=$("$SHELL_BIN" -c 'echo $((5 >= 5))' 2>&1)
554554
 if [ "$result" = "1" ]; then
555555
     pass "\$((...)) greater or equal"
556556
 else
557557
     fail "\$((...)) greater or equal" "1" "$result"
558558
 fi
559559
 
560
-result=$("$FORTSH_BIN" -c 'echo $((3 <= 5))' 2>&1)
560
+result=$("$SHELL_BIN" -c 'echo $((3 <= 5))' 2>&1)
561561
 if [ "$result" = "1" ]; then
562562
     pass "\$((...)) less or equal"
563563
 else
564564
     fail "\$((...)) less or equal" "1" "$result"
565565
 fi
566566
 
567
-result=$("$FORTSH_BIN" -c 'echo $((1 && 1))' 2>&1)
567
+result=$("$SHELL_BIN" -c 'echo $((1 && 1))' 2>&1)
568568
 if [ "$result" = "1" ]; then
569569
     pass "\$((...)) logical AND"
570570
 else
571571
     fail "\$((...)) logical AND" "1" "$result"
572572
 fi
573573
 
574
-result=$("$FORTSH_BIN" -c 'echo $((1 && 0))' 2>&1)
574
+result=$("$SHELL_BIN" -c 'echo $((1 && 0))' 2>&1)
575575
 if [ "$result" = "0" ]; then
576576
     pass "\$((...)) logical AND false"
577577
 else
578578
     fail "\$((...)) logical AND false" "0" "$result"
579579
 fi
580580
 
581
-result=$("$FORTSH_BIN" -c 'echo $((0 || 1))' 2>&1)
581
+result=$("$SHELL_BIN" -c 'echo $((0 || 1))' 2>&1)
582582
 if [ "$result" = "1" ]; then
583583
     pass "\$((...)) logical OR"
584584
 else
585585
     fail "\$((...)) logical OR" "1" "$result"
586586
 fi
587587
 
588
-result=$("$FORTSH_BIN" -c 'echo $((!0))' 2>&1)
588
+result=$("$SHELL_BIN" -c 'echo $((!0))' 2>&1)
589589
 if [ "$result" = "1" ]; then
590590
     pass "\$((...)) logical NOT"
591591
 else
592592
     fail "\$((...)) logical NOT" "1" "$result"
593593
 fi
594594
 
595
-result=$("$FORTSH_BIN" -c 'echo $((5 & 3))' 2>&1)
595
+result=$("$SHELL_BIN" -c 'echo $((5 & 3))' 2>&1)
596596
 if [ "$result" = "1" ]; then
597597
     pass "\$((...)) bitwise AND"
598598
 else
599599
     fail "\$((...)) bitwise AND" "1" "$result"
600600
 fi
601601
 
602
-result=$("$FORTSH_BIN" -c 'echo $((5 | 3))' 2>&1)
602
+result=$("$SHELL_BIN" -c 'echo $((5 | 3))' 2>&1)
603603
 if [ "$result" = "7" ]; then
604604
     pass "\$((...)) bitwise OR"
605605
 else
606606
     fail "\$((...)) bitwise OR" "7" "$result"
607607
 fi
608608
 
609
-result=$("$FORTSH_BIN" -c 'echo $((5 ^ 3))' 2>&1)
609
+result=$("$SHELL_BIN" -c 'echo $((5 ^ 3))' 2>&1)
610610
 if [ "$result" = "6" ]; then
611611
     pass "\$((...)) bitwise XOR"
612612
 else
613613
     fail "\$((...)) bitwise XOR" "6" "$result"
614614
 fi
615615
 
616
-result=$("$FORTSH_BIN" -c 'echo $((1 << 4))' 2>&1)
616
+result=$("$SHELL_BIN" -c 'echo $((1 << 4))' 2>&1)
617617
 if [ "$result" = "16" ]; then
618618
     pass "\$((...)) left shift"
619619
 else
620620
     fail "\$((...)) left shift" "16" "$result"
621621
 fi
622622
 
623
-result=$("$FORTSH_BIN" -c 'echo $((16 >> 2))' 2>&1)
623
+result=$("$SHELL_BIN" -c 'echo $((16 >> 2))' 2>&1)
624624
 if [ "$result" = "4" ]; then
625625
     pass "\$((...)) right shift"
626626
 else
627627
     fail "\$((...)) right shift" "4" "$result"
628628
 fi
629629
 
630
-result=$("$FORTSH_BIN" -c 'echo $((5 > 3 ? 10 : 20))' 2>&1)
630
+result=$("$SHELL_BIN" -c 'echo $((5 > 3 ? 10 : 20))' 2>&1)
631631
 if [ "$result" = "10" ]; then
632632
     pass "\$((...)) ternary true"
633633
 else
634634
     fail "\$((...)) ternary true" "10" "$result"
635635
 fi
636636
 
637
-result=$("$FORTSH_BIN" -c 'echo $((5 < 3 ? 10 : 20))' 2>&1)
637
+result=$("$SHELL_BIN" -c 'echo $((5 < 3 ? 10 : 20))' 2>&1)
638638
 if [ "$result" = "20" ]; then
639639
     pass "\$((...)) ternary false"
640640
 else
641641
     fail "\$((...)) ternary false" "20" "$result"
642642
 fi
643643
 
644
-result=$("$FORTSH_BIN" -c 'x=5; echo $((x += 3)); echo $x' 2>&1)
644
+result=$("$SHELL_BIN" -c 'x=5; echo $((x += 3)); echo $x' 2>&1)
645645
 expected=$(printf "8\n8")
646646
 if [ "$result" = "$expected" ]; then
647647
     pass "\$((...)) += assignment"
@@ -649,7 +649,7 @@ else
649649
     fail "\$((...)) += assignment" "$expected" "$result"
650650
 fi
651651
 
652
-result=$("$FORTSH_BIN" -c 'x=10; echo $((x -= 3)); echo $x' 2>&1)
652
+result=$("$SHELL_BIN" -c 'x=10; echo $((x -= 3)); echo $x' 2>&1)
653653
 expected=$(printf "7\n7")
654654
 if [ "$result" = "$expected" ]; then
655655
     pass "\$((...)) -= assignment"
@@ -657,14 +657,14 @@ else
657657
     fail "\$((...)) -= assignment" "$expected" "$result"
658658
 fi
659659
 
660
-result=$("$FORTSH_BIN" -c 'x=5; echo $((x *= 3))' 2>&1)
660
+result=$("$SHELL_BIN" -c 'x=5; echo $((x *= 3))' 2>&1)
661661
 if [ "$result" = "15" ]; then
662662
     pass "\$((...)) *= assignment"
663663
 else
664664
     fail "\$((...)) *= assignment" "15" "$result"
665665
 fi
666666
 
667
-result=$("$FORTSH_BIN" -c 'x=5; echo $((++x)); echo $x' 2>&1)
667
+result=$("$SHELL_BIN" -c 'x=5; echo $((++x)); echo $x' 2>&1)
668668
 expected=$(printf "6\n6")
669669
 if [ "$result" = "$expected" ]; then
670670
     pass "\$((...)) pre-increment"
@@ -672,7 +672,7 @@ else
672672
     fail "\$((...)) pre-increment" "$expected" "$result"
673673
 fi
674674
 
675
-result=$("$FORTSH_BIN" -c 'x=5; echo $((x++)); echo $x' 2>&1)
675
+result=$("$SHELL_BIN" -c 'x=5; echo $((x++)); echo $x' 2>&1)
676676
 expected=$(printf "5\n6")
677677
 if [ "$result" = "$expected" ]; then
678678
     pass "\$((...)) post-increment"
@@ -680,7 +680,7 @@ else
680680
     fail "\$((...)) post-increment" "$expected" "$result"
681681
 fi
682682
 
683
-result=$("$FORTSH_BIN" -c 'x=5; echo $((--x)); echo $x' 2>&1)
683
+result=$("$SHELL_BIN" -c 'x=5; echo $((--x)); echo $x' 2>&1)
684684
 expected=$(printf "4\n4")
685685
 if [ "$result" = "$expected" ]; then
686686
     pass "\$((...)) pre-decrement"
@@ -688,7 +688,7 @@ else
688688
     fail "\$((...)) pre-decrement" "$expected" "$result"
689689
 fi
690690
 
691
-result=$("$FORTSH_BIN" -c 'x=5; echo $((x--)); echo $x' 2>&1)
691
+result=$("$SHELL_BIN" -c 'x=5; echo $((x--)); echo $x' 2>&1)
692692
 expected=$(printf "5\n4")
693693
 if [ "$result" = "$expected" ]; then
694694
     pass "\$((...)) post-decrement"
@@ -696,14 +696,14 @@ else
696696
     fail "\$((...)) post-decrement" "$expected" "$result"
697697
 fi
698698
 
699
-result=$("$FORTSH_BIN" -c 'echo $(( 2 + 3 * 4 ))' 2>&1)
699
+result=$("$SHELL_BIN" -c 'echo $(( 2 + 3 * 4 ))' 2>&1)
700700
 if [ "$result" = "14" ]; then
701701
     pass "\$((...)) operator precedence"
702702
 else
703703
     fail "\$((...)) operator precedence" "14" "$result"
704704
 fi
705705
 
706
-result=$("$FORTSH_BIN" -c 'a=2; b=3; echo $(( a * b + a ))' 2>&1)
706
+result=$("$SHELL_BIN" -c 'a=2; b=3; echo $(( a * b + a ))' 2>&1)
707707
 if [ "$result" = "8" ]; then
708708
     pass "\$((...)) multiple variables"
709709
 else
@@ -714,21 +714,21 @@ fi
714714
 section "410. TILDE EXPANSION"
715715
 # =====================================
716716
 
717
-result=$("$FORTSH_BIN" -c 'echo ~' 2>&1)
717
+result=$("$SHELL_BIN" -c 'echo ~' 2>&1)
718718
 if [ "$result" = "$HOME" ]; then
719719
     pass "~ expands to \$HOME"
720720
 else
721721
     fail "~ expands to \$HOME" "$HOME" "$result"
722722
 fi
723723
 
724
-result=$("$FORTSH_BIN" -c 'echo ~/test' 2>&1)
724
+result=$("$SHELL_BIN" -c 'echo ~/test' 2>&1)
725725
 if [ "$result" = "$HOME/test" ]; then
726726
     pass "~/path expands correctly"
727727
 else
728728
     fail "~/path expands correctly" "$HOME/test" "$result"
729729
 fi
730730
 
731
-result=$("$FORTSH_BIN" -c 'x=~; echo $x' 2>&1)
731
+result=$("$SHELL_BIN" -c 'x=~; echo $x' 2>&1)
732732
 if [ "$result" = "$HOME" ]; then
733733
     pass "~ in assignment expands"
734734
 else
suites/posix/posix_compliance_jobcontrol.shmodified
@@ -23,12 +23,12 @@ FAILED_TESTS_LIST=""
2323
 
2424
 # Get script directory (POSIX way)
2525
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
26
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
26
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2727
 
2828
 # Check if fortsh exists
29
-if [ ! -x "$FORTSH_BIN" ]; then
30
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
31
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
29
+if [ ! -x "$SHELL_BIN" ]; then
30
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
31
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3232
     exit 1
3333
 fi
3434
 
@@ -73,7 +73,7 @@ test_succeeds() {
7373
     test_name="$1"
7474
     test_cmd="$2"
7575
 
76
-    if FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" >/dev/null 2>&1; then
76
+    if FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" >/dev/null 2>&1; then
7777
         pass "$test_name"
7878
     else
7979
         fail "$test_name" "should succeed" "failed"
@@ -86,7 +86,7 @@ test_output() {
8686
     test_cmd="$2"
8787
     expected="$3"
8888
 
89
-    output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1)
89
+    output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1)
9090
     if [ "$output" = "$expected" ]; then
9191
         pass "$test_name"
9292
     else
@@ -100,7 +100,7 @@ test_contains() {
100100
     test_cmd="$2"
101101
     pattern="$3"
102102
 
103
-    output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1)
103
+    output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1)
104104
     if echo "$output" | grep -q "$pattern"; then
105105
         pass "$test_name"
106106
     else
@@ -202,7 +202,7 @@ test_output_unordered() {
202202
     test_cmd="$2"
203203
     shift 2
204204
 
205
-    output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1)
205
+    output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1)
206206
     for word in "$@"; do
207207
         if ! echo "$output" | grep -qF "$word"; then
208208
             fail "$test_name" "output containing '$word'" "$output"
suites/posix/posix_compliance_options.shmodified
1047 lines changed — click to load
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -74,35 +74,35 @@ section() {
7474
 section "381. SET -e (ERREXIT)"
7575
 # =====================================
7676
 
77
-result=$("$FORTSH_BIN" -c 'set -e; true; echo reached' 2>&1)
77
+result=$("$SHELL_BIN" -c 'set -e; true; echo reached' 2>&1)
7878
 if [ "$result" = "reached" ]; then
7979
     pass "set -e allows true command"
8080
 else
8181
     fail "set -e allows true command" "reached" "$result"
8282
 fi
8383
 
84
-result=$("$FORTSH_BIN" -c 'set -e; false; echo "should not reach"' 2>&1)
84
+result=$("$SHELL_BIN" -c 'set -e; false; echo "should not reach"' 2>&1)
8585
 if [ -z "$result" ] || ! echo "$result" | grep -q "should not reach"; then
8686
     pass "set -e exits on false"
8787
 else
8888
     fail "set -e exits on false" "(no output)" "$result"
8989
 fi
9090
 
91
-result=$("$FORTSH_BIN" -c 'set -e; if false; then echo no; fi; echo reached' 2>&1)
91
+result=$("$SHELL_BIN" -c 'set -e; if false; then echo no; fi; echo reached' 2>&1)
9292
 if [ "$result" = "reached" ]; then
9393
     pass "set -e ignores false in if condition"
9494
 else
9595
     fail "set -e ignores false in if condition" "reached" "$result"
9696
 fi
9797
 
98
-result=$("$FORTSH_BIN" -c 'set -e; false || echo fallback' 2>&1)
98
+result=$("$SHELL_BIN" -c 'set -e; false || echo fallback' 2>&1)
9999
 if [ "$result" = "fallback" ]; then
100100
     pass "set -e ignores false with || continuation"
101101
 else
102102
     fail "set -e ignores false with || continuation" "fallback" "$result"
103103
 fi
104104
 
105
-result=$("$FORTSH_BIN" -c 'set -e; ! false; echo reached' 2>&1)
105
+result=$("$SHELL_BIN" -c 'set -e; ! false; echo reached' 2>&1)
106106
 if [ "$result" = "reached" ]; then
107107
     pass "set -e ignores negated false"
108108
 else
@@ -113,14 +113,14 @@ fi
113113
 section "382. SET -u (NOUNSET)"
114114
 # =====================================
115115
 
116
-result=$("$FORTSH_BIN" -c 'set -u; x=hello; echo $x' 2>&1)
116
+result=$("$SHELL_BIN" -c 'set -u; x=hello; echo $x' 2>&1)
117117
 if [ "$result" = "hello" ]; then
118118
     pass "set -u allows set variable"
119119
 else
120120
     fail "set -u allows set variable" "hello" "$result"
121121
 fi
122122
 
123
-result=$("$FORTSH_BIN" -c 'set -u; echo $UNSET_VAR_12345' 2>&1)
123
+result=$("$SHELL_BIN" -c 'set -u; echo $UNSET_VAR_12345' 2>&1)
124124
 exit_code=$?
125125
 if echo "$result" | grep -qi "unbound\|unset\|error" || [ $exit_code -ne 0 ]; then
126126
     pass "set -u errors on unset variable"
@@ -128,7 +128,7 @@ else
128128
     fail "set -u errors on unset variable" "error message" "$result"
129129
 fi
130130
 
131
-result=$("$FORTSH_BIN" -c 'set -u; echo ${UNSET_VAR_12345:-default}' 2>&1)
131
+result=$("$SHELL_BIN" -c 'set -u; echo ${UNSET_VAR_12345:-default}' 2>&1)
132132
 if [ "$result" = "default" ]; then
133133
     pass "set -u allows default expansion"
134134
 else
@@ -139,21 +139,21 @@ fi
139139
 section "383. SET -f (NOGLOB)"
140140
 # =====================================
141141
 
142
-result=$("$FORTSH_BIN" -c 'set -f; echo *' 2>&1)
142
+result=$("$SHELL_BIN" -c 'set -f; echo *' 2>&1)
143143
 if [ "$result" = "*" ]; then
144144
     pass "set -f disables globbing"
145145
 else
146146
     fail "set -f disables globbing" "*" "$result"
147147
 fi
148148
 
149
-result=$("$FORTSH_BIN" -c 'set -f; echo [a-z]*' 2>&1)
149
+result=$("$SHELL_BIN" -c 'set -f; echo [a-z]*' 2>&1)
150150
 if [ "$result" = "[a-z]*" ]; then
151151
     pass "set -f disables bracket patterns"
152152
 else
153153
     fail "set -f disables bracket patterns" "[a-z]*" "$result"
154154
 fi
155155
 
156
-result=$("$FORTSH_BIN" -c 'set -f; set +f; cd /tmp && echo [a-z]* | head -c 20' 2>&1)
156
+result=$("$SHELL_BIN" -c 'set -f; set +f; cd /tmp && echo [a-z]* | head -c 20' 2>&1)
157157
 if [ "$result" != "[a-z]*" ] && [ -n "$result" ]; then
158158
     pass "set +f re-enables globbing"
159159
 else
@@ -164,7 +164,7 @@ fi
164164
 section "384. SET -n (NOEXEC)"
165165
 # =====================================
166166
 
167
-result=$("$FORTSH_BIN" -c 'set -n; echo hello' 2>&1)
167
+result=$("$SHELL_BIN" -c 'set -n; echo hello' 2>&1)
168168
 if [ -z "$result" ]; then
169169
     pass "set -n prevents execution"
170170
 else
@@ -175,14 +175,14 @@ fi
175175
 section "385. SET -x (XTRACE)"
176176
 # =====================================
177177
 
178
-result=$("$FORTSH_BIN" -c 'set -x; echo hello' 2>&1)
178
+result=$("$SHELL_BIN" -c 'set -x; echo hello' 2>&1)
179179
 if echo "$result" | grep -q "echo hello\|+ echo"; then
180180
     pass "set -x shows trace output"
181181
 else
182182
     fail "set -x shows trace output" "trace line" "$result"
183183
 fi
184184
 
185
-result=$("$FORTSH_BIN" -c 'set -x; x=5; echo $x' 2>&1)
185
+result=$("$SHELL_BIN" -c 'set -x; x=5; echo $x' 2>&1)
186186
 if echo "$result" | grep -qE "x=5|echo 5|\+ echo"; then
187187
     pass "set -x traces variable assignment"
188188
 else
@@ -195,7 +195,7 @@ section "386. SET -v (VERBOSE)"
195195
 
196196
 # Note: set -v only echoes lines as they're READ, not from -c argument
197197
 # Test that -v option is accepted and runs without error
198
-"$FORTSH_BIN" -c 'set -v; echo hello' >/dev/null 2>&1
198
+"$SHELL_BIN" -c 'set -v; echo hello' >/dev/null 2>&1
199199
 fortsh_exit=$?
200200
 "$BASH_REF" -c 'set -v; echo hello' >/dev/null 2>&1
201201
 bash_exit=$?
@@ -212,7 +212,7 @@ section "387. SET -C (NOCLOBBER)"
212212
 TEST_DIR="/tmp/fortsh_options_$$"
213213
 mkdir -p "$TEST_DIR"
214214
 
215
-result=$("$FORTSH_BIN" -c 'set -C; echo test > '"$TEST_DIR"'/clobber1; echo test2 > '"$TEST_DIR"'/clobber1' 2>&1)
215
+result=$("$SHELL_BIN" -c 'set -C; echo test > '"$TEST_DIR"'/clobber1; echo test2 > '"$TEST_DIR"'/clobber1' 2>&1)
216216
 if echo "$result" | grep -qi "exist\|cannot\|error\|clobber"; then
217217
     pass "set -C prevents clobbering existing file"
218218
 else
@@ -235,21 +235,21 @@ rm -rf "$TEST_DIR"
235235
 section "388. SET -o OPTIONS"
236236
 # =====================================
237237
 
238
-result=$("$FORTSH_BIN" -c 'set -o errexit; true; echo ok' 2>&1)
238
+result=$("$SHELL_BIN" -c 'set -o errexit; true; echo ok' 2>&1)
239239
 if [ "$result" = "ok" ]; then
240240
     pass "set -o errexit (same as -e)"
241241
 else
242242
     fail "set -o errexit (same as -e)" "ok" "$result"
243243
 fi
244244
 
245
-result=$("$FORTSH_BIN" -c 'set -o noglob; echo *' 2>&1)
245
+result=$("$SHELL_BIN" -c 'set -o noglob; echo *' 2>&1)
246246
 if [ "$result" = "*" ]; then
247247
     pass "set -o noglob (same as -f)"
248248
 else
249249
     fail "set -o noglob (same as -f)" "*" "$result"
250250
 fi
251251
 
252
-result=$("$FORTSH_BIN" -c 'set -o nounset; x=val; echo $x' 2>&1)
252
+result=$("$SHELL_BIN" -c 'set -o nounset; x=val; echo $x' 2>&1)
253253
 if [ "$result" = "val" ]; then
254254
     pass "set -o nounset (same as -u)"
255255
 else
@@ -260,28 +260,28 @@ fi
260260
 section "389. SET -- POSITIONAL PARAMETERS"
261261
 # =====================================
262262
 
263
-result=$("$FORTSH_BIN" -c 'set -- a b c; echo $1 $2 $3' 2>&1)
263
+result=$("$SHELL_BIN" -c 'set -- a b c; echo $1 $2 $3' 2>&1)
264264
 if [ "$result" = "a b c" ]; then
265265
     pass "set -- sets positional parameters"
266266
 else
267267
     fail "set -- sets positional parameters" "a b c" "$result"
268268
 fi
269269
 
270
-result=$("$FORTSH_BIN" -c 'set -- a b c d e; echo $#' 2>&1)
270
+result=$("$SHELL_BIN" -c 'set -- a b c d e; echo $#' 2>&1)
271271
 if [ "$result" = "5" ]; then
272272
     pass "set -- updates \$#"
273273
 else
274274
     fail "set -- updates \$#" "5" "$result"
275275
 fi
276276
 
277
-result=$("$FORTSH_BIN" -c 'set -- a b c; set --; echo $#' 2>&1)
277
+result=$("$SHELL_BIN" -c 'set -- a b c; set --; echo $#' 2>&1)
278278
 if [ "$result" = "0" ]; then
279279
     pass "set -- clears positional parameters"
280280
 else
281281
     fail "set -- clears positional parameters" "0" "$result"
282282
 fi
283283
 
284
-result=$("$FORTSH_BIN" -c 'set -- "a b" c; echo $1' 2>&1)
284
+result=$("$SHELL_BIN" -c 'set -- "a b" c; echo $1' 2>&1)
285285
 if [ "$result" = "a b" ]; then
286286
     pass "set -- preserves quoted args"
287287
 else
@@ -292,21 +292,21 @@ fi
292292
 section "390. READ BUILTIN BASIC"
293293
 # =====================================
294294
 
295
-result=$("$FORTSH_BIN" -c 'echo "hello" | { read x; echo $x; }' 2>&1)
295
+result=$("$SHELL_BIN" -c 'echo "hello" | { read x; echo $x; }' 2>&1)
296296
 if [ "$result" = "hello" ]; then
297297
     pass "read basic input"
298298
 else
299299
     fail "read basic input" "hello" "$result"
300300
 fi
301301
 
302
-result=$("$FORTSH_BIN" -c 'echo "one two three" | { read a b c; echo "$a|$b|$c"; }' 2>&1)
302
+result=$("$SHELL_BIN" -c 'echo "one two three" | { read a b c; echo "$a|$b|$c"; }' 2>&1)
303303
 if [ "$result" = "one|two|three" ]; then
304304
     pass "read multiple variables"
305305
 else
306306
     fail "read multiple variables" "one|two|three" "$result"
307307
 fi
308308
 
309
-result=$("$FORTSH_BIN" -c 'echo "one two three four" | { read a b; echo "$a|$b"; }' 2>&1)
309
+result=$("$SHELL_BIN" -c 'echo "one two three four" | { read a b; echo "$a|$b"; }' 2>&1)
310310
 if [ "$result" = "one|two three four" ]; then
311311
     pass "read remaining into last variable"
312312
 else
@@ -317,21 +317,21 @@ fi
317317
 section "391. READ WITH IFS"
318318
 # =====================================
319319
 
320
-result=$("$FORTSH_BIN" -c 'echo "a:b:c" | { IFS=: read x y z; echo "$x|$y|$z"; }' 2>&1)
320
+result=$("$SHELL_BIN" -c 'echo "a:b:c" | { IFS=: read x y z; echo "$x|$y|$z"; }' 2>&1)
321321
 if [ "$result" = "a|b|c" ]; then
322322
     pass "read with custom IFS"
323323
 else
324324
     fail "read with custom IFS" "a|b|c" "$result"
325325
 fi
326326
 
327
-result=$("$FORTSH_BIN" -c 'echo "a::c" | { IFS=: read x y z; echo "$x|$y|$z"; }' 2>&1)
327
+result=$("$SHELL_BIN" -c 'echo "a::c" | { IFS=: read x y z; echo "$x|$y|$z"; }' 2>&1)
328328
 if [ "$result" = "a||c" ]; then
329329
     pass "read with empty field"
330330
 else
331331
     fail "read with empty field" "a||c" "$result"
332332
 fi
333333
 
334
-result=$("$FORTSH_BIN" -c 'echo "  a  b  " | { read x y; echo ">$x|$y<"; }' 2>&1)
334
+result=$("$SHELL_BIN" -c 'echo "  a  b  " | { read x y; echo ">$x|$y<"; }' 2>&1)
335335
 if [ "$result" = ">a|b<" ]; then
336336
     pass "read strips leading/trailing whitespace"
337337
 else
@@ -342,7 +342,7 @@ fi
342342
 section "392. READ -r (RAW MODE)"
343343
 # =====================================
344344
 
345
-result=$("$FORTSH_BIN" -c 'echo "hello\\nworld" | { read -r x; echo "$x"; }' 2>&1)
345
+result=$("$SHELL_BIN" -c 'echo "hello\\nworld" | { read -r x; echo "$x"; }' 2>&1)
346346
 if [ "$result" = 'hello\nworld' ]; then
347347
     pass "read -r preserves backslashes"
348348
 else
@@ -352,7 +352,7 @@ fi
352352
 # POSIX: read without -r joins lines ending with backslash (line continuation)
353353
 # printf with single quotes produces: line<backslash><newline>continued<newline>
354354
 # read joins: line + continued = linecontinued
355
-result=$("$FORTSH_BIN" -c 'printf '"'"'line\\\ncontinued\n'"'"' | { read x; echo "$x"; }' 2>&1)
355
+result=$("$SHELL_BIN" -c 'printf '"'"'line\\\ncontinued\n'"'"' | { read x; echo "$x"; }' 2>&1)
356356
 if [ "$result" = "linecontinued" ]; then
357357
     pass "read without -r joins continued lines"
358358
 else
@@ -363,14 +363,14 @@ fi
363363
 section "393. READ EXIT STATUS"
364364
 # =====================================
365365
 
366
-result=$("$FORTSH_BIN" -c 'echo "test" | { read x; echo $?; }' 2>&1)
366
+result=$("$SHELL_BIN" -c 'echo "test" | { read x; echo $?; }' 2>&1)
367367
 if [ "$result" = "0" ]; then
368368
     pass "read returns 0 on success"
369369
 else
370370
     fail "read returns 0 on success" "0" "$result"
371371
 fi
372372
 
373
-result=$("$FORTSH_BIN" -c 'echo -n "" | { read x; echo $?; }' 2>&1)
373
+result=$("$SHELL_BIN" -c 'echo -n "" | { read x; echo $?; }' 2>&1)
374374
 if [ "$result" = "1" ]; then
375375
     pass "read returns non-zero on EOF"
376376
 else
@@ -381,28 +381,28 @@ fi
381381
 section "394. SHIFT BUILTIN"
382382
 # =====================================
383383
 
384
-result=$("$FORTSH_BIN" -c 'set -- a b c d; shift; echo $1 $2 $3' 2>&1)
384
+result=$("$SHELL_BIN" -c 'set -- a b c d; shift; echo $1 $2 $3' 2>&1)
385385
 if [ "$result" = "b c d" ]; then
386386
     pass "shift removes first parameter"
387387
 else
388388
     fail "shift removes first parameter" "b c d" "$result"
389389
 fi
390390
 
391
-result=$("$FORTSH_BIN" -c 'set -- a b c d e; shift 2; echo $1 $2 $3' 2>&1)
391
+result=$("$SHELL_BIN" -c 'set -- a b c d e; shift 2; echo $1 $2 $3' 2>&1)
392392
 if [ "$result" = "c d e" ]; then
393393
     pass "shift n removes n parameters"
394394
 else
395395
     fail "shift n removes n parameters" "c d e" "$result"
396396
 fi
397397
 
398
-result=$("$FORTSH_BIN" -c 'set -- a b c; shift; echo $#' 2>&1)
398
+result=$("$SHELL_BIN" -c 'set -- a b c; shift; echo $#' 2>&1)
399399
 if [ "$result" = "2" ]; then
400400
     pass "shift updates \$#"
401401
 else
402402
     fail "shift updates \$#" "2" "$result"
403403
 fi
404404
 
405
-result=$("$FORTSH_BIN" -c 'set -- a; shift 5 2>/dev/null; echo $?' 2>&1)
405
+result=$("$SHELL_BIN" -c 'set -- a; shift 5 2>/dev/null; echo $?' 2>&1)
406406
 if [ "$result" = "1" ]; then
407407
     pass "shift beyond count returns error"
408408
 else
@@ -413,21 +413,21 @@ fi
413413
 section "395. SPECIAL PARAMETERS"
414414
 # =====================================
415415
 
416
-result=$("$FORTSH_BIN" -c 'set -- a b c; echo "$@"' 2>&1)
416
+result=$("$SHELL_BIN" -c 'set -- a b c; echo "$@"' 2>&1)
417417
 if [ "$result" = "a b c" ]; then
418418
     pass "\$@ expands all positional parameters"
419419
 else
420420
     fail "\$@ expands all positional parameters" "a b c" "$result"
421421
 fi
422422
 
423
-result=$("$FORTSH_BIN" -c 'set -- a b c; echo "$*"' 2>&1)
423
+result=$("$SHELL_BIN" -c 'set -- a b c; echo "$*"' 2>&1)
424424
 if [ "$result" = "a b c" ]; then
425425
     pass "\$* expands all positional parameters"
426426
 else
427427
     fail "\$* expands all positional parameters" "a b c" "$result"
428428
 fi
429429
 
430
-result=$("$FORTSH_BIN" -c 'set -- a b c; for x in "$@"; do echo "[$x]"; done' 2>&1)
430
+result=$("$SHELL_BIN" -c 'set -- a b c; for x in "$@"; do echo "[$x]"; done' 2>&1)
431431
 expected=$(printf "[a]\n[b]\n[c]")
432432
 if [ "$result" = "$expected" ]; then
433433
     pass "\"\$@\" preserves separate arguments"
@@ -435,7 +435,7 @@ else
435435
     fail "\"\$@\" preserves separate arguments" "$expected" "$result"
436436
 fi
437437
 
438
-result=$("$FORTSH_BIN" -c 'set -- "a b" c; for x in "$@"; do echo "[$x]"; done' 2>&1)
438
+result=$("$SHELL_BIN" -c 'set -- "a b" c; for x in "$@"; do echo "[$x]"; done' 2>&1)
439439
 expected=$(printf "[a b]\n[c]")
440440
 if [ "$result" = "$expected" ]; then
441441
     pass "\"\$@\" preserves quoted arguments"
@@ -443,14 +443,14 @@ else
443443
     fail "\"\$@\" preserves quoted arguments" "$expected" "$result"
444444
 fi
445445
 
446
-result=$("$FORTSH_BIN" -c 'echo $$' 2>&1)
446
+result=$("$SHELL_BIN" -c 'echo $$' 2>&1)
447447
 if echo "$result" | grep -qE '^[0-9]+$' && [ "$result" -gt 0 ]; then
448448
     pass "\$\$ returns PID"
449449
 else
450450
     fail "\$\$ returns PID" "numeric PID" "$result"
451451
 fi
452452
 
453
-result=$("$FORTSH_BIN" -c 'echo $?' 2>&1)
453
+result=$("$SHELL_BIN" -c 'echo $?' 2>&1)
454454
 if [ "$result" = "0" ]; then
455455
     pass "\$? returns exit status"
456456
 else
@@ -461,7 +461,7 @@ fi
461461
 section "396. IFS WORD SPLITTING"
462462
 # =====================================
463463
 
464
-result=$("$FORTSH_BIN" -c 'x="a:b:c"; IFS=:; for w in $x; do echo "[$w]"; done' 2>&1)
464
+result=$("$SHELL_BIN" -c 'x="a:b:c"; IFS=:; for w in $x; do echo "[$w]"; done' 2>&1)
465465
 expected=$(printf "[a]\n[b]\n[c]")
466466
 if [ "$result" = "$expected" ]; then
467467
     pass "IFS changes word splitting"
@@ -469,35 +469,35 @@ else
469469
     fail "IFS changes word splitting" "$expected" "$result"
470470
 fi
471471
 
472
-result=$("$FORTSH_BIN" -c 'x="a::c"; IFS=:; set -- $x; echo $#' 2>&1)
472
+result=$("$SHELL_BIN" -c 'x="a::c"; IFS=:; set -- $x; echo $#' 2>&1)
473473
 if [ "$result" = "3" ]; then
474474
     pass "IFS empty fields create arguments"
475475
 else
476476
     fail "IFS empty fields create arguments" "3" "$result"
477477
 fi
478478
 
479
-result=$("$FORTSH_BIN" -c 'IFS=:; x="a:b:c"; echo $x' 2>&1)
479
+result=$("$SHELL_BIN" -c 'IFS=:; x="a:b:c"; echo $x' 2>&1)
480480
 if [ "$result" = "a b c" ]; then
481481
     pass "IFS affects echo output"
482482
 else
483483
     fail "IFS affects echo output" "a b c" "$result"
484484
 fi
485485
 
486
-result=$("$FORTSH_BIN" -c 'IFS=""; x="a b c"; for w in $x; do echo "[$w]"; done' 2>&1)
486
+result=$("$SHELL_BIN" -c 'IFS=""; x="a b c"; for w in $x; do echo "[$w]"; done' 2>&1)
487487
 if [ "$result" = "[a b c]" ]; then
488488
     pass "Empty IFS prevents splitting"
489489
 else
490490
     fail "Empty IFS prevents splitting" "[a b c]" "$result"
491491
 fi
492492
 
493
-result=$("$FORTSH_BIN" -c 'unset IFS; x="a  b"; echo $x' 2>&1)
493
+result=$("$SHELL_BIN" -c 'unset IFS; x="a  b"; echo $x' 2>&1)
494494
 if [ "$result" = "a b" ]; then
495495
     pass "unset IFS uses default"
496496
 else
497497
     fail "unset IFS uses default" "a b" "$result"
498498
 fi
499499
 
500
-result=$("$FORTSH_BIN" -c 'IFS=",;"; x="a,b;c"; set -- $x; echo $1 $2 $3' 2>&1)
500
+result=$("$SHELL_BIN" -c 'IFS=",;"; x="a,b;c"; set -- $x; echo $1 $2 $3' 2>&1)
501501
 if [ "$result" = "a b c" ]; then
502502
     pass "IFS with multiple characters"
503503
 else
@@ -508,7 +508,7 @@ fi
508508
 section "397. ALIAS BUILTIN"
509509
 # =====================================
510510
 
511
-result=$("$FORTSH_BIN" -c 'alias ll="ls -la"; alias ll' 2>&1)
511
+result=$("$SHELL_BIN" -c 'alias ll="ls -la"; alias ll' 2>&1)
512512
 if echo "$result" | grep -q "ls -la\|ll="; then
513513
     pass "alias defines and shows alias"
514514
 else
@@ -517,21 +517,21 @@ fi
517517
 
518518
 # Note: Aliases defined in -c mode aren't expanded in the same command line
519519
 # This matches bash behavior - aliases are expanded at parse time
520
-result=$("$FORTSH_BIN" -c 'alias greeting="echo hello"; alias greeting' 2>&1)
520
+result=$("$SHELL_BIN" -c 'alias greeting="echo hello"; alias greeting' 2>&1)
521521
 if echo "$result" | grep -q "echo hello"; then
522522
     pass "alias defines correctly (matches bash)"
523523
 else
524524
     fail "alias defines correctly (matches bash)" "echo hello" "$result"
525525
 fi
526526
 
527
-result=$("$FORTSH_BIN" -c 'alias x="echo a"; alias y="echo b"; alias | wc -l' 2>&1)
527
+result=$("$SHELL_BIN" -c 'alias x="echo a"; alias y="echo b"; alias | wc -l' 2>&1)
528528
 if [ "$result" -ge 2 ] 2>/dev/null; then
529529
     pass "alias lists all aliases"
530530
 else
531531
     fail "alias lists all aliases" "at least 2" "$result"
532532
 fi
533533
 
534
-result=$("$FORTSH_BIN" -c 'alias greet="echo hi"; unalias greet; greet 2>/dev/null; echo $?' 2>&1)
534
+result=$("$SHELL_BIN" -c 'alias greet="echo hi"; unalias greet; greet 2>/dev/null; echo $?' 2>&1)
535535
 if echo "$result" | grep -qE "127|1"; then
536536
     pass "unalias removes alias"
537537
 else
@@ -539,7 +539,7 @@ else
539539
 fi
540540
 
541541
 # Note: Test redefinition by checking alias output (execution won't work in same line)
542
-result=$("$FORTSH_BIN" -c 'alias foo="echo one"; alias foo="echo two"; alias foo' 2>&1)
542
+result=$("$SHELL_BIN" -c 'alias foo="echo one"; alias foo="echo two"; alias foo' 2>&1)
543543
 if echo "$result" | grep -q "echo two"; then
544544
     pass "alias can be redefined"
545545
 else
@@ -550,28 +550,28 @@ fi
550550
 section "398. EXPORT BUILTIN"
551551
 # =====================================
552552
 
553
-result=$("$FORTSH_BIN" -c 'export TESTVAR=hello; echo $TESTVAR' 2>&1)
553
+result=$("$SHELL_BIN" -c 'export TESTVAR=hello; echo $TESTVAR' 2>&1)
554554
 if [ "$result" = "hello" ]; then
555555
     pass "export sets and exports variable"
556556
 else
557557
     fail "export sets and exports variable" "hello" "$result"
558558
 fi
559559
 
560
-result=$("$FORTSH_BIN" -c 'MYVAR=world; export MYVAR; echo $MYVAR' 2>&1)
560
+result=$("$SHELL_BIN" -c 'MYVAR=world; export MYVAR; echo $MYVAR' 2>&1)
561561
 if [ "$result" = "world" ]; then
562562
     pass "export existing variable"
563563
 else
564564
     fail "export existing variable" "world" "$result"
565565
 fi
566566
 
567
-result=$("$FORTSH_BIN" -c 'export X=1 Y=2 Z=3; echo $X $Y $Z' 2>&1)
567
+result=$("$SHELL_BIN" -c 'export X=1 Y=2 Z=3; echo $X $Y $Z' 2>&1)
568568
 if [ "$result" = "1 2 3" ]; then
569569
     pass "export multiple variables"
570570
 else
571571
     fail "export multiple variables" "1 2 3" "$result"
572572
 fi
573573
 
574
-result=$("$FORTSH_BIN" -c 'export SUBTEST=value; sh -c "echo \$SUBTEST"' 2>&1)
574
+result=$("$SHELL_BIN" -c 'export SUBTEST=value; sh -c "echo \$SUBTEST"' 2>&1)
575575
 if [ "$result" = "value" ]; then
576576
     pass "exported var visible in subshell"
577577
 else
@@ -582,21 +582,21 @@ fi
582582
 section "399. READONLY BUILTIN"
583583
 # =====================================
584584
 
585
-result=$("$FORTSH_BIN" -c 'readonly CONST=42; echo $CONST' 2>&1)
585
+result=$("$SHELL_BIN" -c 'readonly CONST=42; echo $CONST' 2>&1)
586586
 if [ "$result" = "42" ]; then
587587
     pass "readonly sets variable"
588588
 else
589589
     fail "readonly sets variable" "42" "$result"
590590
 fi
591591
 
592
-result=$("$FORTSH_BIN" -c 'readonly RO=1; RO=2 2>&1; echo $RO' 2>&1)
592
+result=$("$SHELL_BIN" -c 'readonly RO=1; RO=2 2>&1; echo $RO' 2>&1)
593593
 if echo "$result" | grep -q "1"; then
594594
     pass "readonly prevents modification"
595595
 else
596596
     fail "readonly prevents modification" "1" "$result"
597597
 fi
598598
 
599
-result=$("$FORTSH_BIN" -c 'readonly A=1 B=2; echo $A $B' 2>&1)
599
+result=$("$SHELL_BIN" -c 'readonly A=1 B=2; echo $A $B' 2>&1)
600600
 if [ "$result" = "1 2" ]; then
601601
     pass "readonly multiple variables"
602602
 else
@@ -607,21 +607,21 @@ fi
607607
 section "400. UNSET BUILTIN"
608608
 # =====================================
609609
 
610
-result=$("$FORTSH_BIN" -c 'x=hello; unset x; echo "${x:-unset}"' 2>&1)
610
+result=$("$SHELL_BIN" -c 'x=hello; unset x; echo "${x:-unset}"' 2>&1)
611611
 if [ "$result" = "unset" ]; then
612612
     pass "unset removes variable"
613613
 else
614614
     fail "unset removes variable" "unset" "$result"
615615
 fi
616616
 
617
-result=$("$FORTSH_BIN" -c 'x=1; y=2; unset x y; echo "${x:-a} ${y:-b}"' 2>&1)
617
+result=$("$SHELL_BIN" -c 'x=1; y=2; unset x y; echo "${x:-a} ${y:-b}"' 2>&1)
618618
 if [ "$result" = "a b" ]; then
619619
     pass "unset multiple variables"
620620
 else
621621
     fail "unset multiple variables" "a b" "$result"
622622
 fi
623623
 
624
-result=$("$FORTSH_BIN" -c 'f() { echo hi; }; unset -f f; type f 2>/dev/null; echo $?' 2>&1)
624
+result=$("$SHELL_BIN" -c 'f() { echo hi; }; unset -f f; type f 2>/dev/null; echo $?' 2>&1)
625625
 if echo "$result" | grep -qE "1|127"; then
626626
     pass "unset -f removes function"
627627
 else
@@ -633,7 +633,7 @@ section "401. GETOPTS BUILTIN"
633633
 # =====================================
634634
 
635635
 # Basic option parsing
636
-result=$("$FORTSH_BIN" -c 'set -- -a; getopts "ab" opt; echo $opt' 2>&1)
636
+result=$("$SHELL_BIN" -c 'set -- -a; getopts "ab" opt; echo $opt' 2>&1)
637637
 if [ "$result" = "a" ]; then
638638
     pass "getopts parses simple option"
639639
 else
@@ -641,7 +641,7 @@ else
641641
 fi
642642
 
643643
 # Option with argument
644
-result=$("$FORTSH_BIN" -c 'set -- -a value; getopts "a:" opt; echo "$OPTARG"' 2>&1)
644
+result=$("$SHELL_BIN" -c 'set -- -a value; getopts "a:" opt; echo "$OPTARG"' 2>&1)
645645
 if [ "$result" = "value" ]; then
646646
     pass "getopts sets OPTARG"
647647
 else
@@ -649,7 +649,7 @@ else
649649
 fi
650650
 
651651
 # OPTIND increment
652
-result=$("$FORTSH_BIN" -c 'set -- -a -b; getopts "ab" opt; getopts "ab" opt; echo $OPTIND' 2>&1)
652
+result=$("$SHELL_BIN" -c 'set -- -a -b; getopts "ab" opt; getopts "ab" opt; echo $OPTIND' 2>&1)
653653
 if [ "$result" = "3" ]; then
654654
     pass "getopts increments OPTIND"
655655
 else
@@ -657,7 +657,7 @@ else
657657
 fi
658658
 
659659
 # Multiple options in loop
660
-result=$("$FORTSH_BIN" -c 'set -- -a -b -c; while getopts "abc" opt; do echo -n $opt; done' 2>&1)
660
+result=$("$SHELL_BIN" -c 'set -- -a -b -c; while getopts "abc" opt; do echo -n $opt; done' 2>&1)
661661
 if [ "$result" = "abc" ]; then
662662
     pass "getopts in while loop"
663663
 else
@@ -665,7 +665,7 @@ else
665665
 fi
666666
 
667667
 # Invalid option handling
668
-result=$("$FORTSH_BIN" -c 'set -- -z; getopts "ab" opt 2>/dev/null; echo $opt' 2>&1)
668
+result=$("$SHELL_BIN" -c 'set -- -z; getopts "ab" opt 2>/dev/null; echo $opt' 2>&1)
669669
 if [ "$result" = "?" ]; then
670670
     pass "getopts returns ? for invalid option"
671671
 else
@@ -673,7 +673,7 @@ else
673673
 fi
674674
 
675675
 # Silent mode with leading colon
676
-result=$("$FORTSH_BIN" -c 'set -- -a; getopts ":a:b" opt; echo $opt' 2>&1)
676
+result=$("$SHELL_BIN" -c 'set -- -a; getopts ":a:b" opt; echo $opt' 2>&1)
677677
 if [ "$result" = ":" ] || [ "$result" = "a" ]; then
678678
     pass "getopts silent mode with colon"
679679
 else
@@ -681,7 +681,7 @@ else
681681
 fi
682682
 
683683
 # Reset OPTIND
684
-result=$("$FORTSH_BIN" -c 'set -- -a; getopts "a" opt; OPTIND=1; getopts "a" opt; echo $opt' 2>&1)
684
+result=$("$SHELL_BIN" -c 'set -- -a; getopts "a" opt; OPTIND=1; getopts "a" opt; echo $opt' 2>&1)
685685
 if [ "$result" = "a" ]; then
686686
     pass "OPTIND reset allows reparse"
687687
 else
@@ -693,7 +693,7 @@ section "402. TYPE BUILTIN"
693693
 # =====================================
694694
 
695695
 # type finds commands
696
-result=$("$FORTSH_BIN" -c 'type echo' 2>&1)
696
+result=$("$SHELL_BIN" -c 'type echo' 2>&1)
697697
 if echo "$result" | grep -qE "echo|builtin|/"; then
698698
     pass "type finds echo"
699699
 else
@@ -701,7 +701,7 @@ else
701701
 fi
702702
 
703703
 # type returns error for unknown
704
-result=$("$FORTSH_BIN" -c 'type nonexistent_xyz_cmd 2>/dev/null; echo $?' 2>&1)
704
+result=$("$SHELL_BIN" -c 'type nonexistent_xyz_cmd 2>/dev/null; echo $?' 2>&1)
705705
 if [ "$result" != "0" ]; then
706706
     pass "type returns error for unknown command"
707707
 else
@@ -709,7 +709,7 @@ else
709709
 fi
710710
 
711711
 # type finds functions
712
-result=$("$FORTSH_BIN" -c 'myfunc() { :; }; type myfunc' 2>&1)
712
+result=$("$SHELL_BIN" -c 'myfunc() { :; }; type myfunc' 2>&1)
713713
 if echo "$result" | grep -qE "myfunc|function"; then
714714
     pass "type finds functions"
715715
 else
@@ -717,7 +717,7 @@ else
717717
 fi
718718
 
719719
 # type finds aliases
720
-result=$("$FORTSH_BIN" -c 'alias myalias=echo; type myalias' 2>&1)
720
+result=$("$SHELL_BIN" -c 'alias myalias=echo; type myalias' 2>&1)
721721
 if echo "$result" | grep -qE "myalias|alias"; then
722722
     pass "type finds aliases"
723723
 else
@@ -725,7 +725,7 @@ else
725725
 fi
726726
 
727727
 # type finds builtins
728
-result=$("$FORTSH_BIN" -c 'type cd' 2>&1)
728
+result=$("$SHELL_BIN" -c 'type cd' 2>&1)
729729
 if echo "$result" | grep -qE "cd|builtin"; then
730730
     pass "type identifies builtins"
731731
 else
@@ -737,7 +737,7 @@ section "403. COMMAND BUILTIN"
737737
 # =====================================
738738
 
739739
 # command -v finds commands
740
-result=$("$FORTSH_BIN" -c 'command -v echo' 2>&1)
740
+result=$("$SHELL_BIN" -c 'command -v echo' 2>&1)
741741
 if [ -n "$result" ]; then
742742
     pass "command -v finds echo"
743743
 else
@@ -745,7 +745,7 @@ else
745745
 fi
746746
 
747747
 # command -v returns empty for unknown
748
-result=$("$FORTSH_BIN" -c 'command -v nonexistent_xyz_cmd; echo $?' 2>&1)
748
+result=$("$SHELL_BIN" -c 'command -v nonexistent_xyz_cmd; echo $?' 2>&1)
749749
 if [ "$result" != "0" ]; then
750750
     pass "command -v returns error for unknown"
751751
 else
@@ -753,7 +753,7 @@ else
753753
 fi
754754
 
755755
 # command bypasses functions
756
-result=$("$FORTSH_BIN" -c 'echo() { printf "FUNC"; }; command echo hello' 2>&1)
756
+result=$("$SHELL_BIN" -c 'echo() { printf "FUNC"; }; command echo hello' 2>&1)
757757
 if [ "$result" = "hello" ]; then
758758
     pass "command bypasses function"
759759
 else
@@ -761,7 +761,7 @@ else
761761
 fi
762762
 
763763
 # command bypasses aliases
764
-result=$("$FORTSH_BIN" -c 'alias echo="printf ALIAS"; command echo hello' 2>&1)
764
+result=$("$SHELL_BIN" -c 'alias echo="printf ALIAS"; command echo hello' 2>&1)
765765
 if [ "$result" = "hello" ]; then
766766
     pass "command bypasses alias"
767767
 else
@@ -773,7 +773,7 @@ section "404. TRAP BUILTIN EDGE CASES"
773773
 # =====================================
774774
 
775775
 # trap with empty action
776
-result=$("$FORTSH_BIN" -c 'trap "" INT; trap' 2>&1)
776
+result=$("$SHELL_BIN" -c 'trap "" INT; trap' 2>&1)
777777
 if echo "$result" | grep -qE "INT|''"; then
778778
     pass "trap with empty action (ignore signal)"
779779
 else
@@ -781,7 +781,7 @@ else
781781
 fi
782782
 
783783
 # trap - removes trap
784
-result=$("$FORTSH_BIN" -c 'trap "echo x" EXIT; trap - EXIT; trap' 2>&1)
784
+result=$("$SHELL_BIN" -c 'trap "echo x" EXIT; trap - EXIT; trap' 2>&1)
785785
 if ! echo "$result" | grep -q "EXIT"; then
786786
     pass "trap - removes trap"
787787
 else
@@ -789,7 +789,7 @@ else
789789
 fi
790790
 
791791
 # Multiple traps
792
-result=$("$FORTSH_BIN" -c 'trap "echo INT" INT; trap "echo TERM" TERM; trap | wc -l' 2>&1)
792
+result=$("$SHELL_BIN" -c 'trap "echo INT" INT; trap "echo TERM" TERM; trap | wc -l' 2>&1)
793793
 if [ "$result" -ge 2 ] 2>/dev/null; then
794794
     pass "Multiple traps can be set"
795795
 else
@@ -797,7 +797,7 @@ else
797797
 fi
798798
 
799799
 # trap with no args lists traps
800
-result=$("$FORTSH_BIN" -c 'trap "echo x" INT; trap' 2>&1)
800
+result=$("$SHELL_BIN" -c 'trap "echo x" INT; trap' 2>&1)
801801
 if [ -n "$result" ]; then
802802
     pass "trap with no args lists traps"
803803
 else
@@ -805,7 +805,7 @@ else
805805
 fi
806806
 
807807
 # EXIT trap runs on exit
808
-result=$("$FORTSH_BIN" -c 'trap "echo EXITING" EXIT; exit 0' 2>&1)
808
+result=$("$SHELL_BIN" -c 'trap "echo EXITING" EXIT; exit 0' 2>&1)
809809
 if [ "$result" = "EXITING" ]; then
810810
     pass "EXIT trap executes on exit"
811811
 else
@@ -817,12 +817,12 @@ section "405. HASH BUILTIN"
817817
 # =====================================
818818
 
819819
 # hash without args
820
-result=$("$FORTSH_BIN" -c 'hash 2>&1; echo $?' 2>&1)
820
+result=$("$SHELL_BIN" -c 'hash 2>&1; echo $?' 2>&1)
821821
 # hash returns 0 even if empty
822822
 pass "hash builtin exists"
823823
 
824824
 # hash -r clears cache
825
-result=$("$FORTSH_BIN" -c 'ls >/dev/null 2>&1; hash -r; echo $?' 2>&1)
825
+result=$("$SHELL_BIN" -c 'ls >/dev/null 2>&1; hash -r; echo $?' 2>&1)
826826
 if [ "$result" = "0" ]; then
827827
     pass "hash -r clears cache"
828828
 else
@@ -834,7 +834,7 @@ section "406. WAIT BUILTIN EDGE CASES"
834834
 # =====================================
835835
 
836836
 # wait with no args
837
-result=$("$FORTSH_BIN" -c 'sleep 0.1 & sleep 0.1 & wait; echo done' 2>&1)
837
+result=$("$SHELL_BIN" -c 'sleep 0.1 & sleep 0.1 & wait; echo done' 2>&1)
838838
 if [ "$result" = "done" ]; then
839839
     pass "wait with no args waits for all"
840840
 else
@@ -842,7 +842,7 @@ else
842842
 fi
843843
 
844844
 # wait with specific PID
845
-result=$("$FORTSH_BIN" -c 'sleep 0.1 & pid=$!; wait $pid; echo $?' 2>&1)
845
+result=$("$SHELL_BIN" -c 'sleep 0.1 & pid=$!; wait $pid; echo $?' 2>&1)
846846
 if [ "$result" = "0" ]; then
847847
     pass "wait with PID"
848848
 else
@@ -850,7 +850,7 @@ else
850850
 fi
851851
 
852852
 # wait preserves exit status
853
-result=$("$FORTSH_BIN" -c '(exit 42) & pid=$!; wait $pid; echo $?' 2>&1)
853
+result=$("$SHELL_BIN" -c '(exit 42) & pid=$!; wait $pid; echo $?' 2>&1)
854854
 if [ "$result" = "42" ]; then
855855
     pass "wait preserves exit status"
856856
 else
@@ -862,7 +862,7 @@ section "407. ULIMIT BUILTIN"
862862
 # =====================================
863863
 
864864
 # ulimit -a shows limits
865
-result=$("$FORTSH_BIN" -c 'ulimit -a 2>&1' | head -5)
865
+result=$("$SHELL_BIN" -c 'ulimit -a 2>&1' | head -5)
866866
 if [ -n "$result" ]; then
867867
     pass "ulimit -a shows limits"
868868
 else
@@ -870,7 +870,7 @@ else
870870
 fi
871871
 
872872
 # ulimit shows soft limit
873
-result=$("$FORTSH_BIN" -c 'ulimit 2>&1' | head -1)
873
+result=$("$SHELL_BIN" -c 'ulimit 2>&1' | head -1)
874874
 if [ -n "$result" ]; then
875875
     pass "ulimit shows default limit"
876876
 else
@@ -882,7 +882,7 @@ section "408. READ BUILTIN"
882882
 # =====================================
883883
 
884884
 # read single variable
885
-result=$("$FORTSH_BIN" -c 'echo "hello" | { read x; echo $x; }' 2>&1)
885
+result=$("$SHELL_BIN" -c 'echo "hello" | { read x; echo $x; }' 2>&1)
886886
 if [ "$result" = "hello" ]; then
887887
     pass "read single variable"
888888
 else
@@ -890,7 +890,7 @@ else
890890
 fi
891891
 
892892
 # read multiple variables
893
-result=$("$FORTSH_BIN" -c 'echo "a b c" | { read x y z; echo "$x:$y:$z"; }' 2>&1)
893
+result=$("$SHELL_BIN" -c 'echo "a b c" | { read x y z; echo "$x:$y:$z"; }' 2>&1)
894894
 if [ "$result" = "a:b:c" ]; then
895895
     pass "read multiple variables"
896896
 else
@@ -898,7 +898,7 @@ else
898898
 fi
899899
 
900900
 # read with extra words
901
-result=$("$FORTSH_BIN" -c 'echo "a b c d e" | { read x y; echo "$x|$y"; }' 2>&1)
901
+result=$("$SHELL_BIN" -c 'echo "a b c d e" | { read x y; echo "$x|$y"; }' 2>&1)
902902
 if [ "$result" = "a|b c d e" ]; then
903903
     pass "read extra words to last var"
904904
 else
@@ -910,7 +910,7 @@ section "409. PRINTF BUILTIN"
910910
 # =====================================
911911
 
912912
 # printf basic
913
-result=$("$FORTSH_BIN" -c 'printf "hello\n"' 2>&1)
913
+result=$("$SHELL_BIN" -c 'printf "hello\n"' 2>&1)
914914
 if [ "$result" = "hello" ]; then
915915
     pass "printf basic"
916916
 else
@@ -918,7 +918,7 @@ else
918918
 fi
919919
 
920920
 # printf with format
921
-result=$("$FORTSH_BIN" -c 'printf "%s world\n" "hello"' 2>&1)
921
+result=$("$SHELL_BIN" -c 'printf "%s world\n" "hello"' 2>&1)
922922
 if [ "$result" = "hello world" ]; then
923923
     pass "printf with %s"
924924
 else
@@ -926,7 +926,7 @@ else
926926
 fi
927927
 
928928
 # printf with number
929
-result=$("$FORTSH_BIN" -c 'printf "%d\n" 42' 2>&1)
929
+result=$("$SHELL_BIN" -c 'printf "%d\n" 42' 2>&1)
930930
 if [ "$result" = "42" ]; then
931931
     pass "printf with %d"
932932
 else
@@ -934,7 +934,7 @@ else
934934
 fi
935935
 
936936
 # printf width
937
-result=$("$FORTSH_BIN" -c 'printf "%5d\n" 42' 2>&1)
937
+result=$("$SHELL_BIN" -c 'printf "%5d\n" 42' 2>&1)
938938
 if [ "$result" = "   42" ]; then
939939
     pass "printf with width"
940940
 else
@@ -946,7 +946,7 @@ section "410. ECHO BUILTIN"
946946
 # =====================================
947947
 
948948
 # echo basic
949
-result=$("$FORTSH_BIN" -c 'echo hello' 2>&1)
949
+result=$("$SHELL_BIN" -c 'echo hello' 2>&1)
950950
 if [ "$result" = "hello" ]; then
951951
     pass "echo basic"
952952
 else
@@ -954,7 +954,7 @@ else
954954
 fi
955955
 
956956
 # echo multiple args
957
-result=$("$FORTSH_BIN" -c 'echo a b c' 2>&1)
957
+result=$("$SHELL_BIN" -c 'echo a b c' 2>&1)
958958
 if [ "$result" = "a b c" ]; then
959959
     pass "echo multiple args"
960960
 else
@@ -962,7 +962,7 @@ else
962962
 fi
963963
 
964964
 # echo with quotes
965
-result=$("$FORTSH_BIN" -c 'echo "hello world"' 2>&1)
965
+result=$("$SHELL_BIN" -c 'echo "hello world"' 2>&1)
966966
 if [ "$result" = "hello world" ]; then
967967
     pass "echo with quotes"
968968
 else
@@ -974,7 +974,7 @@ section "411. KILL BUILTIN"
974974
 # =====================================
975975
 
976976
 # kill -l lists signals
977
-result=$("$FORTSH_BIN" -c 'kill -l 2>&1 | head -1')
977
+result=$("$SHELL_BIN" -c 'kill -l 2>&1 | head -1')
978978
 if [ -n "$result" ]; then
979979
     pass "kill -l lists signals"
980980
 else
@@ -986,7 +986,7 @@ section "412. SET OPTIONS"
986986
 # =====================================
987987
 
988988
 # set -e (errexit)
989
-result=$("$FORTSH_BIN" -c 'set -e; true; echo reached' 2>&1)
989
+result=$("$SHELL_BIN" -c 'set -e; true; echo reached' 2>&1)
990990
 if [ "$result" = "reached" ]; then
991991
     pass "set -e continues on success"
992992
 else
@@ -994,7 +994,7 @@ else
994994
 fi
995995
 
996996
 # set -x (xtrace)
997
-result=$("$FORTSH_BIN" -c 'set -x; echo test 2>&1' | grep -c test)
997
+result=$("$SHELL_BIN" -c 'set -x; echo test 2>&1' | grep -c test)
998998
 if [ "$result" -ge 1 ]; then
999999
     pass "set -x traces commands"
10001000
 else
@@ -1002,7 +1002,7 @@ else
10021002
 fi
10031003
 
10041004
 # set -f (noglob)
1005
-result=$("$FORTSH_BIN" -c 'set -f; echo *' 2>&1)
1005
+result=$("$SHELL_BIN" -c 'set -f; echo *' 2>&1)
10061006
 if [ "$result" = "*" ]; then
10071007
     pass "set -f disables glob"
10081008
 else
@@ -1010,7 +1010,7 @@ else
10101010
 fi
10111011
 
10121012
 # set +f (enable glob)
1013
-result=$("$FORTSH_BIN" -c 'set -f; set +f; ls /*.txt 2>/dev/null | wc -l || echo 0' 2>&1)
1013
+result=$("$SHELL_BIN" -c 'set -f; set +f; ls /*.txt 2>/dev/null | wc -l || echo 0' 2>&1)
10141014
 if echo "$result" | grep -qE '^[[:space:]]*[0-9]+[[:space:]]*$'; then
10151015
     pass "set +f enables glob"
10161016
 else
@@ -1022,7 +1022,7 @@ section "413. UNSET BUILTIN"
10221022
 # =====================================
10231023
 
10241024
 # unset variable
1025
-result=$("$FORTSH_BIN" -c 'x=value; unset x; echo ${x:-empty}' 2>&1)
1025
+result=$("$SHELL_BIN" -c 'x=value; unset x; echo ${x:-empty}' 2>&1)
10261026
 if [ "$result" = "empty" ]; then
10271027
     pass "unset removes variable"
10281028
 else
@@ -1030,7 +1030,7 @@ else
10301030
 fi
10311031
 
10321032
 # unset function
1033
-result=$("$FORTSH_BIN" -c 'f() { echo hi; }; unset -f f; f 2>/dev/null || echo gone' 2>&1)
1033
+result=$("$SHELL_BIN" -c 'f() { echo hi; }; unset -f f; f 2>/dev/null || echo gone' 2>&1)
10341034
 if [ "$result" = "gone" ]; then
10351035
     pass "unset -f removes function"
10361036
 else
@@ -1038,7 +1038,7 @@ else
10381038
 fi
10391039
 
10401040
 # unset readonly fails
1041
-result=$("$FORTSH_BIN" -c 'readonly x=1; unset x 2>/dev/null; echo $?' 2>&1)
1041
+result=$("$SHELL_BIN" -c 'readonly x=1; unset x 2>/dev/null; echo $?' 2>&1)
10421042
 if [ "$result" != "0" ]; then
10431043
     pass "unset readonly fails"
10441044
 else
@@ -1050,7 +1050,7 @@ section "414. SHIFT BUILTIN"
10501050
 # =====================================
10511051
 
10521052
 # basic shift
1053
-result=$("$FORTSH_BIN" -c 'set -- a b c; shift; echo $1' 2>&1)
1053
+result=$("$SHELL_BIN" -c 'set -- a b c; shift; echo $1' 2>&1)
10541054
 if [ "$result" = "b" ]; then
10551055
     pass "shift removes first arg"
10561056
 else
@@ -1058,7 +1058,7 @@ else
10581058
 fi
10591059
 
10601060
 # shift with count
1061
-result=$("$FORTSH_BIN" -c 'set -- a b c d e; shift 3; echo $1' 2>&1)
1061
+result=$("$SHELL_BIN" -c 'set -- a b c d e; shift 3; echo $1' 2>&1)
10621062
 if [ "$result" = "d" ]; then
10631063
     pass "shift with count"
10641064
 else
@@ -1066,7 +1066,7 @@ else
10661066
 fi
10671067
 
10681068
 # shift updates $#
1069
-result=$("$FORTSH_BIN" -c 'set -- a b c; shift; echo $#' 2>&1)
1069
+result=$("$SHELL_BIN" -c 'set -- a b c; shift; echo $#' 2>&1)
10701070
 if [ "$result" = "2" ]; then
10711071
     pass "shift updates arg count"
10721072
 else
@@ -1078,7 +1078,7 @@ section "415. TRUE AND FALSE BUILTINS"
10781078
 # =====================================
10791079
 
10801080
 # true returns 0
1081
-result=$("$FORTSH_BIN" -c 'true; echo $?' 2>&1)
1081
+result=$("$SHELL_BIN" -c 'true; echo $?' 2>&1)
10821082
 if [ "$result" = "0" ]; then
10831083
     pass "true returns 0"
10841084
 else
@@ -1086,7 +1086,7 @@ else
10861086
 fi
10871087
 
10881088
 # false returns 1
1089
-result=$("$FORTSH_BIN" -c 'false; echo $?' 2>&1)
1089
+result=$("$SHELL_BIN" -c 'false; echo $?' 2>&1)
10901090
 if [ "$result" = "1" ]; then
10911091
     pass "false returns 1"
10921092
 else
@@ -1094,7 +1094,7 @@ else
10941094
 fi
10951095
 
10961096
 # true in conditional
1097
-result=$("$FORTSH_BIN" -c 'if true; then echo yes; fi' 2>&1)
1097
+result=$("$SHELL_BIN" -c 'if true; then echo yes; fi' 2>&1)
10981098
 if [ "$result" = "yes" ]; then
10991099
     pass "true in if condition"
11001100
 else
@@ -1102,7 +1102,7 @@ else
11021102
 fi
11031103
 
11041104
 # false in conditional
1105
-result=$("$FORTSH_BIN" -c 'if false; then echo no; else echo yes; fi' 2>&1)
1105
+result=$("$SHELL_BIN" -c 'if false; then echo no; else echo yes; fi' 2>&1)
11061106
 if [ "$result" = "yes" ]; then
11071107
     pass "false in if condition"
11081108
 else
@@ -1114,7 +1114,7 @@ section "416. COLON BUILTIN"
11141114
 # =====================================
11151115
 
11161116
 # colon returns 0
1117
-result=$("$FORTSH_BIN" -c ':; echo $?' 2>&1)
1117
+result=$("$SHELL_BIN" -c ':; echo $?' 2>&1)
11181118
 if [ "$result" = "0" ]; then
11191119
     pass "colon returns 0"
11201120
 else
@@ -1122,7 +1122,7 @@ else
11221122
 fi
11231123
 
11241124
 # colon with args (ignored)
1125
-result=$("$FORTSH_BIN" -c ': arg1 arg2 arg3; echo $?' 2>&1)
1125
+result=$("$SHELL_BIN" -c ': arg1 arg2 arg3; echo $?' 2>&1)
11261126
 if [ "$result" = "0" ]; then
11271127
     pass "colon ignores args"
11281128
 else
@@ -1130,7 +1130,7 @@ else
11301130
 fi
11311131
 
11321132
 # colon in loop condition
1133
-result=$("$FORTSH_BIN" -c 'i=0; while :; do i=$((i+1)); [ $i -ge 3 ] && break; done; echo $i' 2>&1)
1133
+result=$("$SHELL_BIN" -c 'i=0; while :; do i=$((i+1)); [ $i -ge 3 ] && break; done; echo $i' 2>&1)
11341134
 if [ "$result" = "3" ]; then
11351135
     pass "colon as infinite loop condition"
11361136
 else
@@ -1142,7 +1142,7 @@ section "417. PWD BUILTIN"
11421142
 # =====================================
11431143
 
11441144
 # pwd returns current dir
1145
-result=$("$FORTSH_BIN" -c 'pwd | grep -c "^/"' 2>&1)
1145
+result=$("$SHELL_BIN" -c 'pwd | grep -c "^/"' 2>&1)
11461146
 if [ "$result" = "1" ]; then
11471147
     pass "pwd returns absolute path"
11481148
 else
@@ -1150,7 +1150,7 @@ else
11501150
 fi
11511151
 
11521152
 # pwd after cd
1153
-result=$("$FORTSH_BIN" -c 'cd /tmp && pwd' 2>&1)
1153
+result=$("$SHELL_BIN" -c 'cd /tmp && pwd' 2>&1)
11541154
 if [ "$result" = "/tmp" ]; then
11551155
     pass "pwd after cd"
11561156
 else
@@ -1162,7 +1162,7 @@ section "418. CD BUILTIN"
11621162
 # =====================================
11631163
 
11641164
 # cd to absolute path
1165
-result=$("$FORTSH_BIN" -c 'cd /tmp && pwd' 2>&1)
1165
+result=$("$SHELL_BIN" -c 'cd /tmp && pwd' 2>&1)
11661166
 if [ "$result" = "/tmp" ]; then
11671167
     pass "cd to absolute path"
11681168
 else
@@ -1170,7 +1170,7 @@ else
11701170
 fi
11711171
 
11721172
 # cd - returns to OLDPWD
1173
-result=$("$FORTSH_BIN" -c 'cd /tmp; cd /; cd - 2>&1' 2>&1)
1173
+result=$("$SHELL_BIN" -c 'cd /tmp; cd /; cd - 2>&1' 2>&1)
11741174
 if echo "$result" | grep -q "tmp"; then
11751175
     pass "cd - returns to OLDPWD"
11761176
 else
@@ -1178,7 +1178,7 @@ else
11781178
 fi
11791179
 
11801180
 # cd nonexistent fails
1181
-result=$("$FORTSH_BIN" -c 'cd /nonexistent_dir_xyz 2>/dev/null; echo $?' 2>&1)
1181
+result=$("$SHELL_BIN" -c 'cd /nonexistent_dir_xyz 2>/dev/null; echo $?' 2>&1)
11821182
 if [ "$result" != "0" ]; then
11831183
     pass "cd nonexistent fails"
11841184
 else
@@ -1190,7 +1190,7 @@ section "419. TIMES BUILTIN"
11901190
 # =====================================
11911191
 
11921192
 # times outputs something
1193
-result=$("$FORTSH_BIN" -c 'times 2>&1 | head -1 || echo skipped')
1193
+result=$("$SHELL_BIN" -c 'times 2>&1 | head -1 || echo skipped')
11941194
 if [ -n "$result" ]; then
11951195
     pass "times outputs timing info"
11961196
 else
@@ -1202,7 +1202,7 @@ section "420. EXIT BUILTIN"
12021202
 # =====================================
12031203
 
12041204
 # exit with code
1205
-result=$("$FORTSH_BIN" -c 'exit 42' 2>&1; echo $?)
1205
+result=$("$SHELL_BIN" -c 'exit 42' 2>&1; echo $?)
12061206
 if [ "$result" = "42" ]; then
12071207
     pass "exit with code"
12081208
 else
@@ -1210,7 +1210,7 @@ else
12101210
 fi
12111211
 
12121212
 # exit default 0
1213
-result=$("$FORTSH_BIN" -c 'exit' 2>&1; echo $?)
1213
+result=$("$SHELL_BIN" -c 'exit' 2>&1; echo $?)
12141214
 if [ "$result" = "0" ]; then
12151215
     pass "exit default 0"
12161216
 else
@@ -1218,7 +1218,7 @@ else
12181218
 fi
12191219
 
12201220
 # exit from subshell
1221
-result=$("$FORTSH_BIN" -c '(exit 7); echo $?' 2>&1)
1221
+result=$("$SHELL_BIN" -c '(exit 7); echo $?' 2>&1)
12221222
 if [ "$result" = "7" ]; then
12231223
     pass "exit from subshell"
12241224
 else
suites/posix/posix_compliance_printf.shmodified
@@ -24,12 +24,12 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 
2929
 # Check if fortsh exists
30
-if [ ! -x "$FORTSH_BIN" ]; then
31
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
+if [ ! -x "$SHELL_BIN" ]; then
31
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
32
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3333
     exit 1
3434
 fi
3535
 
@@ -73,42 +73,42 @@ section() {
7373
 section "358. PRINTF BASIC STRING FORMAT %s"
7474
 # =====================================
7575
 
76
-result=$("$FORTSH_BIN" -c 'printf "%s\n" "hello"' 2>&1)
76
+result=$("$SHELL_BIN" -c 'printf "%s\n" "hello"' 2>&1)
7777
 if [ "$result" = "hello" ]; then
7878
     pass "printf %s basic string"
7979
 else
8080
     fail "printf %s basic string" "hello" "$result"
8181
 fi
8282
 
83
-result=$("$FORTSH_BIN" -c 'printf "%s %s\n" "hello" "world"' 2>&1)
83
+result=$("$SHELL_BIN" -c 'printf "%s %s\n" "hello" "world"' 2>&1)
8484
 if [ "$result" = "hello world" ]; then
8585
     pass "printf %s multiple arguments"
8686
 else
8787
     fail "printf %s multiple arguments" "hello world" "$result"
8888
 fi
8989
 
90
-result=$("$FORTSH_BIN" -c 'printf "%s" ""' 2>&1)
90
+result=$("$SHELL_BIN" -c 'printf "%s" ""' 2>&1)
9191
 if [ "$result" = "" ]; then
9292
     pass "printf %s empty string"
9393
 else
9494
     fail "printf %s empty string" "(empty)" "$result"
9595
 fi
9696
 
97
-result=$("$FORTSH_BIN" -c 'printf "%.3s\n" "hello"' 2>&1)
97
+result=$("$SHELL_BIN" -c 'printf "%.3s\n" "hello"' 2>&1)
9898
 if [ "$result" = "hel" ]; then
9999
     pass "printf %.3s precision truncates"
100100
 else
101101
     fail "printf %.3s precision truncates" "hel" "$result"
102102
 fi
103103
 
104
-result=$("$FORTSH_BIN" -c 'printf "%10s\n" "hi"' 2>&1)
104
+result=$("$SHELL_BIN" -c 'printf "%10s\n" "hi"' 2>&1)
105105
 if [ "$result" = "        hi" ]; then
106106
     pass "printf %10s width right-align"
107107
 else
108108
     fail "printf %10s width right-align" "        hi" "$result"
109109
 fi
110110
 
111
-result=$("$FORTSH_BIN" -c 'printf "%-10s|\n" "hi"' 2>&1)
111
+result=$("$SHELL_BIN" -c 'printf "%-10s|\n" "hi"' 2>&1)
112112
 if [ "$result" = "hi        |" ]; then
113113
     pass "printf %-10s width left-align"
114114
 else
@@ -119,49 +119,49 @@ fi
119119
 section "359. PRINTF INTEGER FORMATS %d %i"
120120
 # =====================================
121121
 
122
-result=$("$FORTSH_BIN" -c 'printf "%d\n" 42' 2>&1)
122
+result=$("$SHELL_BIN" -c 'printf "%d\n" 42' 2>&1)
123123
 if [ "$result" = "42" ]; then
124124
     pass "printf %d basic decimal"
125125
 else
126126
     fail "printf %d basic decimal" "42" "$result"
127127
 fi
128128
 
129
-result=$("$FORTSH_BIN" -c 'printf "%i\n" 42' 2>&1)
129
+result=$("$SHELL_BIN" -c 'printf "%i\n" 42' 2>&1)
130130
 if [ "$result" = "42" ]; then
131131
     pass "printf %i basic integer"
132132
 else
133133
     fail "printf %i basic integer" "42" "$result"
134134
 fi
135135
 
136
-result=$("$FORTSH_BIN" -c 'printf "%d\n" -42' 2>&1)
136
+result=$("$SHELL_BIN" -c 'printf "%d\n" -42' 2>&1)
137137
 if [ "$result" = "-42" ]; then
138138
     pass "printf %d negative number"
139139
 else
140140
     fail "printf %d negative number" "-42" "$result"
141141
 fi
142142
 
143
-result=$("$FORTSH_BIN" -c 'printf "%5d\n" 42' 2>&1)
143
+result=$("$SHELL_BIN" -c 'printf "%5d\n" 42' 2>&1)
144144
 if [ "$result" = "   42" ]; then
145145
     pass "printf %5d width padding"
146146
 else
147147
     fail "printf %5d width padding" "   42" "$result"
148148
 fi
149149
 
150
-result=$("$FORTSH_BIN" -c 'printf "%05d\n" 42' 2>&1)
150
+result=$("$SHELL_BIN" -c 'printf "%05d\n" 42' 2>&1)
151151
 if [ "$result" = "00042" ]; then
152152
     pass "printf %05d zero padding"
153153
 else
154154
     fail "printf %05d zero padding" "00042" "$result"
155155
 fi
156156
 
157
-result=$("$FORTSH_BIN" -c 'printf "%-5d|\n" 42' 2>&1)
157
+result=$("$SHELL_BIN" -c 'printf "%-5d|\n" 42' 2>&1)
158158
 if [ "$result" = "42   |" ]; then
159159
     pass "printf %-5d left-align"
160160
 else
161161
     fail "printf %-5d left-align" "42   |" "$result"
162162
 fi
163163
 
164
-result=$("$FORTSH_BIN" -c 'printf "%+d\n" 42' 2>&1)
164
+result=$("$SHELL_BIN" -c 'printf "%+d\n" 42' 2>&1)
165165
 if [ "$result" = "+42" ]; then
166166
     pass "printf %+d explicit plus sign"
167167
 else
@@ -172,35 +172,35 @@ fi
172172
 section "360. PRINTF OCTAL AND HEX FORMATS %o %x %X"
173173
 # =====================================
174174
 
175
-result=$("$FORTSH_BIN" -c 'printf "%o\n" 8' 2>&1)
175
+result=$("$SHELL_BIN" -c 'printf "%o\n" 8' 2>&1)
176176
 if [ "$result" = "10" ]; then
177177
     pass "printf %o octal format"
178178
 else
179179
     fail "printf %o octal format" "10" "$result"
180180
 fi
181181
 
182
-result=$("$FORTSH_BIN" -c 'printf "%x\n" 255' 2>&1)
182
+result=$("$SHELL_BIN" -c 'printf "%x\n" 255' 2>&1)
183183
 if [ "$result" = "ff" ]; then
184184
     pass "printf %x lowercase hex"
185185
 else
186186
     fail "printf %x lowercase hex" "ff" "$result"
187187
 fi
188188
 
189
-result=$("$FORTSH_BIN" -c 'printf "%X\n" 255' 2>&1)
189
+result=$("$SHELL_BIN" -c 'printf "%X\n" 255' 2>&1)
190190
 if [ "$result" = "FF" ]; then
191191
     pass "printf %X uppercase hex"
192192
 else
193193
     fail "printf %X uppercase hex" "FF" "$result"
194194
 fi
195195
 
196
-result=$("$FORTSH_BIN" -c 'printf "%#x\n" 255' 2>&1)
196
+result=$("$SHELL_BIN" -c 'printf "%#x\n" 255' 2>&1)
197197
 if [ "$result" = "0xff" ]; then
198198
     pass "printf %#x alternate form"
199199
 else
200200
     fail "printf %#x alternate form" "0xff" "$result"
201201
 fi
202202
 
203
-result=$("$FORTSH_BIN" -c 'printf "%#o\n" 8' 2>&1)
203
+result=$("$SHELL_BIN" -c 'printf "%#o\n" 8' 2>&1)
204204
 if [ "$result" = "010" ]; then
205205
     pass "printf %#o alternate octal form"
206206
 else
@@ -211,21 +211,21 @@ fi
211211
 section "361. PRINTF CHARACTER FORMAT %c"
212212
 # =====================================
213213
 
214
-result=$("$FORTSH_BIN" -c 'printf "%c\n" A' 2>&1)
214
+result=$("$SHELL_BIN" -c 'printf "%c\n" A' 2>&1)
215215
 if [ "$result" = "A" ]; then
216216
     pass "printf %c single character"
217217
 else
218218
     fail "printf %c single character" "A" "$result"
219219
 fi
220220
 
221
-result=$("$FORTSH_BIN" -c 'printf "%c\n" "hello"' 2>&1)
221
+result=$("$SHELL_BIN" -c 'printf "%c\n" "hello"' 2>&1)
222222
 if [ "$result" = "h" ]; then
223223
     pass "printf %c first char of string"
224224
 else
225225
     fail "printf %c first char of string" "h" "$result"
226226
 fi
227227
 
228
-result=$("$FORTSH_BIN" -c 'printf "%c%c%c\n" a b c' 2>&1)
228
+result=$("$SHELL_BIN" -c 'printf "%c%c%c\n" a b c' 2>&1)
229229
 if [ "$result" = "abc" ]; then
230230
     pass "printf %c multiple chars"
231231
 else
@@ -236,7 +236,7 @@ fi
236236
 section "362. PRINTF ESCAPE SEQUENCES"
237237
 # =====================================
238238
 
239
-result=$("$FORTSH_BIN" -c 'printf "hello\nworld\n"' 2>&1)
239
+result=$("$SHELL_BIN" -c 'printf "hello\nworld\n"' 2>&1)
240240
 expected=$(printf "hello\nworld")
241241
 if [ "$result" = "$expected" ]; then
242242
     pass "printf \\n newline"
@@ -244,7 +244,7 @@ else
244244
     fail "printf \\n newline" "$expected" "$result"
245245
 fi
246246
 
247
-result=$("$FORTSH_BIN" -c 'printf "a\tb\n"' 2>&1)
247
+result=$("$SHELL_BIN" -c 'printf "a\tb\n"' 2>&1)
248248
 expected=$(printf "a\tb")
249249
 if [ "$result" = "$expected" ]; then
250250
     pass "printf \\t tab"
@@ -252,21 +252,21 @@ else
252252
     fail "printf \\t tab" "$expected" "$result"
253253
 fi
254254
 
255
-result=$("$FORTSH_BIN" -c 'printf "back\\\\slash\n"' 2>&1)
255
+result=$("$SHELL_BIN" -c 'printf "back\\\\slash\n"' 2>&1)
256256
 if [ "$result" = 'back\slash' ]; then
257257
     pass "printf \\\\ literal backslash"
258258
 else
259259
     fail "printf \\\\ literal backslash" 'back\slash' "$result"
260260
 fi
261261
 
262
-result=$("$FORTSH_BIN" -c 'printf "100%%\n"' 2>&1)
262
+result=$("$SHELL_BIN" -c 'printf "100%%\n"' 2>&1)
263263
 if [ "$result" = "100%" ]; then
264264
     pass "printf %% literal percent"
265265
 else
266266
     fail "printf %% literal percent" "100%" "$result"
267267
 fi
268268
 
269
-result=$("$FORTSH_BIN" -c 'printf "\101\n"' 2>&1)
269
+result=$("$SHELL_BIN" -c 'printf "\101\n"' 2>&1)
270270
 if [ "$result" = "A" ]; then
271271
     pass "printf \\NNN octal escape"
272272
 else
@@ -277,7 +277,7 @@ fi
277277
 section "363. PRINTF %b ESCAPE INTERPRETATION"
278278
 # =====================================
279279
 
280
-result=$("$FORTSH_BIN" -c 'printf "%b\n" "hello\nworld"' 2>&1)
280
+result=$("$SHELL_BIN" -c 'printf "%b\n" "hello\nworld"' 2>&1)
281281
 expected=$(printf "hello\nworld")
282282
 if [ "$result" = "$expected" ]; then
283283
     pass "printf %b interprets backslash escapes"
@@ -285,7 +285,7 @@ else
285285
     fail "printf %b interprets backslash escapes" "(newline)" "$result"
286286
 fi
287287
 
288
-result=$("$FORTSH_BIN" -c 'printf "%b\n" "tab\there"' 2>&1)
288
+result=$("$SHELL_BIN" -c 'printf "%b\n" "tab\there"' 2>&1)
289289
 expected=$(printf "tab\there")
290290
 if [ "$result" = "$expected" ]; then
291291
     pass "printf %b interprets \\t"
@@ -297,7 +297,7 @@ fi
297297
 section "364. PRINTF FORMAT REUSE"
298298
 # =====================================
299299
 
300
-result=$("$FORTSH_BIN" -c 'printf "%s\n" one two three' 2>&1)
300
+result=$("$SHELL_BIN" -c 'printf "%s\n" one two three' 2>&1)
301301
 expected=$(printf "one\ntwo\nthree")
302302
 if [ "$result" = "$expected" ]; then
303303
     pass "printf format reused for extra args"
@@ -305,7 +305,7 @@ else
305305
     fail "printf format reused for extra args" "$expected" "$result"
306306
 fi
307307
 
308
-result=$("$FORTSH_BIN" -c 'printf "%d " 1 2 3 4 5; printf "\n"' 2>&1)
308
+result=$("$SHELL_BIN" -c 'printf "%d " 1 2 3 4 5; printf "\n"' 2>&1)
309309
 if [ "$result" = "1 2 3 4 5 " ]; then
310310
     pass "printf %d reused for multiple integers"
311311
 else
@@ -316,21 +316,21 @@ fi
316316
 section "365. PRINTF WITH VARIABLES"
317317
 # =====================================
318318
 
319
-result=$("$FORTSH_BIN" -c 'x="hello"; printf "%s\n" "$x"' 2>&1)
319
+result=$("$SHELL_BIN" -c 'x="hello"; printf "%s\n" "$x"' 2>&1)
320320
 if [ "$result" = "hello" ]; then
321321
     pass "printf with variable argument"
322322
 else
323323
     fail "printf with variable argument" "hello" "$result"
324324
 fi
325325
 
326
-result=$("$FORTSH_BIN" -c 'n=42; printf "Value: %d\n" "$n"' 2>&1)
326
+result=$("$SHELL_BIN" -c 'n=42; printf "Value: %d\n" "$n"' 2>&1)
327327
 if [ "$result" = "Value: 42" ]; then
328328
     pass "printf integer from variable"
329329
 else
330330
     fail "printf integer from variable" "Value: 42" "$result"
331331
 fi
332332
 
333
-result=$("$FORTSH_BIN" -c 'fmt="%s: %d\n"; printf "$fmt" name 42' 2>&1)
333
+result=$("$SHELL_BIN" -c 'fmt="%s: %d\n"; printf "$fmt" name 42' 2>&1)
334334
 if [ "$result" = "name: 42" ]; then
335335
     pass "printf format from variable"
336336
 else
@@ -341,21 +341,21 @@ fi
341341
 section "366. PRINTF DYNAMIC WIDTH AND PRECISION"
342342
 # =====================================
343343
 
344
-result=$("$FORTSH_BIN" -c 'printf "%*s\n" 10 hi' 2>&1)
344
+result=$("$SHELL_BIN" -c 'printf "%*s\n" 10 hi' 2>&1)
345345
 if [ "$result" = "        hi" ]; then
346346
     pass "printf %*s dynamic width"
347347
 else
348348
     fail "printf %*s dynamic width" "        hi" "$result"
349349
 fi
350350
 
351
-result=$("$FORTSH_BIN" -c 'printf "%.*s\n" 3 hello' 2>&1)
351
+result=$("$SHELL_BIN" -c 'printf "%.*s\n" 3 hello' 2>&1)
352352
 if [ "$result" = "hel" ]; then
353353
     pass "printf %.*s dynamic precision"
354354
 else
355355
     fail "printf %.*s dynamic precision" "hel" "$result"
356356
 fi
357357
 
358
-result=$("$FORTSH_BIN" -c 'printf "%*.*s\n" 10 3 hello' 2>&1)
358
+result=$("$SHELL_BIN" -c 'printf "%*.*s\n" 10 3 hello' 2>&1)
359359
 if [ "$result" = "       hel" ]; then
360360
     pass "printf %*.*s dynamic width and precision"
361361
 else
@@ -366,7 +366,7 @@ fi
366366
 section "367. PRINTF RETURN VALUE"
367367
 # =====================================
368368
 
369
-result=$("$FORTSH_BIN" -c 'printf "%s" "test"; echo $?' 2>&1)
369
+result=$("$SHELL_BIN" -c 'printf "%s" "test"; echo $?' 2>&1)
370370
 if echo "$result" | grep -q "0"; then
371371
     pass "printf returns 0 on success"
372372
 else
@@ -377,28 +377,28 @@ fi
377377
 section "368. PRINTF EDGE CASES"
378378
 # =====================================
379379
 
380
-result=$("$FORTSH_BIN" -c 'printf "%d\n" 0' 2>&1)
380
+result=$("$SHELL_BIN" -c 'printf "%d\n" 0' 2>&1)
381381
 if [ "$result" = "0" ]; then
382382
     pass "printf %d zero"
383383
 else
384384
     fail "printf %d zero" "0" "$result"
385385
 fi
386386
 
387
-result=$("$FORTSH_BIN" -c 'printf "%s\n" ""' 2>&1)
387
+result=$("$SHELL_BIN" -c 'printf "%s\n" ""' 2>&1)
388388
 if [ "$result" = "" ]; then
389389
     pass "printf empty argument"
390390
 else
391391
     fail "printf empty argument" "(empty)" "$result"
392392
 fi
393393
 
394
-result=$("$FORTSH_BIN" -c 'printf "no format"' 2>&1)
394
+result=$("$SHELL_BIN" -c 'printf "no format"' 2>&1)
395395
 if [ "$result" = "no format" ]; then
396396
     pass "printf literal string no format"
397397
 else
398398
     fail "printf literal string no format" "no format" "$result"
399399
 fi
400400
 
401
-result=$("$FORTSH_BIN" -c 'printf ""' 2>&1)
401
+result=$("$SHELL_BIN" -c 'printf ""' 2>&1)
402402
 if [ "$result" = "" ]; then
403403
     pass "printf empty format string"
404404
 else
suites/posix/posix_compliance_quoting.shmodified
@@ -24,12 +24,12 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 
2929
 # Check if fortsh exists
30
-if [ ! -x "$FORTSH_BIN" ]; then
31
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
+if [ ! -x "$SHELL_BIN" ]; then
31
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
32
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3333
     exit 1
3434
 fi
3535
 
@@ -73,35 +73,35 @@ section() {
7373
 section "446. SINGLE QUOTES"
7474
 # =====================================
7575
 
76
-result=$("$FORTSH_BIN" -c "echo 'hello world'" 2>&1)
76
+result=$("$SHELL_BIN" -c "echo 'hello world'" 2>&1)
7777
 if [ "$result" = "hello world" ]; then
7878
     pass "Single quotes preserve spaces"
7979
 else
8080
     fail "Single quotes preserve spaces" "hello world" "$result"
8181
 fi
8282
 
83
-result=$("$FORTSH_BIN" -c "x=test; echo '\$x'" 2>&1)
83
+result=$("$SHELL_BIN" -c "x=test; echo '\$x'" 2>&1)
8484
 if [ "$result" = '$x' ]; then
8585
     pass "Single quotes prevent variable expansion"
8686
 else
8787
     fail "Single quotes prevent variable expansion" '$x' "$result"
8888
 fi
8989
 
90
-result=$("$FORTSH_BIN" -c "echo 'back\\slash'" 2>&1)
90
+result=$("$SHELL_BIN" -c "echo 'back\\slash'" 2>&1)
9191
 if [ "$result" = 'back\slash' ]; then
9292
     pass "Single quotes preserve backslash"
9393
 else
9494
     fail "Single quotes preserve backslash" 'back\slash' "$result"
9595
 fi
9696
 
97
-result=$("$FORTSH_BIN" -c "echo 'has \"double\" quotes'" 2>&1)
97
+result=$("$SHELL_BIN" -c "echo 'has \"double\" quotes'" 2>&1)
9898
 if [ "$result" = 'has "double" quotes' ]; then
9999
     pass "Single quotes preserve double quotes"
100100
 else
101101
     fail "Single quotes preserve double quotes" 'has "double" quotes' "$result"
102102
 fi
103103
 
104
-result=$("$FORTSH_BIN" -c "echo '\$(echo no)'" 2>&1)
104
+result=$("$SHELL_BIN" -c "echo '\$(echo no)'" 2>&1)
105105
 if [ "$result" = '$(echo no)' ]; then
106106
     pass "Single quotes prevent command substitution"
107107
 else
@@ -112,49 +112,49 @@ fi
112112
 section "447. DOUBLE QUOTES"
113113
 # =====================================
114114
 
115
-result=$("$FORTSH_BIN" -c 'echo "hello world"' 2>&1)
115
+result=$("$SHELL_BIN" -c 'echo "hello world"' 2>&1)
116116
 if [ "$result" = "hello world" ]; then
117117
     pass "Double quotes preserve spaces"
118118
 else
119119
     fail "Double quotes preserve spaces" "hello world" "$result"
120120
 fi
121121
 
122
-result=$("$FORTSH_BIN" -c 'x=test; echo "$x"' 2>&1)
122
+result=$("$SHELL_BIN" -c 'x=test; echo "$x"' 2>&1)
123123
 if [ "$result" = "test" ]; then
124124
     pass "Double quotes allow variable expansion"
125125
 else
126126
     fail "Double quotes allow variable expansion" "test" "$result"
127127
 fi
128128
 
129
-result=$("$FORTSH_BIN" -c 'echo "$(echo hello)"' 2>&1)
129
+result=$("$SHELL_BIN" -c 'echo "$(echo hello)"' 2>&1)
130130
 if [ "$result" = "hello" ]; then
131131
     pass "Double quotes allow command substitution"
132132
 else
133133
     fail "Double quotes allow command substitution" "hello" "$result"
134134
 fi
135135
 
136
-result=$("$FORTSH_BIN" -c 'echo "has '\''single'\'' quotes"' 2>&1)
136
+result=$("$SHELL_BIN" -c 'echo "has '\''single'\'' quotes"' 2>&1)
137137
 if [ "$result" = "has 'single' quotes" ]; then
138138
     pass "Double quotes preserve single quotes"
139139
 else
140140
     fail "Double quotes preserve single quotes" "has 'single' quotes" "$result"
141141
 fi
142142
 
143
-result=$("$FORTSH_BIN" -c 'echo "escaped \"quote\""' 2>&1)
143
+result=$("$SHELL_BIN" -c 'echo "escaped \"quote\""' 2>&1)
144144
 if [ "$result" = 'escaped "quote"' ]; then
145145
     pass "Double quotes with escaped quotes"
146146
 else
147147
     fail "Double quotes with escaped quotes" 'escaped "quote"' "$result"
148148
 fi
149149
 
150
-result=$("$FORTSH_BIN" -c 'echo "back\\slash"' 2>&1)
150
+result=$("$SHELL_BIN" -c 'echo "back\\slash"' 2>&1)
151151
 if [ "$result" = 'back\slash' ]; then
152152
     pass "Double quotes with escaped backslash"
153153
 else
154154
     fail "Double quotes with escaped backslash" 'back\slash' "$result"
155155
 fi
156156
 
157
-result=$("$FORTSH_BIN" -c 'echo "dollar\$sign"' 2>&1)
157
+result=$("$SHELL_BIN" -c 'echo "dollar\$sign"' 2>&1)
158158
 if [ "$result" = 'dollar$sign' ]; then
159159
     pass "Double quotes with escaped dollar"
160160
 else
@@ -165,28 +165,28 @@ fi
165165
 section "448. BACKSLASH ESCAPING"
166166
 # =====================================
167167
 
168
-result=$("$FORTSH_BIN" -c 'echo hello\ world' 2>&1)
168
+result=$("$SHELL_BIN" -c 'echo hello\ world' 2>&1)
169169
 if [ "$result" = "hello world" ]; then
170170
     pass "Backslash escapes space"
171171
 else
172172
     fail "Backslash escapes space" "hello world" "$result"
173173
 fi
174174
 
175
-result=$("$FORTSH_BIN" -c 'x=test; echo \$x' 2>&1)
175
+result=$("$SHELL_BIN" -c 'x=test; echo \$x' 2>&1)
176176
 if [ "$result" = '$x' ]; then
177177
     pass "Backslash escapes dollar sign"
178178
 else
179179
     fail "Backslash escapes dollar sign" '$x' "$result"
180180
 fi
181181
 
182
-result=$("$FORTSH_BIN" -c 'echo back\\slash' 2>&1)
182
+result=$("$SHELL_BIN" -c 'echo back\\slash' 2>&1)
183183
 if [ "$result" = 'back\slash' ]; then
184184
     pass "Backslash escapes backslash"
185185
 else
186186
     fail "Backslash escapes backslash" 'back\slash' "$result"
187187
 fi
188188
 
189
-result=$("$FORTSH_BIN" -c 'echo hello\
189
+result=$("$SHELL_BIN" -c 'echo hello\
190190
 world' 2>&1)
191191
 if [ "$result" = "helloworld" ]; then
192192
     pass "Backslash-newline line continuation"
@@ -198,7 +198,7 @@ fi
198198
 section "449. MIXED QUOTING"
199199
 # =====================================
200200
 
201
-result=$("$FORTSH_BIN" -c 'echo "hello"'\''world'\''' 2>&1)
201
+result=$("$SHELL_BIN" -c 'echo "hello"'\''world'\''' 2>&1)
202202
 # Adjacent quoted strings concatenate: "hello" + 'world' = helloworld
203203
 if [ "$result" = "helloworld" ]; then
204204
     pass "Adjacent double and single quotes"
@@ -206,14 +206,14 @@ else
206206
     fail "Adjacent double and single quotes" "helloworld" "$result"
207207
 fi
208208
 
209
-result=$("$FORTSH_BIN" -c 'x=val; echo "$x"'\''$x'\''' 2>&1)
209
+result=$("$SHELL_BIN" -c 'x=val; echo "$x"'\''$x'\''' 2>&1)
210210
 if [ "$result" = 'val$x' ]; then
211211
     pass "Mixed expansion and literal"
212212
 else
213213
     fail "Mixed expansion and literal" 'val$x' "$result"
214214
 fi
215215
 
216
-result=$("$FORTSH_BIN" -c "echo 'don'\\''t'" 2>&1)
216
+result=$("$SHELL_BIN" -c "echo 'don'\\''t'" 2>&1)
217217
 if [ "$result" = "don't" ]; then
218218
     pass "Single quote in single quoted string"
219219
 else
@@ -224,49 +224,49 @@ fi
224224
 section "450. QUOTING SPECIAL CHARACTERS"
225225
 # =====================================
226226
 
227
-result=$("$FORTSH_BIN" -c 'echo "semi;colon"' 2>&1)
227
+result=$("$SHELL_BIN" -c 'echo "semi;colon"' 2>&1)
228228
 if [ "$result" = "semi;colon" ]; then
229229
     pass "Semicolon in double quotes"
230230
 else
231231
     fail "Semicolon in double quotes" "semi;colon" "$result"
232232
 fi
233233
 
234
-result=$("$FORTSH_BIN" -c "echo 'pipe|char'" 2>&1)
234
+result=$("$SHELL_BIN" -c "echo 'pipe|char'" 2>&1)
235235
 if [ "$result" = "pipe|char" ]; then
236236
     pass "Pipe in single quotes"
237237
 else
238238
     fail "Pipe in single quotes" "pipe|char" "$result"
239239
 fi
240240
 
241
-result=$("$FORTSH_BIN" -c 'echo "ampersand&here"' 2>&1)
241
+result=$("$SHELL_BIN" -c 'echo "ampersand&here"' 2>&1)
242242
 if [ "$result" = "ampersand&here" ]; then
243243
     pass "Ampersand in double quotes"
244244
 else
245245
     fail "Ampersand in double quotes" "ampersand&here" "$result"
246246
 fi
247247
 
248
-result=$("$FORTSH_BIN" -c "echo 'less<greater>'" 2>&1)
248
+result=$("$SHELL_BIN" -c "echo 'less<greater>'" 2>&1)
249249
 if [ "$result" = "less<greater>" ]; then
250250
     pass "Angle brackets in single quotes"
251251
 else
252252
     fail "Angle brackets in single quotes" "less<greater>" "$result"
253253
 fi
254254
 
255
-result=$("$FORTSH_BIN" -c 'echo "paren(here)"' 2>&1)
255
+result=$("$SHELL_BIN" -c 'echo "paren(here)"' 2>&1)
256256
 if [ "$result" = "paren(here)" ]; then
257257
     pass "Parentheses in double quotes"
258258
 else
259259
     fail "Parentheses in double quotes" "paren(here)" "$result"
260260
 fi
261261
 
262
-result=$("$FORTSH_BIN" -c "echo 'star*glob?'" 2>&1)
262
+result=$("$SHELL_BIN" -c "echo 'star*glob?'" 2>&1)
263263
 if [ "$result" = "star*glob?" ]; then
264264
     pass "Glob chars in single quotes"
265265
 else
266266
     fail "Glob chars in single quotes" "star*glob?" "$result"
267267
 fi
268268
 
269
-result=$("$FORTSH_BIN" -c 'echo "hash#comment"' 2>&1)
269
+result=$("$SHELL_BIN" -c 'echo "hash#comment"' 2>&1)
270270
 if [ "$result" = "hash#comment" ]; then
271271
     pass "Hash in double quotes"
272272
 else
@@ -277,28 +277,28 @@ fi
277277
 section "451. EMPTY STRINGS"
278278
 # =====================================
279279
 
280
-result=$("$FORTSH_BIN" -c 'echo ""' 2>&1)
280
+result=$("$SHELL_BIN" -c 'echo ""' 2>&1)
281281
 if [ "$result" = "" ]; then
282282
     pass "Empty double-quoted string"
283283
 else
284284
     fail "Empty double-quoted string" "(empty)" "$result"
285285
 fi
286286
 
287
-result=$("$FORTSH_BIN" -c "echo ''" 2>&1)
287
+result=$("$SHELL_BIN" -c "echo ''" 2>&1)
288288
 if [ "$result" = "" ]; then
289289
     pass "Empty single-quoted string"
290290
 else
291291
     fail "Empty single-quoted string" "(empty)" "$result"
292292
 fi
293293
 
294
-result=$("$FORTSH_BIN" -c 'x=""; echo "[$x]"' 2>&1)
294
+result=$("$SHELL_BIN" -c 'x=""; echo "[$x]"' 2>&1)
295295
 if [ "$result" = "[]" ]; then
296296
     pass "Empty variable in quotes"
297297
 else
298298
     fail "Empty variable in quotes" "[]" "$result"
299299
 fi
300300
 
301
-result=$("$FORTSH_BIN" -c 'echo a "" b' 2>&1)
301
+result=$("$SHELL_BIN" -c 'echo a "" b' 2>&1)
302302
 if [ "$result" = "a  b" ]; then
303303
     pass "Empty string preserves word"
304304
 else
@@ -309,7 +309,7 @@ fi
309309
 section "452. WORD SPLITTING"
310310
 # =====================================
311311
 
312
-result=$("$FORTSH_BIN" -c 'x="a b c"; for w in $x; do echo "[$w]"; done' 2>&1)
312
+result=$("$SHELL_BIN" -c 'x="a b c"; for w in $x; do echo "[$w]"; done' 2>&1)
313313
 expected=$(printf "[a]\n[b]\n[c]")
314314
 if [ "$result" = "$expected" ]; then
315315
     pass "Unquoted variable splits on whitespace"
@@ -317,21 +317,21 @@ else
317317
     fail "Unquoted variable splits on whitespace" "$expected" "$result"
318318
 fi
319319
 
320
-result=$("$FORTSH_BIN" -c 'x="a b c"; for w in "$x"; do echo "[$w]"; done' 2>&1)
320
+result=$("$SHELL_BIN" -c 'x="a b c"; for w in "$x"; do echo "[$w]"; done' 2>&1)
321321
 if [ "$result" = "[a b c]" ]; then
322322
     pass "Quoted variable prevents splitting"
323323
 else
324324
     fail "Quoted variable prevents splitting" "[a b c]" "$result"
325325
 fi
326326
 
327
-result=$("$FORTSH_BIN" -c 'x="a  b"; echo $x' 2>&1)
327
+result=$("$SHELL_BIN" -c 'x="a  b"; echo $x' 2>&1)
328328
 if [ "$result" = "a b" ]; then
329329
     pass "Word splitting collapses spaces"
330330
 else
331331
     fail "Word splitting collapses spaces" "a b" "$result"
332332
 fi
333333
 
334
-result=$("$FORTSH_BIN" -c 'x="a  b"; echo "$x"' 2>&1)
334
+result=$("$SHELL_BIN" -c 'x="a  b"; echo "$x"' 2>&1)
335335
 if [ "$result" = "a  b" ]; then
336336
     pass "Quoting preserves multiple spaces"
337337
 else
@@ -342,21 +342,21 @@ fi
342342
 section "453. GLOB PREVENTION"
343343
 # =====================================
344344
 
345
-result=$("$FORTSH_BIN" -c 'echo "*"' 2>&1)
345
+result=$("$SHELL_BIN" -c 'echo "*"' 2>&1)
346346
 if [ "$result" = "*" ]; then
347347
     pass "Double quotes prevent glob expansion"
348348
 else
349349
     fail "Double quotes prevent glob expansion" "*" "$result"
350350
 fi
351351
 
352
-result=$("$FORTSH_BIN" -c "echo '[a-z]*'" 2>&1)
352
+result=$("$SHELL_BIN" -c "echo '[a-z]*'" 2>&1)
353353
 if [ "$result" = "[a-z]*" ]; then
354354
     pass "Single quotes prevent bracket expansion"
355355
 else
356356
     fail "Single quotes prevent bracket expansion" "[a-z]*" "$result"
357357
 fi
358358
 
359
-result=$("$FORTSH_BIN" -c 'echo "?"' 2>&1)
359
+result=$("$SHELL_BIN" -c 'echo "?"' 2>&1)
360360
 if [ "$result" = "?" ]; then
361361
     pass "Double quotes prevent ? expansion"
362362
 else
@@ -367,14 +367,14 @@ fi
367367
 section "454. QUOTE IN VARIABLE"
368368
 # =====================================
369369
 
370
-result=$("$FORTSH_BIN" -c "x=\"has 'quotes'\"; echo \"\$x\"" 2>&1)
370
+result=$("$SHELL_BIN" -c "x=\"has 'quotes'\"; echo \"\$x\"" 2>&1)
371371
 if [ "$result" = "has 'quotes'" ]; then
372372
     pass "Single quotes inside double-quoted variable"
373373
 else
374374
     fail "Single quotes inside double-quoted variable" "has 'quotes'" "$result"
375375
 fi
376376
 
377
-result=$("$FORTSH_BIN" -c 'x="has \"quotes\""; echo "$x"' 2>&1)
377
+result=$("$SHELL_BIN" -c 'x="has \"quotes\""; echo "$x"' 2>&1)
378378
 if [ "$result" = 'has "quotes"' ]; then
379379
     pass "Double quotes inside variable"
380380
 else
@@ -385,21 +385,21 @@ fi
385385
 section "455. QUOTING IN ASSIGNMENTS"
386386
 # =====================================
387387
 
388
-result=$("$FORTSH_BIN" -c 'x="hello world"; echo $x' 2>&1)
388
+result=$("$SHELL_BIN" -c 'x="hello world"; echo $x' 2>&1)
389389
 if [ "$result" = "hello world" ]; then
390390
     pass "Quoted assignment with spaces"
391391
 else
392392
     fail "Quoted assignment with spaces" "hello world" "$result"
393393
 fi
394394
 
395
-result=$("$FORTSH_BIN" -c "x='no \$expansion'; echo \"\$x\"" 2>&1)
395
+result=$("$SHELL_BIN" -c "x='no \$expansion'; echo \"\$x\"" 2>&1)
396396
 if [ "$result" = 'no $expansion' ]; then
397397
     pass "Single-quoted assignment"
398398
 else
399399
     fail "Single-quoted assignment" 'no $expansion' "$result"
400400
 fi
401401
 
402
-result=$("$FORTSH_BIN" -c 'y=value; x="with $y"; echo "$x"' 2>&1)
402
+result=$("$SHELL_BIN" -c 'y=value; x="with $y"; echo "$x"' 2>&1)
403403
 if [ "$result" = "with value" ]; then
404404
     pass "Variable expansion in assignment"
405405
 else
@@ -410,14 +410,14 @@ fi
410410
 section "456. QUOTING IN COMMAND SUBSTITUTION"
411411
 # =====================================
412412
 
413
-result=$("$FORTSH_BIN" -c 'x=$(echo "hello world"); echo "$x"' 2>&1)
413
+result=$("$SHELL_BIN" -c 'x=$(echo "hello world"); echo "$x"' 2>&1)
414414
 if [ "$result" = "hello world" ]; then
415415
     pass "Quotes inside command substitution"
416416
 else
417417
     fail "Quotes inside command substitution" "hello world" "$result"
418418
 fi
419419
 
420
-result=$("$FORTSH_BIN" -c 'x="$(echo "nested quotes")"; echo "$x"' 2>&1)
420
+result=$("$SHELL_BIN" -c 'x="$(echo "nested quotes")"; echo "$x"' 2>&1)
421421
 if [ "$result" = "nested quotes" ]; then
422422
     pass "Nested quotes in command substitution"
423423
 else
@@ -430,21 +430,21 @@ section "457. BACKSLASH IN DOUBLE QUOTES"
430430
 
431431
 # POSIX: In double quotes, \\\\ (4 backslashes) becomes \\ (2 backslashes)
432432
 # Each pair of \\ in double quotes produces one literal backslash
433
-result=$("$FORTSH_BIN" -c 'echo "back\\\\slash"' 2>&1)
433
+result=$("$SHELL_BIN" -c 'echo "back\\\\slash"' 2>&1)
434434
 if [ "$result" = 'back\\slash' ]; then
435435
     pass "Backslash-backslash in double quotes"
436436
 else
437437
     fail "Backslash-backslash in double quotes" 'back\\slash' "$result"
438438
 fi
439439
 
440
-result=$("$FORTSH_BIN" -c 'echo "newline\\n"' 2>&1)
440
+result=$("$SHELL_BIN" -c 'echo "newline\\n"' 2>&1)
441441
 if [ "$result" = 'newline\n' ]; then
442442
     pass "Backslash-n in double quotes (literal)"
443443
 else
444444
     fail "Backslash-n in double quotes (literal)" 'newline\n' "$result"
445445
 fi
446446
 
447
-result=$("$FORTSH_BIN" -c 'echo "tab\\t"' 2>&1)
447
+result=$("$SHELL_BIN" -c 'echo "tab\\t"' 2>&1)
448448
 if [ "$result" = 'tab\t' ]; then
449449
     pass "Backslash-t in double quotes (literal)"
450450
 else
@@ -455,14 +455,14 @@ fi
455455
 section "458. DOLLAR IN QUOTES"
456456
 # =====================================
457457
 
458
-result=$("$FORTSH_BIN" -c 'echo "cost: \$5"' 2>&1)
458
+result=$("$SHELL_BIN" -c 'echo "cost: \$5"' 2>&1)
459459
 if [ "$result" = 'cost: $5' ]; then
460460
     pass "Escaped dollar in double quotes"
461461
 else
462462
     fail "Escaped dollar in double quotes" 'cost: $5' "$result"
463463
 fi
464464
 
465
-result=$("$FORTSH_BIN" -c "echo 'cost: \$5'" 2>&1)
465
+result=$("$SHELL_BIN" -c "echo 'cost: \$5'" 2>&1)
466466
 if [ "$result" = 'cost: $5' ]; then
467467
     pass "Dollar in single quotes (literal)"
468468
 else
@@ -473,7 +473,7 @@ fi
473473
 section "459. NEWLINE IN QUOTES"
474474
 # =====================================
475475
 
476
-result=$("$FORTSH_BIN" -c 'echo "line1
476
+result=$("$SHELL_BIN" -c 'echo "line1
477477
 line2"' 2>&1)
478478
 expected=$(printf "line1\nline2")
479479
 if [ "$result" = "$expected" ]; then
@@ -482,7 +482,7 @@ else
482482
     fail "Literal newline in double quotes" "$expected" "$result"
483483
 fi
484484
 
485
-result=$("$FORTSH_BIN" -c "echo 'line1
485
+result=$("$SHELL_BIN" -c "echo 'line1
486486
 line2'" 2>&1)
487487
 expected=$(printf "line1\nline2")
488488
 if [ "$result" = "$expected" ]; then
@@ -495,14 +495,14 @@ fi
495495
 section "460. TAB AND SPACE IN QUOTES"
496496
 # =====================================
497497
 
498
-result=$("$FORTSH_BIN" -c 'echo "	tab"' 2>&1)
498
+result=$("$SHELL_BIN" -c 'echo "	tab"' 2>&1)
499499
 if printf "%s" "$result" | grep -q "	"; then
500500
     pass "Literal tab in double quotes"
501501
 else
502502
     fail "Literal tab in double quotes" "string with tab" "$result"
503503
 fi
504504
 
505
-result=$("$FORTSH_BIN" -c 'echo "  spaces  "' 2>&1)
505
+result=$("$SHELL_BIN" -c 'echo "  spaces  "' 2>&1)
506506
 if [ "$result" = "  spaces  " ]; then
507507
     pass "Multiple spaces in double quotes"
508508
 else
@@ -513,7 +513,7 @@ fi
513513
 section "461. QUOTING IN FOR LOOP"
514514
 # =====================================
515515
 
516
-result=$("$FORTSH_BIN" -c 'for x in "a b" c; do echo "[$x]"; done' 2>&1)
516
+result=$("$SHELL_BIN" -c 'for x in "a b" c; do echo "[$x]"; done' 2>&1)
517517
 expected=$(printf "[a b]\n[c]")
518518
 if [ "$result" = "$expected" ]; then
519519
     pass "Quoted string in for list"
@@ -521,7 +521,7 @@ else
521521
     fail "Quoted string in for list" "$expected" "$result"
522522
 fi
523523
 
524
-result=$("$FORTSH_BIN" -c 'list="a b c"; for x in $list; do echo "[$x]"; done' 2>&1)
524
+result=$("$SHELL_BIN" -c 'list="a b c"; for x in $list; do echo "[$x]"; done' 2>&1)
525525
 expected=$(printf "[a]\n[b]\n[c]")
526526
 if [ "$result" = "$expected" ]; then
527527
     pass "Unquoted var splits in for"
@@ -529,7 +529,7 @@ else
529529
     fail "Unquoted var splits in for" "$expected" "$result"
530530
 fi
531531
 
532
-result=$("$FORTSH_BIN" -c 'list="a b c"; for x in "$list"; do echo "[$x]"; done' 2>&1)
532
+result=$("$SHELL_BIN" -c 'list="a b c"; for x in "$list"; do echo "[$x]"; done' 2>&1)
533533
 if [ "$result" = "[a b c]" ]; then
534534
     pass "Quoted var no split in for"
535535
 else
@@ -540,14 +540,14 @@ fi
540540
 section "462. QUOTING IN CASE STATEMENT"
541541
 # =====================================
542542
 
543
-result=$("$FORTSH_BIN" -c 'x="hello world"; case "$x" in "hello world") echo match;; esac' 2>&1)
543
+result=$("$SHELL_BIN" -c 'x="hello world"; case "$x" in "hello world") echo match;; esac' 2>&1)
544544
 if [ "$result" = "match" ]; then
545545
     pass "Quoted string in case word"
546546
 else
547547
     fail "Quoted string in case word" "match" "$result"
548548
 fi
549549
 
550
-result=$("$FORTSH_BIN" -c 'case "a b" in "a b") echo yes;; *) echo no;; esac' 2>&1)
550
+result=$("$SHELL_BIN" -c 'case "a b" in "a b") echo yes;; *) echo no;; esac' 2>&1)
551551
 if [ "$result" = "yes" ]; then
552552
     pass "Quoted pattern in case"
553553
 else
@@ -558,28 +558,28 @@ fi
558558
 section "463. QUOTING SPECIAL SHELL CHARS"
559559
 # =====================================
560560
 
561
-result=$("$FORTSH_BIN" -c 'echo "hello; world"' 2>&1)
561
+result=$("$SHELL_BIN" -c 'echo "hello; world"' 2>&1)
562562
 if [ "$result" = "hello; world" ]; then
563563
     pass "Semicolon in double quotes"
564564
 else
565565
     fail "Semicolon in double quotes" "hello; world" "$result"
566566
 fi
567567
 
568
-result=$("$FORTSH_BIN" -c "echo 'a && b'" 2>&1)
568
+result=$("$SHELL_BIN" -c "echo 'a && b'" 2>&1)
569569
 if [ "$result" = "a && b" ]; then
570570
     pass "Double ampersand in single quotes"
571571
 else
572572
     fail "Double ampersand in single quotes" "a && b" "$result"
573573
 fi
574574
 
575
-result=$("$FORTSH_BIN" -c 'echo "a || b"' 2>&1)
575
+result=$("$SHELL_BIN" -c 'echo "a || b"' 2>&1)
576576
 if [ "$result" = "a || b" ]; then
577577
     pass "Double pipe in double quotes"
578578
 else
579579
     fail "Double pipe in double quotes" "a || b" "$result"
580580
 fi
581581
 
582
-result=$("$FORTSH_BIN" -c "echo 'back\`tick'" 2>&1)
582
+result=$("$SHELL_BIN" -c "echo 'back\`tick'" 2>&1)
583583
 if [ "$result" = 'back`tick' ]; then
584584
     pass "Backtick in single quotes"
585585
 else
@@ -590,14 +590,14 @@ fi
590590
 section "464. QUOTING IN ARITHMETIC"
591591
 # =====================================
592592
 
593
-result=$("$FORTSH_BIN" -c 'x=5; echo $((x + 3))' 2>&1)
593
+result=$("$SHELL_BIN" -c 'x=5; echo $((x + 3))' 2>&1)
594594
 if [ "$result" = "8" ]; then
595595
     pass "Unquoted var in arithmetic"
596596
 else
597597
     fail "Unquoted var in arithmetic" "8" "$result"
598598
 fi
599599
 
600
-result=$("$FORTSH_BIN" -c 'x="5"; echo $((x + 3))' 2>&1)
600
+result=$("$SHELL_BIN" -c 'x="5"; echo $((x + 3))' 2>&1)
601601
 if [ "$result" = "8" ]; then
602602
     pass "Quoted assignment used in arithmetic"
603603
 else
@@ -608,7 +608,7 @@ fi
608608
 section "465. ESCAPE SEQUENCES"
609609
 # =====================================
610610
 
611
-result=$("$FORTSH_BIN" -c 'echo "hello\tworld"' 2>&1)
611
+result=$("$SHELL_BIN" -c 'echo "hello\tworld"' 2>&1)
612612
 if echo "$result" | grep -q "hello"; then
613613
     pass "Backslash-t in double quotes"
614614
 else
@@ -616,7 +616,7 @@ else
616616
 fi
617617
 
618618
 # Test backslash-n literal in single quotes (use double backslash for POSIX sh compatibility)
619
-result=$("$FORTSH_BIN" -c "echo 'hello\\nworld'" 2>&1)
619
+result=$("$SHELL_BIN" -c "echo 'hello\\nworld'" 2>&1)
620620
 if printf '%s' "$result" | grep -q 'hello.nworld'; then
621621
     pass "Backslash-n literal in single quotes"
622622
 else
@@ -627,28 +627,28 @@ fi
627627
 section "466. QUOTING AND WORD SPLITTING"
628628
 # =====================================
629629
 
630
-result=$("$FORTSH_BIN" -c 'x="a b c"; set -- $x; echo $#' 2>&1)
630
+result=$("$SHELL_BIN" -c 'x="a b c"; set -- $x; echo $#' 2>&1)
631631
 if [ "$result" = "3" ]; then
632632
     pass "Unquoted var splits on spaces"
633633
 else
634634
     fail "Unquoted var splits on spaces" "3" "$result"
635635
 fi
636636
 
637
-result=$("$FORTSH_BIN" -c 'x="a b c"; set -- "$x"; echo $#' 2>&1)
637
+result=$("$SHELL_BIN" -c 'x="a b c"; set -- "$x"; echo $#' 2>&1)
638638
 if [ "$result" = "1" ]; then
639639
     pass "Quoted var prevents splitting"
640640
 else
641641
     fail "Quoted var prevents splitting" "1" "$result"
642642
 fi
643643
 
644
-result=$("$FORTSH_BIN" -c 'x=""; set -- $x; echo $#' 2>&1)
644
+result=$("$SHELL_BIN" -c 'x=""; set -- $x; echo $#' 2>&1)
645645
 if [ "$result" = "0" ]; then
646646
     pass "Empty unquoted var produces no args"
647647
 else
648648
     fail "Empty unquoted var produces no args" "0" "$result"
649649
 fi
650650
 
651
-result=$("$FORTSH_BIN" -c 'x=""; set -- "$x"; echo $#' 2>&1)
651
+result=$("$SHELL_BIN" -c 'x=""; set -- "$x"; echo $#' 2>&1)
652652
 if [ "$result" = "1" ]; then
653653
     pass "Empty quoted var produces one empty arg"
654654
 else
@@ -659,21 +659,21 @@ fi
659659
 section "467. QUOTING SPECIAL PARAMETERS"
660660
 # =====================================
661661
 
662
-result=$("$FORTSH_BIN" -c 'set -- a b c; echo "$@" | wc -w' 2>&1)
662
+result=$("$SHELL_BIN" -c 'set -- a b c; echo "$@" | wc -w' 2>&1)
663663
 if [ "$result" -eq 3 ] 2>/dev/null; then
664664
     pass 'Quoted $@ preserves args'
665665
 else
666666
     fail 'Quoted $@ preserves args' "3" "$result"
667667
 fi
668668
 
669
-result=$("$FORTSH_BIN" -c 'set -- a b c; echo "$*"' 2>&1)
669
+result=$("$SHELL_BIN" -c 'set -- a b c; echo "$*"' 2>&1)
670670
 if [ "$result" = "a b c" ]; then
671671
     pass 'Quoted $* joins args'
672672
 else
673673
     fail 'Quoted $* joins args' "a b c" "$result"
674674
 fi
675675
 
676
-result=$("$FORTSH_BIN" -c 'set -- a "b c" d; for x in "$@"; do echo "[$x]"; done' 2>&1)
676
+result=$("$SHELL_BIN" -c 'set -- a "b c" d; for x in "$@"; do echo "[$x]"; done' 2>&1)
677677
 expected=$(printf "[a]\n[b c]\n[d]")
678678
 if [ "$result" = "$expected" ]; then
679679
     pass 'Quoted $@ preserves quoting in original args'
@@ -685,14 +685,14 @@ fi
685685
 section "468. NESTED QUOTING"
686686
 # =====================================
687687
 
688
-result=$("$FORTSH_BIN" -c "echo 'single \"with\" double'" 2>&1)
688
+result=$("$SHELL_BIN" -c "echo 'single \"with\" double'" 2>&1)
689689
 if [ "$result" = 'single "with" double' ]; then
690690
     pass "Double quotes inside single quotes"
691691
 else
692692
     fail "Double quotes inside single quotes"
693693
 fi
694694
 
695
-result=$("$FORTSH_BIN" -c 'echo "double '\''with'\'' single"' 2>&1)
695
+result=$("$SHELL_BIN" -c 'echo "double '\''with'\'' single"' 2>&1)
696696
 if [ "$result" = "double 'with' single" ]; then
697697
     pass "Single quotes inside double quotes (escaped)"
698698
 else
@@ -703,21 +703,21 @@ fi
703703
 section "469. QUOTING IN ASSIGNMENTS"
704704
 # =====================================
705705
 
706
-result=$("$FORTSH_BIN" -c 'x="hello world"; echo $x' 2>&1)
706
+result=$("$SHELL_BIN" -c 'x="hello world"; echo $x' 2>&1)
707707
 if [ "$result" = "hello world" ]; then
708708
     pass "Quoted assignment with spaces"
709709
 else
710710
     fail "Quoted assignment with spaces" "hello world" "$result"
711711
 fi
712712
 
713
-result=$("$FORTSH_BIN" -c "x='hello world'; echo \$x" 2>&1)
713
+result=$("$SHELL_BIN" -c "x='hello world'; echo \$x" 2>&1)
714714
 if [ "$result" = "hello world" ]; then
715715
     pass "Single-quoted assignment with spaces"
716716
 else
717717
     fail "Single-quoted assignment with spaces" "hello world" "$result"
718718
 fi
719719
 
720
-result=$("$FORTSH_BIN" -c 'x=hello\ world; echo $x' 2>&1)
720
+result=$("$SHELL_BIN" -c 'x=hello\ world; echo $x' 2>&1)
721721
 if [ "$result" = "hello world" ]; then
722722
     pass "Escaped space in assignment"
723723
 else
@@ -728,14 +728,14 @@ fi
728728
 section "470. QUOTING IN COMMAND SUBSTITUTION"
729729
 # =====================================
730730
 
731
-result=$("$FORTSH_BIN" -c 'x=$(echo "hello world"); echo "$x"' 2>&1)
731
+result=$("$SHELL_BIN" -c 'x=$(echo "hello world"); echo "$x"' 2>&1)
732732
 if [ "$result" = "hello world" ]; then
733733
     pass "Quoted string in command substitution"
734734
 else
735735
     fail "Quoted string in command substitution" "hello world" "$result"
736736
 fi
737737
 
738
-result=$("$FORTSH_BIN" -c 'x=`echo "hello world"`; echo "$x"' 2>&1)
738
+result=$("$SHELL_BIN" -c 'x=`echo "hello world"`; echo "$x"' 2>&1)
739739
 if [ "$result" = "hello world" ]; then
740740
     pass "Quoted string in backtick substitution"
741741
 else
@@ -746,21 +746,21 @@ fi
746746
 section "471. QUOTING AND GLOB PREVENTION"
747747
 # =====================================
748748
 
749
-result=$("$FORTSH_BIN" -c 'echo "*"' 2>&1)
749
+result=$("$SHELL_BIN" -c 'echo "*"' 2>&1)
750750
 if [ "$result" = "*" ]; then
751751
     pass "Quoted asterisk is literal"
752752
 else
753753
     fail "Quoted asterisk is literal" "*" "$result"
754754
 fi
755755
 
756
-result=$("$FORTSH_BIN" -c 'echo "?"' 2>&1)
756
+result=$("$SHELL_BIN" -c 'echo "?"' 2>&1)
757757
 if [ "$result" = "?" ]; then
758758
     pass "Quoted question mark is literal"
759759
 else
760760
     fail "Quoted question mark is literal" "?" "$result"
761761
 fi
762762
 
763
-result=$("$FORTSH_BIN" -c 'echo "[abc]"' 2>&1)
763
+result=$("$SHELL_BIN" -c 'echo "[abc]"' 2>&1)
764764
 if [ "$result" = "[abc]" ]; then
765765
     pass "Quoted brackets are literal"
766766
 else
@@ -771,21 +771,21 @@ fi
771771
 section "472. QUOTING IN TESTS"
772772
 # =====================================
773773
 
774
-result=$("$FORTSH_BIN" -c 'x=""; [ -z "$x" ] && echo empty' 2>&1)
774
+result=$("$SHELL_BIN" -c 'x=""; [ -z "$x" ] && echo empty' 2>&1)
775775
 if [ "$result" = "empty" ]; then
776776
     pass "Quoted empty var in test -z"
777777
 else
778778
     fail "Quoted empty var in test -z" "empty" "$result"
779779
 fi
780780
 
781
-result=$("$FORTSH_BIN" -c 'x="hello"; [ -n "$x" ] && echo nonempty' 2>&1)
781
+result=$("$SHELL_BIN" -c 'x="hello"; [ -n "$x" ] && echo nonempty' 2>&1)
782782
 if [ "$result" = "nonempty" ]; then
783783
     pass "Quoted var in test -n"
784784
 else
785785
     fail "Quoted var in test -n" "nonempty" "$result"
786786
 fi
787787
 
788
-result=$("$FORTSH_BIN" -c 'x="a b"; [ "$x" = "a b" ] && echo match' 2>&1)
788
+result=$("$SHELL_BIN" -c 'x="a b"; [ "$x" = "a b" ] && echo match' 2>&1)
789789
 if [ "$result" = "match" ]; then
790790
     pass "Quoted var with spaces in test ="
791791
 else
@@ -796,14 +796,14 @@ fi
796796
 section "473. QUOTING IN CASE PATTERNS"
797797
 # =====================================
798798
 
799
-result=$("$FORTSH_BIN" -c 'x="*"; case "$x" in "*") echo literal;; esac' 2>&1)
799
+result=$("$SHELL_BIN" -c 'x="*"; case "$x" in "*") echo literal;; esac' 2>&1)
800800
 if [ "$result" = "literal" ]; then
801801
     pass "Quoted asterisk matches literally in case"
802802
 else
803803
     fail "Quoted asterisk matches literally in case" "literal" "$result"
804804
 fi
805805
 
806
-result=$("$FORTSH_BIN" -c 'x="a b"; case "$x" in "a b") echo match;; esac' 2>&1)
806
+result=$("$SHELL_BIN" -c 'x="a b"; case "$x" in "a b") echo match;; esac' 2>&1)
807807
 if [ "$result" = "match" ]; then
808808
     pass "Quoted pattern with space in case"
809809
 else
@@ -814,14 +814,14 @@ fi
814814
 section "474. QUOTING IN FUNCTION ARGS"
815815
 # =====================================
816816
 
817
-result=$("$FORTSH_BIN" -c 'f() { echo "[$1]"; }; f "hello world"' 2>&1)
817
+result=$("$SHELL_BIN" -c 'f() { echo "[$1]"; }; f "hello world"' 2>&1)
818818
 if [ "$result" = "[hello world]" ]; then
819819
     pass "Quoted arg to function"
820820
 else
821821
     fail "Quoted arg to function" "[hello world]" "$result"
822822
 fi
823823
 
824
-result=$("$FORTSH_BIN" -c 'f() { echo $#; }; f "a b" "c d"' 2>&1)
824
+result=$("$SHELL_BIN" -c 'f() { echo $#; }; f "a b" "c d"' 2>&1)
825825
 if [ "$result" = "2" ]; then
826826
     pass "Quoted args count in function"
827827
 else
@@ -832,14 +832,14 @@ fi
832832
 section "475. DOLLAR IN QUOTES"
833833
 # =====================================
834834
 
835
-result=$("$FORTSH_BIN" -c 'echo "\$HOME"' 2>&1)
835
+result=$("$SHELL_BIN" -c 'echo "\$HOME"' 2>&1)
836836
 if [ "$result" = '$HOME' ]; then
837837
     pass "Escaped dollar in double quotes"
838838
 else
839839
     fail "Escaped dollar in double quotes" "\$HOME" "$result"
840840
 fi
841841
 
842
-result=$("$FORTSH_BIN" -c "echo '\$HOME'" 2>&1)
842
+result=$("$SHELL_BIN" -c "echo '\$HOME'" 2>&1)
843843
 if [ "$result" = '$HOME' ]; then
844844
     pass "Dollar in single quotes"
845845
 else
@@ -850,14 +850,14 @@ fi
850850
 section "476. BACKSLASH IN QUOTES"
851851
 # =====================================
852852
 
853
-result=$("$FORTSH_BIN" -c 'echo "\\"' 2>&1)
853
+result=$("$SHELL_BIN" -c 'echo "\\"' 2>&1)
854854
 if [ "$result" = '\' ]; then
855855
     pass "Escaped backslash in double quotes"
856856
 else
857857
     fail "Escaped backslash in double quotes" "\\" "$result"
858858
 fi
859859
 
860
-result=$("$FORTSH_BIN" -c "echo '\\'" 2>&1)
860
+result=$("$SHELL_BIN" -c "echo '\\'" 2>&1)
861861
 if [ "$result" = '\' ]; then
862862
     pass "Backslash in single quotes"
863863
 else
@@ -868,14 +868,14 @@ fi
868868
 section "477. QUOTE REMOVAL"
869869
 # =====================================
870870
 
871
-result=$("$FORTSH_BIN" -c 'echo ""hello""' 2>&1)
871
+result=$("$SHELL_BIN" -c 'echo ""hello""' 2>&1)
872872
 if [ "$result" = "hello" ]; then
873873
     pass "Empty quotes around word"
874874
 else
875875
     fail "Empty quotes around word" "hello" "$result"
876876
 fi
877877
 
878
-result=$("$FORTSH_BIN" -c 'echo "a""b""c"' 2>&1)
878
+result=$("$SHELL_BIN" -c 'echo "a""b""c"' 2>&1)
879879
 if [ "$result" = "abc" ]; then
880880
     pass "Adjacent quoted strings concatenate"
881881
 else
@@ -886,14 +886,14 @@ fi
886886
 section "478. MIXED QUOTE STYLES"
887887
 # =====================================
888888
 
889
-result=$("$FORTSH_BIN" -c "x=val; echo 'a'\"\$x\"'b'" 2>&1)
889
+result=$("$SHELL_BIN" -c "x=val; echo 'a'\"\$x\"'b'" 2>&1)
890890
 if [ "$result" = "avalb" ]; then
891891
     pass "Mixed single and double quotes"
892892
 else
893893
     fail "Mixed single and double quotes" "avalb" "$result"
894894
 fi
895895
 
896
-result=$("$FORTSH_BIN" -c "echo 'single'\"double\"'single'" 2>&1)
896
+result=$("$SHELL_BIN" -c "echo 'single'\"double\"'single'" 2>&1)
897897
 if [ "$result" = "singledoublesingle" ]; then
898898
     pass "Alternating quote styles"
899899
 else
@@ -904,7 +904,7 @@ fi
904904
 section "479. QUOTING IN REDIRECTIONS"
905905
 # =====================================
906906
 
907
-result=$("$FORTSH_BIN" -c 'echo test > "/tmp/quote space test.txt"; cat "/tmp/quote space test.txt"; rm "/tmp/quote space test.txt"' 2>&1)
907
+result=$("$SHELL_BIN" -c 'echo test > "/tmp/quote space test.txt"; cat "/tmp/quote space test.txt"; rm "/tmp/quote space test.txt"' 2>&1)
908908
 if [ "$result" = "test" ]; then
909909
     pass "Quoted filename with space in redirect"
910910
 else
@@ -915,21 +915,21 @@ fi
915915
 section "480. EMPTY QUOTES"
916916
 # =====================================
917917
 
918
-result=$("$FORTSH_BIN" -c 'echo ""' 2>&1)
918
+result=$("$SHELL_BIN" -c 'echo ""' 2>&1)
919919
 if [ -z "$result" ]; then
920920
     pass "Empty double quotes produce empty output"
921921
 else
922922
     fail "Empty double quotes produce empty output" "empty" "$result"
923923
 fi
924924
 
925
-result=$("$FORTSH_BIN" -c "echo ''" 2>&1)
925
+result=$("$SHELL_BIN" -c "echo ''" 2>&1)
926926
 if [ -z "$result" ]; then
927927
     pass "Empty single quotes produce empty output"
928928
 else
929929
     fail "Empty single quotes produce empty output" "empty" "$result"
930930
 fi
931931
 
932
-result=$("$FORTSH_BIN" -c 'x=""; echo "[$x]"' 2>&1)
932
+result=$("$SHELL_BIN" -c 'x=""; echo "[$x]"' 2>&1)
933933
 if [ "$result" = "[]" ]; then
934934
     pass "Empty var in quotes"
935935
 else
suites/posix/posix_compliance_redirect.shmodified
@@ -24,12 +24,12 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 
2929
 # Check if fortsh exists
30
-if [ ! -x "$FORTSH_BIN" ]; then
31
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
+if [ ! -x "$SHELL_BIN" ]; then
31
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
32
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3333
     exit 1
3434
 fi
3535
 
@@ -81,21 +81,21 @@ trap cleanup EXIT
8181
 section "428. OUTPUT REDIRECTION >"
8282
 # =====================================
8383
 
84
-result=$("$FORTSH_BIN" -c 'echo hello > '"$TEST_DIR"'/out1.txt; cat '"$TEST_DIR"'/out1.txt' 2>&1)
84
+result=$("$SHELL_BIN" -c 'echo hello > '"$TEST_DIR"'/out1.txt; cat '"$TEST_DIR"'/out1.txt' 2>&1)
8585
 if [ "$result" = "hello" ]; then
8686
     pass "> redirects stdout to file"
8787
 else
8888
     fail "> redirects stdout to file" "hello" "$result"
8989
 fi
9090
 
91
-result=$("$FORTSH_BIN" -c 'echo first > '"$TEST_DIR"'/out2.txt; echo second > '"$TEST_DIR"'/out2.txt; cat '"$TEST_DIR"'/out2.txt' 2>&1)
91
+result=$("$SHELL_BIN" -c 'echo first > '"$TEST_DIR"'/out2.txt; echo second > '"$TEST_DIR"'/out2.txt; cat '"$TEST_DIR"'/out2.txt' 2>&1)
9292
 if [ "$result" = "second" ]; then
9393
     pass "> overwrites existing file"
9494
 else
9595
     fail "> overwrites existing file" "second" "$result"
9696
 fi
9797
 
98
-result=$("$FORTSH_BIN" -c 'echo "multi word" > '"$TEST_DIR"'/out3.txt; cat '"$TEST_DIR"'/out3.txt' 2>&1)
98
+result=$("$SHELL_BIN" -c 'echo "multi word" > '"$TEST_DIR"'/out3.txt; cat '"$TEST_DIR"'/out3.txt' 2>&1)
9999
 if [ "$result" = "multi word" ]; then
100100
     pass "> with quoted string"
101101
 else
@@ -106,7 +106,7 @@ fi
106106
 section "429. APPEND REDIRECTION >>"
107107
 # =====================================
108108
 
109
-result=$("$FORTSH_BIN" -c 'echo first > '"$TEST_DIR"'/append.txt; echo second >> '"$TEST_DIR"'/append.txt; cat '"$TEST_DIR"'/append.txt' 2>&1)
109
+result=$("$SHELL_BIN" -c 'echo first > '"$TEST_DIR"'/append.txt; echo second >> '"$TEST_DIR"'/append.txt; cat '"$TEST_DIR"'/append.txt' 2>&1)
110110
 expected=$(printf "first\nsecond")
111111
 if [ "$result" = "$expected" ]; then
112112
     pass ">> appends to file"
@@ -114,7 +114,7 @@ else
114114
     fail ">> appends to file" "$expected" "$result"
115115
 fi
116116
 
117
-result=$("$FORTSH_BIN" -c 'echo line1 >> '"$TEST_DIR"'/new.txt; cat '"$TEST_DIR"'/new.txt' 2>&1)
117
+result=$("$SHELL_BIN" -c 'echo line1 >> '"$TEST_DIR"'/new.txt; cat '"$TEST_DIR"'/new.txt' 2>&1)
118118
 if [ "$result" = "line1" ]; then
119119
     pass ">> creates file if not exists"
120120
 else
@@ -127,14 +127,14 @@ section "430. INPUT REDIRECTION <"
127127
 
128128
 echo "test input" > "$TEST_DIR/input.txt"
129129
 
130
-result=$("$FORTSH_BIN" -c 'cat < '"$TEST_DIR"'/input.txt' 2>&1)
130
+result=$("$SHELL_BIN" -c 'cat < '"$TEST_DIR"'/input.txt' 2>&1)
131131
 if [ "$result" = "test input" ]; then
132132
     pass "< redirects file to stdin"
133133
 else
134134
     fail "< redirects file to stdin" "test input" "$result"
135135
 fi
136136
 
137
-result=$("$FORTSH_BIN" -c 'read line < '"$TEST_DIR"'/input.txt; echo "$line"' 2>&1)
137
+result=$("$SHELL_BIN" -c 'read line < '"$TEST_DIR"'/input.txt; echo "$line"' 2>&1)
138138
 if [ "$result" = "test input" ]; then
139139
     pass "< with read builtin"
140140
 else
@@ -145,14 +145,14 @@ fi
145145
 section "431. STDERR REDIRECTION 2>"
146146
 # =====================================
147147
 
148
-result=$("$FORTSH_BIN" -c 'ls /nonexistent 2> '"$TEST_DIR"'/err.txt; cat '"$TEST_DIR"'/err.txt' 2>&1)
148
+result=$("$SHELL_BIN" -c 'ls /nonexistent 2> '"$TEST_DIR"'/err.txt; cat '"$TEST_DIR"'/err.txt' 2>&1)
149149
 if echo "$result" | grep -qi "no such\|not found\|cannot"; then
150150
     pass "2> redirects stderr to file"
151151
 else
152152
     fail "2> redirects stderr to file" "error message" "$result"
153153
 fi
154154
 
155
-result=$("$FORTSH_BIN" -c 'echo stdout; ls /nonexistent 2>/dev/null' 2>&1)
155
+result=$("$SHELL_BIN" -c 'echo stdout; ls /nonexistent 2>/dev/null' 2>&1)
156156
 if [ "$result" = "stdout" ]; then
157157
     pass "2>/dev/null suppresses stderr"
158158
 else
@@ -163,14 +163,14 @@ fi
163163
 section "432. REDIRECT STDERR TO STDOUT 2>&1"
164164
 # =====================================
165165
 
166
-result=$("$FORTSH_BIN" -c '{ echo out; ls /nonexistent; } 2>&1 | head -2' 2>&1)
166
+result=$("$SHELL_BIN" -c '{ echo out; ls /nonexistent; } 2>&1 | head -2' 2>&1)
167167
 if echo "$result" | grep -q "out"; then
168168
     pass "2>&1 merges stderr to stdout"
169169
 else
170170
     fail "2>&1 merges stderr to stdout" "both streams" "$result"
171171
 fi
172172
 
173
-result=$("$FORTSH_BIN" -c 'ls /nonexistent 2>&1 | cat' 2>&1)
173
+result=$("$SHELL_BIN" -c 'ls /nonexistent 2>&1 | cat' 2>&1)
174174
 if echo "$result" | grep -qi "no such\|not found\|cannot"; then
175175
     pass "2>&1 stderr goes through pipe"
176176
 else
@@ -181,7 +181,7 @@ fi
181181
 section "433. REDIRECT STDOUT TO STDERR 1>&2"
182182
 # =====================================
183183
 
184
-result=$("$FORTSH_BIN" -c 'echo error >&2' 2>&1)
184
+result=$("$SHELL_BIN" -c 'echo error >&2' 2>&1)
185185
 if [ "$result" = "error" ]; then
186186
     pass ">&2 redirects stdout to stderr"
187187
 else
@@ -191,7 +191,7 @@ fi
191191
 # Note: matches bash - POSIX redirections processed left-to-right
192192
 # 1>&2 copies fd2 to fd1, then 2>/dev/null redirects fd2 to null
193193
 # fd1 still points to original fd2 (stderr), so output appears
194
-result=$("$FORTSH_BIN" -c 'echo error 1>&2 2>/dev/null' 2>&1)
194
+result=$("$SHELL_BIN" -c 'echo error 1>&2 2>/dev/null' 2>&1)
195195
 if [ "$result" = "error" ]; then
196196
     pass "1>&2 with stderr suppressed (matches bash)"
197197
 else
@@ -202,14 +202,14 @@ fi
202202
 section "434. COMBINED REDIRECTIONS"
203203
 # =====================================
204204
 
205
-result=$("$FORTSH_BIN" -c 'echo out > '"$TEST_DIR"'/combined.txt 2>&1; cat '"$TEST_DIR"'/combined.txt' 2>&1)
205
+result=$("$SHELL_BIN" -c 'echo out > '"$TEST_DIR"'/combined.txt 2>&1; cat '"$TEST_DIR"'/combined.txt' 2>&1)
206206
 if [ "$result" = "out" ]; then
207207
     pass "> file 2>&1 combination"
208208
 else
209209
     fail "> file 2>&1 combination" "out" "$result"
210210
 fi
211211
 
212
-result=$("$FORTSH_BIN" -c '{ echo out; echo err >&2; } > '"$TEST_DIR"'/both.txt 2>&1; cat '"$TEST_DIR"'/both.txt' 2>&1)
212
+result=$("$SHELL_BIN" -c '{ echo out; echo err >&2; } > '"$TEST_DIR"'/both.txt 2>&1; cat '"$TEST_DIR"'/both.txt' 2>&1)
213213
 expected=$(printf "out\nerr")
214214
 if [ "$result" = "$expected" ]; then
215215
     pass "Both streams to same file"
@@ -223,7 +223,7 @@ section "435. NOCLOBBER WITH >|"
223223
 
224224
 echo "original" > "$TEST_DIR/noclobber.txt"
225225
 
226
-result=$("$FORTSH_BIN" -c 'set -C; echo new >| '"$TEST_DIR"'/noclobber.txt; cat '"$TEST_DIR"'/noclobber.txt' 2>&1)
226
+result=$("$SHELL_BIN" -c 'set -C; echo new >| '"$TEST_DIR"'/noclobber.txt; cat '"$TEST_DIR"'/noclobber.txt' 2>&1)
227227
 if [ "$result" = "new" ]; then
228228
     pass ">| overrides noclobber"
229229
 else
@@ -234,21 +234,21 @@ fi
234234
 section "436. SIMPLE PIPELINE"
235235
 # =====================================
236236
 
237
-result=$("$FORTSH_BIN" -c 'echo hello | cat' 2>&1)
237
+result=$("$SHELL_BIN" -c 'echo hello | cat' 2>&1)
238238
 if [ "$result" = "hello" ]; then
239239
     pass "Simple two-stage pipeline"
240240
 else
241241
     fail "Simple two-stage pipeline" "hello" "$result"
242242
 fi
243243
 
244
-result=$("$FORTSH_BIN" -c 'echo hello world | wc -w' 2>&1)
244
+result=$("$SHELL_BIN" -c 'echo hello world | wc -w' 2>&1)
245245
 if echo "$result" | grep -q "2"; then
246246
     pass "Pipeline with wc"
247247
 else
248248
     fail "Pipeline with wc" "2" "$result"
249249
 fi
250250
 
251
-result=$("$FORTSH_BIN" -c 'printf "c\na\nb\n" | sort' 2>&1)
251
+result=$("$SHELL_BIN" -c 'printf "c\na\nb\n" | sort' 2>&1)
252252
 expected=$(printf "a\nb\nc")
253253
 if [ "$result" = "$expected" ]; then
254254
     pass "Pipeline with sort"
@@ -260,14 +260,14 @@ fi
260260
 section "437. MULTI-STAGE PIPELINE"
261261
 # =====================================
262262
 
263
-result=$("$FORTSH_BIN" -c 'echo hello | cat | cat | cat' 2>&1)
263
+result=$("$SHELL_BIN" -c 'echo hello | cat | cat | cat' 2>&1)
264264
 if [ "$result" = "hello" ]; then
265265
     pass "Four-stage pipeline"
266266
 else
267267
     fail "Four-stage pipeline" "hello" "$result"
268268
 fi
269269
 
270
-result=$("$FORTSH_BIN" -c 'printf "b\na\nc\nb\na\n" | sort | uniq' 2>&1)
270
+result=$("$SHELL_BIN" -c 'printf "b\na\nc\nb\na\n" | sort | uniq' 2>&1)
271271
 expected=$(printf "a\nb\nc")
272272
 if [ "$result" = "$expected" ]; then
273273
     pass "sort | uniq pipeline"
@@ -275,7 +275,7 @@ else
275275
     fail "sort | uniq pipeline" "$expected" "$result"
276276
 fi
277277
 
278
-result=$("$FORTSH_BIN" -c 'echo "hello world" | tr " " "\n" | wc -l' 2>&1)
278
+result=$("$SHELL_BIN" -c 'echo "hello world" | tr " " "\n" | wc -l' 2>&1)
279279
 if echo "$result" | grep -q "2"; then
280280
     pass "tr | wc pipeline"
281281
 else
@@ -286,7 +286,7 @@ fi
286286
 section "438. PIPELINE WITH REDIRECTION"
287287
 # =====================================
288288
 
289
-result=$("$FORTSH_BIN" -c 'echo hello | cat > '"$TEST_DIR"'/pipe_out.txt; cat '"$TEST_DIR"'/pipe_out.txt' 2>&1)
289
+result=$("$SHELL_BIN" -c 'echo hello | cat > '"$TEST_DIR"'/pipe_out.txt; cat '"$TEST_DIR"'/pipe_out.txt' 2>&1)
290290
 if [ "$result" = "hello" ]; then
291291
     pass "Pipeline with output redirect"
292292
 else
@@ -294,7 +294,7 @@ else
294294
 fi
295295
 
296296
 echo "from file" > "$TEST_DIR/pipe_in.txt"
297
-result=$("$FORTSH_BIN" -c 'cat < '"$TEST_DIR"'/pipe_in.txt | tr "a-z" "A-Z"' 2>&1)
297
+result=$("$SHELL_BIN" -c 'cat < '"$TEST_DIR"'/pipe_in.txt | tr "a-z" "A-Z"' 2>&1)
298298
 if [ "$result" = "FROM FILE" ]; then
299299
     pass "Input redirect into pipeline"
300300
 else
@@ -305,14 +305,14 @@ fi
305305
 section "439. PIPELINE SUBSHELL"
306306
 # =====================================
307307
 
308
-result=$("$FORTSH_BIN" -c 'echo test | { read x; echo "got: $x"; }' 2>&1)
308
+result=$("$SHELL_BIN" -c 'echo test | { read x; echo "got: $x"; }' 2>&1)
309309
 if [ "$result" = "got: test" ]; then
310310
     pass "Pipeline to brace group"
311311
 else
312312
     fail "Pipeline to brace group" "got: test" "$result"
313313
 fi
314314
 
315
-result=$("$FORTSH_BIN" -c 'echo test | (cat; echo done)' 2>&1)
315
+result=$("$SHELL_BIN" -c 'echo test | (cat; echo done)' 2>&1)
316316
 expected=$(printf "test\ndone")
317317
 if [ "$result" = "$expected" ]; then
318318
     pass "Pipeline to subshell"
@@ -324,14 +324,14 @@ fi
324324
 section "440. COMMAND SUBSTITUTION IN PIPELINE"
325325
 # =====================================
326326
 
327
-result=$("$FORTSH_BIN" -c 'echo $(echo hello | tr "a-z" "A-Z")' 2>&1)
327
+result=$("$SHELL_BIN" -c 'echo $(echo hello | tr "a-z" "A-Z")' 2>&1)
328328
 if [ "$result" = "HELLO" ]; then
329329
     pass "Command substitution with pipeline"
330330
 else
331331
     fail "Command substitution with pipeline" "HELLO" "$result"
332332
 fi
333333
 
334
-result=$("$FORTSH_BIN" -c 'x=$(printf "a\nb\nc\n" | wc -l); echo $x' 2>&1)
334
+result=$("$SHELL_BIN" -c 'x=$(printf "a\nb\nc\n" | wc -l); echo $x' 2>&1)
335335
 if echo "$result" | grep -q "3"; then
336336
     pass "Variable from pipeline in command sub"
337337
 else
@@ -343,7 +343,7 @@ section "441. REDIRECTION ORDER"
343343
 # =====================================
344344
 
345345
 # The order matters: 2>&1 before > vs after
346
-result=$("$FORTSH_BIN" -c '{ echo out; echo err >&2; } > '"$TEST_DIR"'/order1.txt 2>&1; cat '"$TEST_DIR"'/order1.txt | wc -l' 2>&1)
346
+result=$("$SHELL_BIN" -c '{ echo out; echo err >&2; } > '"$TEST_DIR"'/order1.txt 2>&1; cat '"$TEST_DIR"'/order1.txt | wc -l' 2>&1)
347347
 if echo "$result" | grep -q "2"; then
348348
     pass "> file 2>&1 captures both"
349349
 else
@@ -354,21 +354,21 @@ fi
354354
 section "442. /dev/null REDIRECTION"
355355
 # =====================================
356356
 
357
-result=$("$FORTSH_BIN" -c 'echo hello > /dev/null; echo done' 2>&1)
357
+result=$("$SHELL_BIN" -c 'echo hello > /dev/null; echo done' 2>&1)
358358
 if [ "$result" = "done" ]; then
359359
     pass "> /dev/null discards output"
360360
 else
361361
     fail "> /dev/null discards output" "done" "$result"
362362
 fi
363363
 
364
-result=$("$FORTSH_BIN" -c 'cat < /dev/null; echo empty' 2>&1)
364
+result=$("$SHELL_BIN" -c 'cat < /dev/null; echo empty' 2>&1)
365365
 if [ "$result" = "empty" ]; then
366366
     pass "< /dev/null provides empty input"
367367
 else
368368
     fail "< /dev/null provides empty input" "empty" "$result"
369369
 fi
370370
 
371
-result=$("$FORTSH_BIN" -c 'ls /nonexistent 2>/dev/null; echo $?' 2>&1)
371
+result=$("$SHELL_BIN" -c 'ls /nonexistent 2>/dev/null; echo $?' 2>&1)
372372
 # Should show non-zero exit but no error output
373373
 if echo "$result" | grep -qE "^[12]$"; then
374374
     pass "2>/dev/null with failing command"
@@ -381,7 +381,7 @@ section "443. PROCESS SUBSTITUTION STYLE"
381381
 # =====================================
382382
 
383383
 # Note: <() is a bash extension, but we test if basic redirects work with commands
384
-result=$("$FORTSH_BIN" -c 'diff <(echo a) <(echo a) 2>/dev/null; echo $?' 2>&1)
384
+result=$("$SHELL_BIN" -c 'diff <(echo a) <(echo a) 2>/dev/null; echo $?' 2>&1)
385385
 # This may not be supported - just document if it works
386386
 if [ "$result" = "0" ]; then
387387
     pass "Process substitution <() works"
@@ -393,7 +393,7 @@ fi
393393
 section "444. CLOSING FILE DESCRIPTORS"
394394
 # =====================================
395395
 
396
-result=$("$FORTSH_BIN" -c 'echo hello >&-; echo done 2>/dev/null' 2>&1)
396
+result=$("$SHELL_BIN" -c 'echo hello >&-; echo done 2>/dev/null' 2>&1)
397397
 # Closing stdout then trying to echo should either error or succeed
398398
 if echo "$result" | grep -q "done"; then
399399
     pass ">&- closes stdout (recovered)"
@@ -405,7 +405,7 @@ fi
405405
 section "445. DUPLICATING INPUT"
406406
 # =====================================
407407
 
408
-result=$("$FORTSH_BIN" -c 'echo test | { cat; } 0<&0' 2>&1)
408
+result=$("$SHELL_BIN" -c 'echo test | { cat; } 0<&0' 2>&1)
409409
 if [ "$result" = "test" ]; then
410410
     pass "0<&0 duplicates stdin"
411411
 else
@@ -417,14 +417,14 @@ section "446. PIPELINE EXIT STATUS"
417417
 # =====================================
418418
 
419419
 # Last command determines exit status
420
-result=$("$FORTSH_BIN" -c 'false | true; echo $?' 2>&1)
420
+result=$("$SHELL_BIN" -c 'false | true; echo $?' 2>&1)
421421
 if [ "$result" = "0" ]; then
422422
     pass "Pipeline exit is last command (false|true=0)"
423423
 else
424424
     fail "Pipeline exit is last command (false|true=0)" "0" "$result"
425425
 fi
426426
 
427
-result=$("$FORTSH_BIN" -c 'true | false; echo $?' 2>&1)
427
+result=$("$SHELL_BIN" -c 'true | false; echo $?' 2>&1)
428428
 if [ "$result" = "1" ]; then
429429
     pass "Pipeline exit is last command (true|false=1)"
430430
 else
@@ -432,7 +432,7 @@ else
432432
 fi
433433
 
434434
 # Multi-stage pipeline
435
-result=$("$FORTSH_BIN" -c 'echo a | cat | cat | cat; echo $?' 2>&1)
435
+result=$("$SHELL_BIN" -c 'echo a | cat | cat | cat; echo $?' 2>&1)
436436
 if echo "$result" | grep -q "0"; then
437437
     pass "Multi-stage pipeline success"
438438
 else
@@ -440,7 +440,7 @@ else
440440
 fi
441441
 
442442
 # Pipeline with negation
443
-result=$("$FORTSH_BIN" -c '! false | true; echo $?' 2>&1)
443
+result=$("$SHELL_BIN" -c '! false | true; echo $?' 2>&1)
444444
 if [ "$result" = "1" ]; then
445445
     pass "! negates pipeline exit"
446446
 else
@@ -452,7 +452,7 @@ section "447. EXEC REDIRECTIONS"
452452
 # =====================================
453453
 
454454
 # exec without command modifies shell FDs
455
-result=$("$FORTSH_BIN" -c '
455
+result=$("$SHELL_BIN" -c '
456456
 exec 3>"'"$TEST_DIR"'/exec_fd3.txt"
457457
 echo "fd3 data" >&3
458458
 exec 3>&-
@@ -465,7 +465,7 @@ else
465465
 fi
466466
 
467467
 # exec read/write mode
468
-result=$("$FORTSH_BIN" -c '
468
+result=$("$SHELL_BIN" -c '
469469
 echo "initial" > "'"$TEST_DIR"'/rw_test.txt"
470470
 exec 4<>"'"$TEST_DIR"'/rw_test.txt"
471471
 read line <&4
@@ -483,7 +483,7 @@ section "448. COMPOUND REDIRECTIONS"
483483
 # =====================================
484484
 
485485
 # Redirect entire loop
486
-result=$("$FORTSH_BIN" -c '
486
+result=$("$SHELL_BIN" -c '
487487
 for i in 1 2 3; do
488488
     echo $i
489489
 done > "'"$TEST_DIR"'/loop_out.txt"
@@ -497,7 +497,7 @@ else
497497
 fi
498498
 
499499
 # Redirect if statement
500
-result=$("$FORTSH_BIN" -c '
500
+result=$("$SHELL_BIN" -c '
501501
 if true; then
502502
     echo inside
503503
 fi > "'"$TEST_DIR"'/if_out.txt"
@@ -510,7 +510,7 @@ else
510510
 fi
511511
 
512512
 # Redirect case statement
513
-result=$("$FORTSH_BIN" -c '
513
+result=$("$SHELL_BIN" -c '
514514
 case "x" in
515515
     x) echo matched;;
516516
 esac > "'"$TEST_DIR"'/case_out.txt"
@@ -529,7 +529,7 @@ section "449. INPUT REDIRECTION VARIATIONS"
529529
 # cat multiple files
530530
 echo "file1" > "$TEST_DIR/cat1.txt"
531531
 echo "file2" > "$TEST_DIR/cat2.txt"
532
-result=$("$FORTSH_BIN" -c 'cat "'"$TEST_DIR"'/cat1.txt" "'"$TEST_DIR"'/cat2.txt"' 2>&1)
532
+result=$("$SHELL_BIN" -c 'cat "'"$TEST_DIR"'/cat1.txt" "'"$TEST_DIR"'/cat2.txt"' 2>&1)
533533
 expected=$(printf "file1\nfile2")
534534
 if [ "$result" = "$expected" ]; then
535535
     pass "cat multiple files"
@@ -539,7 +539,7 @@ fi
539539
 
540540
 # Input from file
541541
 echo "from file" > "$TEST_DIR/input.txt"
542
-result=$("$FORTSH_BIN" -c 'cat < "'"$TEST_DIR"'/input.txt"' 2>&1)
542
+result=$("$SHELL_BIN" -c 'cat < "'"$TEST_DIR"'/input.txt"' 2>&1)
543543
 if [ "$result" = "from file" ]; then
544544
     pass "< redirects stdin from file"
545545
 else
@@ -552,7 +552,7 @@ section "450. OUTPUT APPEND BEHAVIOR"
552552
 
553553
 # >> creates file if not exists
554554
 rm -f "$TEST_DIR/append_new.txt"
555
-result=$("$FORTSH_BIN" -c 'echo first >> "'"$TEST_DIR"'/append_new.txt"; cat "'"$TEST_DIR"'/append_new.txt"' 2>&1)
555
+result=$("$SHELL_BIN" -c 'echo first >> "'"$TEST_DIR"'/append_new.txt"; cat "'"$TEST_DIR"'/append_new.txt"' 2>&1)
556556
 if [ "$result" = "first" ]; then
557557
     pass ">> creates file if not exists"
558558
 else
@@ -561,7 +561,7 @@ fi
561561
 
562562
 # >> appends to existing
563563
 echo "line1" > "$TEST_DIR/append_exist.txt"
564
-result=$("$FORTSH_BIN" -c 'echo line2 >> "'"$TEST_DIR"'/append_exist.txt"; cat "'"$TEST_DIR"'/append_exist.txt"' 2>&1)
564
+result=$("$SHELL_BIN" -c 'echo line2 >> "'"$TEST_DIR"'/append_exist.txt"; cat "'"$TEST_DIR"'/append_exist.txt"' 2>&1)
565565
 expected=$(printf "line1\nline2")
566566
 if [ "$result" = "$expected" ]; then
567567
     pass ">> appends to existing file"
@@ -571,7 +571,7 @@ fi
571571
 
572572
 # Multiple appends
573573
 rm -f "$TEST_DIR/multi_append.txt"
574
-result=$("$FORTSH_BIN" -c '
574
+result=$("$SHELL_BIN" -c '
575575
 echo a >> "'"$TEST_DIR"'/multi_append.txt"
576576
 echo b >> "'"$TEST_DIR"'/multi_append.txt"
577577
 echo c >> "'"$TEST_DIR"'/multi_append.txt"
@@ -589,7 +589,7 @@ section "451. REDIRECT WITH ASSIGNMENTS"
589589
 # =====================================
590590
 
591591
 # Assignment with redirect
592
-result=$("$FORTSH_BIN" -c 'x=$(cat < /dev/null); echo "empty:[$x]"' 2>&1)
592
+result=$("$SHELL_BIN" -c 'x=$(cat < /dev/null); echo "empty:[$x]"' 2>&1)
593593
 if [ "$result" = "empty:[]" ]; then
594594
     pass "Assignment from empty file"
595595
 else
@@ -597,7 +597,7 @@ else
597597
 fi
598598
 
599599
 # Assignment captures command output despite redirects
600
-result=$("$FORTSH_BIN" -c 'x=$(echo hello 2>/dev/null); echo $x' 2>&1)
600
+result=$("$SHELL_BIN" -c 'x=$(echo hello 2>/dev/null); echo $x' 2>&1)
601601
 if [ "$result" = "hello" ]; then
602602
     pass "Assignment captures stdout"
603603
 else
@@ -609,7 +609,7 @@ section "452. HEREDOC VARIATIONS"
609609
 # =====================================
610610
 
611611
 # Basic heredoc
612
-result=$("$FORTSH_BIN" -c 'cat <<END
612
+result=$("$SHELL_BIN" -c 'cat <<END
613613
 hello
614614
 END' 2>&1)
615615
 if [ "$result" = "hello" ]; then
@@ -619,7 +619,7 @@ else
619619
 fi
620620
 
621621
 # Heredoc with variable expansion
622
-result=$("$FORTSH_BIN" -c 'X=world; cat <<END
622
+result=$("$SHELL_BIN" -c 'X=world; cat <<END
623623
 hello $X
624624
 END' 2>&1)
625625
 if [ "$result" = "hello world" ]; then
@@ -629,7 +629,7 @@ else
629629
 fi
630630
 
631631
 # Quoted heredoc prevents expansion
632
-result=$("$FORTSH_BIN" -c 'cat <<'\''END'\''
632
+result=$("$SHELL_BIN" -c 'cat <<'\''END'\''
633633
 $VAR
634634
 END' 2>&1)
635635
 if [ "$result" = '$VAR' ]; then
@@ -643,7 +643,7 @@ section "453. PIPELINE VARIATIONS"
643643
 # =====================================
644644
 
645645
 # Long pipeline
646
-result=$("$FORTSH_BIN" -c 'echo test | cat | cat | cat | cat' 2>&1)
646
+result=$("$SHELL_BIN" -c 'echo test | cat | cat | cat | cat' 2>&1)
647647
 if [ "$result" = "test" ]; then
648648
     pass "Long pipeline with multiple cats"
649649
 else
@@ -651,7 +651,7 @@ else
651651
 fi
652652
 
653653
 # Pipeline with head
654
-result=$("$FORTSH_BIN" -c 'printf "a\nb\nc\n" | head -1' 2>&1)
654
+result=$("$SHELL_BIN" -c 'printf "a\nb\nc\n" | head -1' 2>&1)
655655
 if [ "$result" = "a" ]; then
656656
     pass "Pipeline with head"
657657
 else
@@ -659,7 +659,7 @@ else
659659
 fi
660660
 
661661
 # Pipeline with tail
662
-result=$("$FORTSH_BIN" -c 'printf "a\nb\nc\n" | tail -1' 2>&1)
662
+result=$("$SHELL_BIN" -c 'printf "a\nb\nc\n" | tail -1' 2>&1)
663663
 if [ "$result" = "c" ]; then
664664
     pass "Pipeline with tail"
665665
 else
@@ -667,7 +667,7 @@ else
667667
 fi
668668
 
669669
 # Pipeline with sort
670
-result=$("$FORTSH_BIN" -c 'printf "c\na\nb\n" | sort | head -1' 2>&1)
670
+result=$("$SHELL_BIN" -c 'printf "c\na\nb\n" | sort | head -1' 2>&1)
671671
 if [ "$result" = "a" ]; then
672672
     pass "Pipeline with sort"
673673
 else
@@ -679,7 +679,7 @@ section "454. FILE DESCRIPTOR OPERATIONS"
679679
 # =====================================
680680
 
681681
 # Dup stdout to stderr
682
-result=$("$FORTSH_BIN" -c 'echo test >&2' 2>&1)
682
+result=$("$SHELL_BIN" -c 'echo test >&2' 2>&1)
683683
 if [ "$result" = "test" ]; then
684684
     pass "Redirect stdout to stderr"
685685
 else
@@ -689,7 +689,7 @@ fi
689689
 # Close stdout after redirecting to stderr
690690
 # Note: matches bash - >&2 redirects stdout to stderr, then 1>&- closes fd1
691691
 # The write to closed fd1 fails with "Bad file descriptor"
692
-result=$("$FORTSH_BIN" -c 'echo test >&2 1>&-' 2>&1)
692
+result=$("$SHELL_BIN" -c 'echo test >&2 1>&-' 2>&1)
693693
 if echo "$result" | grep -q "Bad file descriptor"; then
694694
     pass "Close stdout after redirect (matches bash - write error)"
695695
 else
@@ -702,7 +702,7 @@ section "455. INPUT REDIRECTION VARIATIONS"
702702
 
703703
 # Input from file
704704
 echo "content" > "$TEST_DIR/input_test.txt"
705
-result=$("$FORTSH_BIN" -c 'cat < "'"$TEST_DIR"'/input_test.txt"' 2>&1)
705
+result=$("$SHELL_BIN" -c 'cat < "'"$TEST_DIR"'/input_test.txt"' 2>&1)
706706
 if [ "$result" = "content" ]; then
707707
     pass "Input redirection from file"
708708
 else
@@ -710,7 +710,7 @@ else
710710
 fi
711711
 
712712
 # Input from /dev/null
713
-result=$("$FORTSH_BIN" -c 'cat < /dev/null | wc -c' 2>&1)
713
+result=$("$SHELL_BIN" -c 'cat < /dev/null | wc -c' 2>&1)
714714
 if [ "$result" -eq 0 ] 2>/dev/null; then
715715
     pass "Input from /dev/null is empty"
716716
 else
@@ -722,7 +722,7 @@ section "456. OUTPUT TO /dev/null"
722722
 # =====================================
723723
 
724724
 # Stdout to /dev/null
725
-result=$("$FORTSH_BIN" -c 'echo hidden > /dev/null; echo visible' 2>&1)
725
+result=$("$SHELL_BIN" -c 'echo hidden > /dev/null; echo visible' 2>&1)
726726
 if [ "$result" = "visible" ]; then
727727
     pass "Stdout to /dev/null suppresses output"
728728
 else
@@ -730,7 +730,7 @@ else
730730
 fi
731731
 
732732
 # Stderr to /dev/null
733
-result=$("$FORTSH_BIN" -c 'ls /nonexistent 2>/dev/null; echo done' 2>&1)
733
+result=$("$SHELL_BIN" -c 'ls /nonexistent 2>/dev/null; echo done' 2>&1)
734734
 if [ "$result" = "done" ]; then
735735
     pass "Stderr to /dev/null suppresses errors"
736736
 else
@@ -738,7 +738,7 @@ else
738738
 fi
739739
 
740740
 # Both to /dev/null
741
-result=$("$FORTSH_BIN" -c 'ls /nonexistent >/dev/null 2>&1; echo status=$?' 2>&1)
741
+result=$("$SHELL_BIN" -c 'ls /nonexistent >/dev/null 2>&1; echo status=$?' 2>&1)
742742
 if echo "$result" | grep -q "status="; then
743743
     pass "Both stdout and stderr to /dev/null"
744744
 else
@@ -751,7 +751,7 @@ section "457. NOCLOBBER BEHAVIOR"
751751
 
752752
 # Normal overwrite
753753
 echo "old" > "$TEST_DIR/clobber_test.txt"
754
-result=$("$FORTSH_BIN" -c 'echo new > "'"$TEST_DIR"'/clobber_test.txt"; cat "'"$TEST_DIR"'/clobber_test.txt"' 2>&1)
754
+result=$("$SHELL_BIN" -c 'echo new > "'"$TEST_DIR"'/clobber_test.txt"; cat "'"$TEST_DIR"'/clobber_test.txt"' 2>&1)
755755
 if [ "$result" = "new" ]; then
756756
     pass "Normal > overwrites file"
757757
 else
@@ -763,7 +763,7 @@ section "458. COMPOUND REDIRECTIONS"
763763
 # =====================================
764764
 
765765
 # Redirect in if statement
766
-result=$("$FORTSH_BIN" -c 'if true; then echo yes; fi > "'"$TEST_DIR"'/if_redir.txt"; cat "'"$TEST_DIR"'/if_redir.txt"' 2>&1)
766
+result=$("$SHELL_BIN" -c 'if true; then echo yes; fi > "'"$TEST_DIR"'/if_redir.txt"; cat "'"$TEST_DIR"'/if_redir.txt"' 2>&1)
767767
 if [ "$result" = "yes" ]; then
768768
     pass "Redirect if statement output"
769769
 else
@@ -771,7 +771,7 @@ else
771771
 fi
772772
 
773773
 # Redirect in while loop
774
-result=$("$FORTSH_BIN" -c 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done > "'"$TEST_DIR"'/while_redir.txt"; wc -l < "'"$TEST_DIR"'/while_redir.txt"' 2>&1)
774
+result=$("$SHELL_BIN" -c 'i=0; while [ $i -lt 3 ]; do echo $i; i=$((i+1)); done > "'"$TEST_DIR"'/while_redir.txt"; wc -l < "'"$TEST_DIR"'/while_redir.txt"' 2>&1)
775775
 if [ "$result" -eq 3 ] 2>/dev/null; then
776776
     pass "Redirect while loop output"
777777
 else
@@ -779,7 +779,7 @@ else
779779
 fi
780780
 
781781
 # Redirect in for loop
782
-result=$("$FORTSH_BIN" -c 'for x in a b c; do echo $x; done > "'"$TEST_DIR"'/for_redir.txt"; wc -l < "'"$TEST_DIR"'/for_redir.txt"' 2>&1)
782
+result=$("$SHELL_BIN" -c 'for x in a b c; do echo $x; done > "'"$TEST_DIR"'/for_redir.txt"; wc -l < "'"$TEST_DIR"'/for_redir.txt"' 2>&1)
783783
 if [ "$result" -eq 3 ] 2>/dev/null; then
784784
     pass "Redirect for loop output"
785785
 else
@@ -791,14 +791,14 @@ section "459. PIPELINE EXIT STATUS"
791791
 # =====================================
792792
 
793793
 # Last command determines exit
794
-result=$("$FORTSH_BIN" -c 'true | false; echo $?' 2>&1)
794
+result=$("$SHELL_BIN" -c 'true | false; echo $?' 2>&1)
795795
 if [ "$result" = "1" ]; then
796796
     pass "Pipeline exit from last command (false)"
797797
 else
798798
     fail "Pipeline exit from last command (false)" "1" "$result"
799799
 fi
800800
 
801
-result=$("$FORTSH_BIN" -c 'false | true; echo $?' 2>&1)
801
+result=$("$SHELL_BIN" -c 'false | true; echo $?' 2>&1)
802802
 if [ "$result" = "0" ]; then
803803
     pass "Pipeline exit from last command (true)"
804804
 else
@@ -811,7 +811,7 @@ section "460. MULTIPLE REDIRECTIONS"
811811
 
812812
 # Both input and output
813813
 echo "input" > "$TEST_DIR/multi_in.txt"
814
-result=$("$FORTSH_BIN" -c 'cat < "'"$TEST_DIR"'/multi_in.txt" > "'"$TEST_DIR"'/multi_out.txt"; cat "'"$TEST_DIR"'/multi_out.txt"' 2>&1)
814
+result=$("$SHELL_BIN" -c 'cat < "'"$TEST_DIR"'/multi_in.txt" > "'"$TEST_DIR"'/multi_out.txt"; cat "'"$TEST_DIR"'/multi_out.txt"' 2>&1)
815815
 if [ "$result" = "input" ]; then
816816
     pass "Both input and output redirect"
817817
 else
@@ -819,7 +819,7 @@ else
819819
 fi
820820
 
821821
 # Order of redirections
822
-result=$("$FORTSH_BIN" -c 'echo test > "'"$TEST_DIR"'/order1.txt" 2>&1; cat "'"$TEST_DIR"'/order1.txt"' 2>&1)
822
+result=$("$SHELL_BIN" -c 'echo test > "'"$TEST_DIR"'/order1.txt" 2>&1; cat "'"$TEST_DIR"'/order1.txt"' 2>&1)
823823
 if [ "$result" = "test" ]; then
824824
     pass "Redirect order: > then 2>&1"
825825
 else
@@ -831,7 +831,7 @@ section "461. PIPELINE WITH SUBSHELL"
831831
 # =====================================
832832
 
833833
 # Subshell in pipeline
834
-result=$("$FORTSH_BIN" -c '(echo a; echo b) | wc -l' 2>&1)
834
+result=$("$SHELL_BIN" -c '(echo a; echo b) | wc -l' 2>&1)
835835
 if [ "$result" -eq 2 ] 2>/dev/null; then
836836
     pass "Subshell in pipeline"
837837
 else
@@ -839,7 +839,7 @@ else
839839
 fi
840840
 
841841
 # Brace group in pipeline
842
-result=$("$FORTSH_BIN" -c '{ echo x; echo y; } | wc -l' 2>&1)
842
+result=$("$SHELL_BIN" -c '{ echo x; echo y; } | wc -l' 2>&1)
843843
 if [ "$result" -eq 2 ] 2>/dev/null; then
844844
     pass "Brace group in pipeline"
845845
 else
@@ -851,7 +851,7 @@ section "462. REDIRECT AND PIPELINE COMBO"
851851
 # =====================================
852852
 
853853
 # Pipeline with final redirect
854
-result=$("$FORTSH_BIN" -c 'echo test | cat > "'"$TEST_DIR"'/pipe_redir.txt"; cat "'"$TEST_DIR"'/pipe_redir.txt"' 2>&1)
854
+result=$("$SHELL_BIN" -c 'echo test | cat > "'"$TEST_DIR"'/pipe_redir.txt"; cat "'"$TEST_DIR"'/pipe_redir.txt"' 2>&1)
855855
 if [ "$result" = "test" ]; then
856856
     pass "Pipeline with final redirect"
857857
 else
@@ -859,7 +859,7 @@ else
859859
 fi
860860
 
861861
 # Redirect within pipeline
862
-result=$("$FORTSH_BIN" -c 'echo test 2>/dev/null | cat' 2>&1)
862
+result=$("$SHELL_BIN" -c 'echo test 2>/dev/null | cat' 2>&1)
863863
 if [ "$result" = "test" ]; then
864864
     pass "Redirect within pipeline stage"
865865
 else
@@ -871,7 +871,7 @@ section "463. HERE STRING ALTERNATIVES"
871871
 # =====================================
872872
 
873873
 # Echo pipe as here-string alternative
874
-result=$("$FORTSH_BIN" -c 'echo "test" | cat' 2>&1)
874
+result=$("$SHELL_BIN" -c 'echo "test" | cat' 2>&1)
875875
 if [ "$result" = "test" ]; then
876876
     pass "Echo pipe as here-string alternative"
877877
 else
@@ -879,7 +879,7 @@ else
879879
 fi
880880
 
881881
 # Printf pipe
882
-result=$("$FORTSH_BIN" -c 'printf "%s" "test" | cat' 2>&1)
882
+result=$("$SHELL_BIN" -c 'printf "%s" "test" | cat' 2>&1)
883883
 if [ "$result" = "test" ]; then
884884
     pass "Printf pipe"
885885
 else
@@ -891,7 +891,7 @@ section "464. REDIRECTION EDGE CASES"
891891
 # =====================================
892892
 
893893
 # Redirect to same file
894
-result=$("$FORTSH_BIN" -c 'echo original > "'"$TEST_DIR"'/same.txt"; echo new > "'"$TEST_DIR"'/same.txt"; cat "'"$TEST_DIR"'/same.txt"' 2>&1)
894
+result=$("$SHELL_BIN" -c 'echo original > "'"$TEST_DIR"'/same.txt"; echo new > "'"$TEST_DIR"'/same.txt"; cat "'"$TEST_DIR"'/same.txt"' 2>&1)
895895
 if [ "$result" = "new" ]; then
896896
     pass "Multiple redirects to same file"
897897
 else
@@ -900,7 +900,7 @@ fi
900900
 
901901
 # Empty redirect (creates empty file)
902902
 rm -f "$TEST_DIR/empty_redir.txt"
903
-result=$("$FORTSH_BIN" -c '> "'"$TEST_DIR"'/empty_redir.txt"; [ -f "'"$TEST_DIR"'/empty_redir.txt" ] && echo exists' 2>&1)
903
+result=$("$SHELL_BIN" -c '> "'"$TEST_DIR"'/empty_redir.txt"; [ -f "'"$TEST_DIR"'/empty_redir.txt" ] && echo exists' 2>&1)
904904
 if [ "$result" = "exists" ]; then
905905
     pass "Empty redirect creates file"
906906
 else
@@ -912,7 +912,7 @@ section "465. TPYE WITH REDIRECTION"
912912
 # =====================================
913913
 
914914
 # Pipeline preserves data integrity
915
-result=$("$FORTSH_BIN" -c 'echo "hello world" | cat | cat | cat' 2>&1)
915
+result=$("$SHELL_BIN" -c 'echo "hello world" | cat | cat | cat' 2>&1)
916916
 if [ "$result" = "hello world" ]; then
917917
     pass "Pipeline preserves data integrity"
918918
 else
@@ -920,7 +920,7 @@ else
920920
 fi
921921
 
922922
 # Multiple pipes with tr
923
-result=$("$FORTSH_BIN" -c 'echo abc | tr a X | tr b Y | tr c Z' 2>&1)
923
+result=$("$SHELL_BIN" -c 'echo abc | tr a X | tr b Y | tr c Z' 2>&1)
924924
 if [ "$result" = "XYZ" ]; then
925925
     pass "Multiple pipes with tr"
926926
 else
suites/posix/posix_compliance_special.shmodified
1116 lines changed — click to load
@@ -24,12 +24,12 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 
2929
 # Check if fortsh exists
30
-if [ ! -x "$FORTSH_BIN" ]; then
31
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
+if [ ! -x "$SHELL_BIN" ]; then
31
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
32
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3333
     exit 1
3434
 fi
3535
 
@@ -74,7 +74,7 @@ section "358. SPECIAL VARIABLE LINENO"
7474
 # =====================================
7575
 
7676
 # LINENO in simple script
77
-result=$("$FORTSH_BIN" -c 'echo $LINENO' 2>&1)
77
+result=$("$SHELL_BIN" -c 'echo $LINENO' 2>&1)
7878
 if [ "$result" = "1" ]; then
7979
     pass "LINENO is 1 on first line"
8080
 else
@@ -82,7 +82,7 @@ else
8282
 fi
8383
 
8484
 # LINENO increments
85
-result=$("$FORTSH_BIN" -c '
85
+result=$("$SHELL_BIN" -c '
8686
 echo $LINENO
8787
 echo $LINENO
8888
 echo $LINENO
@@ -94,7 +94,7 @@ else
9494
 fi
9595
 
9696
 # LINENO in function
97
-result=$("$FORTSH_BIN" -c '
97
+result=$("$SHELL_BIN" -c '
9898
 func() {
9999
     echo $LINENO
100100
 }
@@ -111,7 +111,7 @@ section "359. SPECIAL VARIABLE PPID"
111111
 # =====================================
112112
 
113113
 # PPID is set
114
-result=$("$FORTSH_BIN" -c 'echo $PPID' 2>&1)
114
+result=$("$SHELL_BIN" -c 'echo $PPID' 2>&1)
115115
 if [ -n "$result" ] && [ "$result" -gt 0 ] 2>/dev/null; then
116116
     pass "PPID is set to positive number"
117117
 else
@@ -120,7 +120,7 @@ fi
120120
 
121121
 # PPID matches parent
122122
 parent_pid=$$
123
-result=$("$FORTSH_BIN" -c 'echo $PPID' 2>&1)
123
+result=$("$SHELL_BIN" -c 'echo $PPID' 2>&1)
124124
 # PPID should be reasonable (not 0 or 1 unless running as init)
125125
 if [ "$result" -gt 1 ] 2>/dev/null; then
126126
     pass "PPID is reasonable value"
@@ -129,7 +129,7 @@ else
129129
 fi
130130
 
131131
 # PPID is readonly conceptually (cannot be assigned)
132
-result=$("$FORTSH_BIN" -c 'PPID=999; echo $PPID' 2>&1)
132
+result=$("$SHELL_BIN" -c 'PPID=999; echo $PPID' 2>&1)
133133
 if [ "$result" != "999" ]; then
134134
     pass "PPID cannot be overwritten"
135135
 else
@@ -141,12 +141,12 @@ section "360. FILE DESCRIPTOR 3-9"
141141
 # =====================================
142142
 
143143
 # FD 3 redirect out
144
-result=$("$FORTSH_BIN" -c 'echo hello 3>/tmp/fd3test_$$; cat /tmp/fd3test_$$; rm -f /tmp/fd3test_$$' 2>&1)
144
+result=$("$SHELL_BIN" -c 'echo hello 3>/tmp/fd3test_$$; cat /tmp/fd3test_$$; rm -f /tmp/fd3test_$$' 2>&1)
145145
 # This might not output to fd3 without explicit redirect
146146
 pass "FD 3 redirect syntax accepted"
147147
 
148148
 # FD 3 redirect with exec
149
-result=$("$FORTSH_BIN" -c '
149
+result=$("$SHELL_BIN" -c '
150150
 exec 3>/tmp/fd3exec_$$
151151
 echo "fd3 output" >&3
152152
 exec 3>&-
@@ -160,7 +160,7 @@ else
160160
 fi
161161
 
162162
 # FD 4 usage
163
-result=$("$FORTSH_BIN" -c '
163
+result=$("$SHELL_BIN" -c '
164164
 exec 4>/tmp/fd4test_$$
165165
 echo "fd4 data" >&4
166166
 exec 4>&-
@@ -174,7 +174,7 @@ else
174174
 fi
175175
 
176176
 # Multiple FDs
177
-result=$("$FORTSH_BIN" -c '
177
+result=$("$SHELL_BIN" -c '
178178
 exec 3>/tmp/fd3m_$$ 4>/tmp/fd4m_$$
179179
 echo "three" >&3
180180
 echo "four" >&4
@@ -193,7 +193,7 @@ section "361. COLON BUILTIN"
193193
 # =====================================
194194
 
195195
 # Colon is no-op, returns 0
196
-result=$("$FORTSH_BIN" -c ':; echo $?' 2>&1)
196
+result=$("$SHELL_BIN" -c ':; echo $?' 2>&1)
197197
 if [ "$result" = "0" ]; then
198198
     pass ": returns exit status 0"
199199
 else
@@ -201,7 +201,7 @@ else
201201
 fi
202202
 
203203
 # Colon with arguments (ignored)
204
-result=$("$FORTSH_BIN" -c ': arg1 arg2 arg3; echo $?' 2>&1)
204
+result=$("$SHELL_BIN" -c ': arg1 arg2 arg3; echo $?' 2>&1)
205205
 if [ "$result" = "0" ]; then
206206
     pass ": ignores arguments"
207207
 else
@@ -209,7 +209,7 @@ else
209209
 fi
210210
 
211211
 # Colon with variable expansion (expansion happens but result ignored)
212
-result=$("$FORTSH_BIN" -c 'x=1; : $((x=x+1)); echo $x' 2>&1)
212
+result=$("$SHELL_BIN" -c 'x=1; : $((x=x+1)); echo $x' 2>&1)
213213
 if [ "$result" = "2" ]; then
214214
     pass ": performs expansions but ignores result"
215215
 else
@@ -217,7 +217,7 @@ else
217217
 fi
218218
 
219219
 # Colon in conditional
220
-result=$("$FORTSH_BIN" -c 'if :; then echo yes; fi' 2>&1)
220
+result=$("$SHELL_BIN" -c 'if :; then echo yes; fi' 2>&1)
221221
 if [ "$result" = "yes" ]; then
222222
     pass ": works in if condition"
223223
 else
@@ -225,7 +225,7 @@ else
225225
 fi
226226
 
227227
 # Colon in while (infinite loop prevention test)
228
-result=$("$FORTSH_BIN" -c 'n=0; while :; do n=$((n+1)); [ $n -ge 3 ] && break; done; echo $n' 2>&1)
228
+result=$("$SHELL_BIN" -c 'n=0; while :; do n=$((n+1)); [ $n -ge 3 ] && break; done; echo $n' 2>&1)
229229
 if [ "$result" = "3" ]; then
230230
     pass ": works in while loop"
231231
 else
@@ -237,7 +237,7 @@ section "362. COMPOUND COMMAND NESTING"
237237
 # =====================================
238238
 
239239
 # Nested subshells
240
-result=$("$FORTSH_BIN" -c 'echo $(echo $(echo deep))' 2>&1)
240
+result=$("$SHELL_BIN" -c 'echo $(echo $(echo deep))' 2>&1)
241241
 if [ "$result" = "deep" ]; then
242242
     pass "Triple nested command substitution"
243243
 else
@@ -245,7 +245,7 @@ else
245245
 fi
246246
 
247247
 # Nested braces
248
-result=$("$FORTSH_BIN" -c '{ { { echo nested; }; }; }' 2>&1)
248
+result=$("$SHELL_BIN" -c '{ { { echo nested; }; }; }' 2>&1)
249249
 if [ "$result" = "nested" ]; then
250250
     pass "Triple nested brace groups"
251251
 else
@@ -253,7 +253,7 @@ else
253253
 fi
254254
 
255255
 # Mixed nesting
256
-result=$("$FORTSH_BIN" -c '{ x=$(echo inner); echo $x; }' 2>&1)
256
+result=$("$SHELL_BIN" -c '{ x=$(echo inner); echo $x; }' 2>&1)
257257
 if [ "$result" = "inner" ]; then
258258
     pass "Command substitution in brace group"
259259
 else
@@ -261,7 +261,7 @@ else
261261
 fi
262262
 
263263
 # Nested loops
264
-result=$("$FORTSH_BIN" -c '
264
+result=$("$SHELL_BIN" -c '
265265
 for i in 1 2; do
266266
     for j in a b; do
267267
         echo "$i$j"
@@ -279,14 +279,14 @@ section "363. COMPLEX PARAMETER EXPANSION"
279279
 # =====================================
280280
 
281281
 # Nested parameter expansion
282
-result=$("$FORTSH_BIN" -c 'x=hello; y=${x:-${z:-default}}; echo $y' 2>&1)
282
+result=$("$SHELL_BIN" -c 'x=hello; y=${x:-${z:-default}}; echo $y' 2>&1)
283283
 if [ "$result" = "hello" ]; then
284284
     pass "Nested default expansion (first set)"
285285
 else
286286
     fail "Nested default expansion (first set)" "hello" "$result"
287287
 fi
288288
 
289
-result=$("$FORTSH_BIN" -c 'unset x; y=${x:-${z:-default}}; echo $y' 2>&1)
289
+result=$("$SHELL_BIN" -c 'unset x; y=${x:-${z:-default}}; echo $y' 2>&1)
290290
 if [ "$result" = "default" ]; then
291291
     pass "Nested default expansion (fallback to nested)"
292292
 else
@@ -294,7 +294,7 @@ else
294294
 fi
295295
 
296296
 # Length of expansion result
297
-result=$("$FORTSH_BIN" -c 'x=hello; echo ${#x}' 2>&1)
297
+result=$("$SHELL_BIN" -c 'x=hello; echo ${#x}' 2>&1)
298298
 if [ "$result" = "5" ]; then
299299
     pass "Length of variable"
300300
 else
@@ -302,7 +302,7 @@ else
302302
 fi
303303
 
304304
 # Pattern removal chained
305
-result=$("$FORTSH_BIN" -c 'x="/path/to/file.txt"; y=${x##*/}; z=${y%.*}; echo $z' 2>&1)
305
+result=$("$SHELL_BIN" -c 'x="/path/to/file.txt"; y=${x##*/}; z=${y%.*}; echo $z' 2>&1)
306306
 if [ "$result" = "file" ]; then
307307
     pass "Chained pattern removal"
308308
 else
@@ -314,7 +314,7 @@ section "364. SPECIAL EXPANSION CONTEXTS"
314314
 # =====================================
315315
 
316316
 # Expansion in here-document
317
-result=$("$FORTSH_BIN" -c 'x=VALUE; cat <<EOF
317
+result=$("$SHELL_BIN" -c 'x=VALUE; cat <<EOF
318318
 $x
319319
 EOF' 2>&1)
320320
 if [ "$result" = "VALUE" ]; then
@@ -324,7 +324,7 @@ else
324324
 fi
325325
 
326326
 # No expansion in quoted heredoc
327
-result=$("$FORTSH_BIN" -c "x=VALUE; cat <<'EOF'
327
+result=$("$SHELL_BIN" -c "x=VALUE; cat <<'EOF'
328328
 \$x
329329
 EOF" 2>&1)
330330
 if [ "$result" = '$x' ]; then
@@ -334,7 +334,7 @@ else
334334
 fi
335335
 
336336
 # Expansion in case pattern
337
-result=$("$FORTSH_BIN" -c 'pat="hel*"; case "hello" in $pat) echo match;; esac' 2>&1)
337
+result=$("$SHELL_BIN" -c 'pat="hel*"; case "hello" in $pat) echo match;; esac' 2>&1)
338338
 if [ "$result" = "match" ]; then
339339
     pass "Variable expansion in case pattern"
340340
 else
@@ -346,7 +346,7 @@ section "365. ARITHMETIC EDGE CASES"
346346
 # =====================================
347347
 
348348
 # Unary minus
349
-result=$("$FORTSH_BIN" -c 'echo $((-5))' 2>&1)
349
+result=$("$SHELL_BIN" -c 'echo $((-5))' 2>&1)
350350
 if [ "$result" = "-5" ]; then
351351
     pass "Unary minus in arithmetic"
352352
 else
@@ -354,7 +354,7 @@ else
354354
 fi
355355
 
356356
 # Unary plus
357
-result=$("$FORTSH_BIN" -c 'echo $((+5))' 2>&1)
357
+result=$("$SHELL_BIN" -c 'echo $((+5))' 2>&1)
358358
 if [ "$result" = "5" ]; then
359359
     pass "Unary plus in arithmetic"
360360
 else
@@ -362,14 +362,14 @@ else
362362
 fi
363363
 
364364
 # Logical NOT
365
-result=$("$FORTSH_BIN" -c 'echo $((!0))' 2>&1)
365
+result=$("$SHELL_BIN" -c 'echo $((!0))' 2>&1)
366366
 if [ "$result" = "1" ]; then
367367
     pass "Logical NOT of 0"
368368
 else
369369
     fail "Logical NOT of 0" "1" "$result"
370370
 fi
371371
 
372
-result=$("$FORTSH_BIN" -c 'echo $((!1))' 2>&1)
372
+result=$("$SHELL_BIN" -c 'echo $((!1))' 2>&1)
373373
 if [ "$result" = "0" ]; then
374374
     pass "Logical NOT of 1"
375375
 else
@@ -377,7 +377,7 @@ else
377377
 fi
378378
 
379379
 # Bitwise NOT
380
-result=$("$FORTSH_BIN" -c 'echo $((~0))' 2>&1)
380
+result=$("$SHELL_BIN" -c 'echo $((~0))' 2>&1)
381381
 if [ "$result" = "-1" ]; then
382382
     pass "Bitwise NOT of 0"
383383
 else
@@ -385,7 +385,7 @@ else
385385
 fi
386386
 
387387
 # Complex expression
388
-result=$("$FORTSH_BIN" -c 'echo $(( (2 + 3) * 4 - 1 ))' 2>&1)
388
+result=$("$SHELL_BIN" -c 'echo $(( (2 + 3) * 4 - 1 ))' 2>&1)
389389
 if [ "$result" = "19" ]; then
390390
     pass "Complex arithmetic with parens"
391391
 else
@@ -397,7 +397,7 @@ section "366. SIGNAL NAME HANDLING"
397397
 # =====================================
398398
 
399399
 # trap with signal name
400
-result=$("$FORTSH_BIN" -c 'trap "echo caught" INT; trap' 2>&1)
400
+result=$("$SHELL_BIN" -c 'trap "echo caught" INT; trap' 2>&1)
401401
 if echo "$result" | grep -qE "INT|SIGINT"; then
402402
     pass "trap accepts signal name"
403403
 else
@@ -405,7 +405,7 @@ else
405405
 fi
406406
 
407407
 # trap with signal number
408
-result=$("$FORTSH_BIN" -c 'trap "echo caught" 2; trap' 2>&1)
408
+result=$("$SHELL_BIN" -c 'trap "echo caught" 2; trap' 2>&1)
409409
 if echo "$result" | grep -qE "INT|SIGINT|2"; then
410410
     pass "trap accepts signal number"
411411
 else
@@ -413,7 +413,7 @@ else
413413
 fi
414414
 
415415
 # Multiple signals
416
-result=$("$FORTSH_BIN" -c 'trap "echo exit" EXIT; trap "echo int" INT; trap' 2>&1)
416
+result=$("$SHELL_BIN" -c 'trap "echo exit" EXIT; trap "echo int" INT; trap' 2>&1)
417417
 if echo "$result" | grep -qE "EXIT|exit" && echo "$result" | grep -qE "INT|SIGINT"; then
418418
     pass "trap with multiple signals"
419419
 else
@@ -425,7 +425,7 @@ section "367. QUOTING EDGE CASES"
425425
 # =====================================
426426
 
427427
 # Single quotes preserve everything
428
-result=$("$FORTSH_BIN" -c "echo 'hello\nworld'" 2>&1)
428
+result=$("$SHELL_BIN" -c "echo 'hello\nworld'" 2>&1)
429429
 if [ "$result" = 'hello\nworld' ]; then
430430
     pass "Single quotes preserve backslash-n literally"
431431
 else
@@ -433,7 +433,7 @@ else
433433
 fi
434434
 
435435
 # Empty string quoting
436
-result=$("$FORTSH_BIN" -c 'echo "" | wc -c' 2>&1)
436
+result=$("$SHELL_BIN" -c 'echo "" | wc -c' 2>&1)
437437
 # Empty string should produce just newline from echo
438438
 result_trimmed=$(echo "$result" | tr -d ' ')
439439
 if [ "$result_trimmed" = "1" ]; then
@@ -443,12 +443,12 @@ else
443443
 fi
444444
 
445445
 # Quote within quote
446
-result=$("$FORTSH_BIN" -c "echo \"it'\"'\"'s\"" 2>&1)
446
+result=$("$SHELL_BIN" -c "echo \"it'\"'\"'s\"" 2>&1)
447447
 # This is tricky - mixing quote styles
448448
 pass "Mixed quote styles accepted"
449449
 
450450
 # Escaped quote in double quotes
451
-result=$("$FORTSH_BIN" -c 'echo "say \"hello\""' 2>&1)
451
+result=$("$SHELL_BIN" -c 'echo "say \"hello\""' 2>&1)
452452
 if [ "$result" = 'say "hello"' ]; then
453453
     pass "Escaped quotes in double quotes"
454454
 else
@@ -460,7 +460,7 @@ section "368. WORD SPLITTING EDGE CASES"
460460
 # =====================================
461461
 
462462
 # Empty IFS prevents splitting
463
-result=$("$FORTSH_BIN" -c 'IFS=""; x="a b c"; set -- $x; echo $#' 2>&1)
463
+result=$("$SHELL_BIN" -c 'IFS=""; x="a b c"; set -- $x; echo $#' 2>&1)
464464
 if [ "$result" = "1" ]; then
465465
     pass "Empty IFS prevents word splitting"
466466
 else
@@ -468,7 +468,7 @@ else
468468
 fi
469469
 
470470
 # IFS with multiple characters
471
-result=$("$FORTSH_BIN" -c 'IFS=":,"; x="a:b,c"; set -- $x; echo $#' 2>&1)
471
+result=$("$SHELL_BIN" -c 'IFS=":,"; x="a:b,c"; set -- $x; echo $#' 2>&1)
472472
 if [ "$result" = "3" ]; then
473473
     pass "IFS with multiple delimiters"
474474
 else
@@ -476,7 +476,7 @@ else
476476
 fi
477477
 
478478
 # Default IFS restoration
479
-result=$("$FORTSH_BIN" -c 'IFS=":"; x="a:b"; set -- $x; unset IFS; y="c d"; set -- $y; echo $#' 2>&1)
479
+result=$("$SHELL_BIN" -c 'IFS=":"; x="a:b"; set -- $x; unset IFS; y="c d"; set -- $y; echo $#' 2>&1)
480480
 if [ "$result" = "2" ]; then
481481
     pass "unset IFS restores default splitting"
482482
 else
@@ -489,7 +489,7 @@ section "369. $$ IN SUBSHELLS"
489489
 
490490
 # $$ in subshell should return parent shell PID per POSIX
491491
 # Test within SAME shell instance (not separate invocations)
492
-result=$("$FORTSH_BIN" -c 'echo $$; (echo $$)' 2>&1)
492
+result=$("$SHELL_BIN" -c 'echo $$; (echo $$)' 2>&1)
493493
 parent_pid=$(echo "$result" | sed -n '1p')
494494
 subshell_pid=$(echo "$result" | sed -n '2p')
495495
 if [ "$parent_pid" = "$subshell_pid" ]; then
@@ -499,7 +499,7 @@ else
499499
 fi
500500
 
501501
 # $$ in command substitution
502
-result=$("$FORTSH_BIN" -c 'echo $$ $(echo $$)' 2>&1)
502
+result=$("$SHELL_BIN" -c 'echo $$ $(echo $$)' 2>&1)
503503
 # Both should be the same PID
504504
 pid1=$(echo "$result" | awk '{print $1}')
505505
 pid2=$(echo "$result" | awk '{print $2}')
@@ -510,7 +510,7 @@ else
510510
 fi
511511
 
512512
 # $$ is numeric
513
-result=$("$FORTSH_BIN" -c 'echo $$' 2>&1)
513
+result=$("$SHELL_BIN" -c 'echo $$' 2>&1)
514514
 if [ "$result" -gt 0 ] 2>/dev/null; then
515515
     pass "\$\$ is positive integer"
516516
 else
@@ -522,7 +522,7 @@ section "370. \$@ VS \$* DIFFERENCES"
522522
 # =====================================
523523
 
524524
 # $@ preserves separate arguments
525
-result=$("$FORTSH_BIN" -c 'set -- "a b" "c d"; for x in "$@"; do echo "[$x]"; done' 2>&1)
525
+result=$("$SHELL_BIN" -c 'set -- "a b" "c d"; for x in "$@"; do echo "[$x]"; done' 2>&1)
526526
 expected=$(printf "[a b]\n[c d]")
527527
 if [ "$result" = "$expected" ]; then
528528
     pass '"\$@" preserves argument boundaries'
@@ -531,7 +531,7 @@ else
531531
 fi
532532
 
533533
 # $* joins with IFS
534
-result=$("$FORTSH_BIN" -c 'IFS=":"; set -- a b c; echo "$*"' 2>&1)
534
+result=$("$SHELL_BIN" -c 'IFS=":"; set -- a b c; echo "$*"' 2>&1)
535535
 if [ "$result" = "a:b:c" ]; then
536536
     pass '"\$*" joins with first char of IFS'
537537
 else
@@ -539,7 +539,7 @@ else
539539
 fi
540540
 
541541
 # $@ unquoted splits
542
-result=$("$FORTSH_BIN" -c 'set -- "a b" "c d"; for x in $@; do echo "[$x]"; done' 2>&1)
542
+result=$("$SHELL_BIN" -c 'set -- "a b" "c d"; for x in $@; do echo "[$x]"; done' 2>&1)
543543
 # Should split into 4 words: a, b, c, d
544544
 expected=$(printf "[a]\n[b]\n[c]\n[d]")
545545
 if [ "$result" = "$expected" ]; then
@@ -549,7 +549,7 @@ else
549549
 fi
550550
 
551551
 # Empty $@ produces nothing
552
-result=$("$FORTSH_BIN" -c 'set --; for x in "$@"; do echo X; done; echo done' 2>&1)
552
+result=$("$SHELL_BIN" -c 'set --; for x in "$@"; do echo X; done; echo done' 2>&1)
553553
 if [ "$result" = "done" ]; then
554554
     pass 'Empty "$@" produces no iterations'
555555
 else
@@ -557,7 +557,7 @@ else
557557
 fi
558558
 
559559
 # $# count
560
-result=$("$FORTSH_BIN" -c 'set -- a b c d e; echo $#' 2>&1)
560
+result=$("$SHELL_BIN" -c 'set -- a b c d e; echo $#' 2>&1)
561561
 if [ "$result" = "5" ]; then
562562
     pass '$# counts positional parameters'
563563
 else
@@ -569,7 +569,7 @@ section "371. PWD AND OLDPWD"
569569
 # =====================================
570570
 
571571
 # PWD is set
572
-result=$("$FORTSH_BIN" -c 'echo $PWD' 2>&1)
572
+result=$("$SHELL_BIN" -c 'echo $PWD' 2>&1)
573573
 if [ -n "$result" ] && [ -d "$result" ]; then
574574
     pass "PWD is set to valid directory"
575575
 else
@@ -577,7 +577,7 @@ else
577577
 fi
578578
 
579579
 # cd updates PWD
580
-result=$("$FORTSH_BIN" -c 'cd /tmp && echo $PWD' 2>&1)
580
+result=$("$SHELL_BIN" -c 'cd /tmp && echo $PWD' 2>&1)
581581
 if echo "$result" | grep -q "tmp"; then
582582
     pass "cd updates PWD"
583583
 else
@@ -585,7 +585,7 @@ else
585585
 fi
586586
 
587587
 # cd updates OLDPWD
588
-result=$("$FORTSH_BIN" -c 'cd /; cd /tmp; echo $OLDPWD' 2>&1)
588
+result=$("$SHELL_BIN" -c 'cd /; cd /tmp; echo $OLDPWD' 2>&1)
589589
 if [ "$result" = "/" ]; then
590590
     pass "cd updates OLDPWD"
591591
 else
@@ -593,7 +593,7 @@ else
593593
 fi
594594
 
595595
 # cd - uses OLDPWD
596
-result=$("$FORTSH_BIN" -c 'cd /; cd /tmp; cd -' 2>&1)
596
+result=$("$SHELL_BIN" -c 'cd /; cd /tmp; cd -' 2>&1)
597597
 if echo "$result" | grep -q "/"; then
598598
     pass "cd - prints previous directory"
599599
 else
@@ -605,7 +605,7 @@ section "372. \$? EXIT STATUS"
605605
 # =====================================
606606
 
607607
 # $? after successful command
608
-result=$("$FORTSH_BIN" -c 'true; echo $?' 2>&1)
608
+result=$("$SHELL_BIN" -c 'true; echo $?' 2>&1)
609609
 if [ "$result" = "0" ]; then
610610
     pass '$? is 0 after true'
611611
 else
@@ -613,7 +613,7 @@ else
613613
 fi
614614
 
615615
 # $? after failed command
616
-result=$("$FORTSH_BIN" -c 'false; echo $?' 2>&1)
616
+result=$("$SHELL_BIN" -c 'false; echo $?' 2>&1)
617617
 if [ "$result" = "1" ]; then
618618
     pass '$? is 1 after false'
619619
 else
@@ -621,7 +621,7 @@ else
621621
 fi
622622
 
623623
 # $? after exit N
624
-result=$("$FORTSH_BIN" -c '(exit 42); echo $?' 2>&1)
624
+result=$("$SHELL_BIN" -c '(exit 42); echo $?' 2>&1)
625625
 if [ "$result" = "42" ]; then
626626
     pass '$? captures exit code from subshell'
627627
 else
@@ -629,7 +629,7 @@ else
629629
 fi
630630
 
631631
 # $? after signal (128+signal)
632
-result=$("$FORTSH_BIN" -c 'sh -c "kill -9 \$\$" 2>/dev/null; echo $?' 2>&1)
632
+result=$("$SHELL_BIN" -c 'sh -c "kill -9 \$\$" 2>/dev/null; echo $?' 2>&1)
633633
 if [ "$result" -ge 128 ] 2>/dev/null; then
634634
     pass '$? is 128+ after signal death'
635635
 else
@@ -637,7 +637,7 @@ else
637637
 fi
638638
 
639639
 # $? after command not found
640
-result=$("$FORTSH_BIN" -c 'nonexistent_cmd_xyz_12345 2>/dev/null; echo $?' 2>&1)
640
+result=$("$SHELL_BIN" -c 'nonexistent_cmd_xyz_12345 2>/dev/null; echo $?' 2>&1)
641641
 if [ "$result" = "127" ]; then
642642
     pass '$? is 127 for command not found'
643643
 else
@@ -649,7 +649,7 @@ section "373. \$0 SCRIPT NAME"
649649
 # =====================================
650650
 
651651
 # $0 in -c command
652
-result=$("$FORTSH_BIN" -c 'echo $0' 2>&1)
652
+result=$("$SHELL_BIN" -c 'echo $0' 2>&1)
653653
 if [ -n "$result" ]; then
654654
     pass '$0 is set in -c command'
655655
 else
@@ -657,7 +657,7 @@ else
657657
 fi
658658
 
659659
 # $0 can be set with -c
660
-result=$("$FORTSH_BIN" -c 'echo $0' myname 2>&1)
660
+result=$("$SHELL_BIN" -c 'echo $0' myname 2>&1)
661661
 if [ "$result" = "myname" ]; then
662662
     pass '$0 can be set via argument after -c'
663663
 else
@@ -669,7 +669,7 @@ section "374. SHIFT EDGE CASES"
669669
 # =====================================
670670
 
671671
 # shift removes first positional param
672
-result=$("$FORTSH_BIN" -c 'set -- a b c; shift; echo $1' 2>&1)
672
+result=$("$SHELL_BIN" -c 'set -- a b c; shift; echo $1' 2>&1)
673673
 if [ "$result" = "b" ]; then
674674
     pass 'shift removes first parameter'
675675
 else
@@ -677,7 +677,7 @@ else
677677
 fi
678678
 
679679
 # shift N removes N params
680
-result=$("$FORTSH_BIN" -c 'set -- a b c d e; shift 2; echo $1' 2>&1)
680
+result=$("$SHELL_BIN" -c 'set -- a b c d e; shift 2; echo $1' 2>&1)
681681
 if [ "$result" = "c" ]; then
682682
     pass 'shift N removes N parameters'
683683
 else
@@ -685,7 +685,7 @@ else
685685
 fi
686686
 
687687
 # shift updates $#
688
-result=$("$FORTSH_BIN" -c 'set -- a b c d e; shift 3; echo $#' 2>&1)
688
+result=$("$SHELL_BIN" -c 'set -- a b c d e; shift 3; echo $#' 2>&1)
689689
 if [ "$result" = "2" ]; then
690690
     pass 'shift updates $#'
691691
 else
@@ -693,7 +693,7 @@ else
693693
 fi
694694
 
695695
 # shift more than $# fails
696
-result=$("$FORTSH_BIN" -c 'set -- a b; shift 5 2>/dev/null; echo $?' 2>&1)
696
+result=$("$SHELL_BIN" -c 'set -- a b; shift 5 2>/dev/null; echo $?' 2>&1)
697697
 if [ "$result" != "0" ]; then
698698
     pass 'shift beyond $# returns non-zero'
699699
 else
@@ -705,7 +705,7 @@ section "375. ENVIRONMENT VARIABLES"
705705
 # =====================================
706706
 
707707
 # HOME is set
708
-result=$("$FORTSH_BIN" -c 'echo $HOME' 2>&1)
708
+result=$("$SHELL_BIN" -c 'echo $HOME' 2>&1)
709709
 if [ -n "$result" ] && [ -d "$result" ]; then
710710
     pass "HOME is set to valid directory"
711711
 else
@@ -713,7 +713,7 @@ else
713713
 fi
714714
 
715715
 # PATH is set
716
-result=$("$FORTSH_BIN" -c 'echo $PATH' 2>&1)
716
+result=$("$SHELL_BIN" -c 'echo $PATH' 2>&1)
717717
 if [ -n "$result" ]; then
718718
     pass "PATH is set"
719719
 else
@@ -722,7 +722,7 @@ fi
722722
 
723723
 # PATH affects command lookup - use actual system paths
724724
 LS_DIR=$(dirname "$(which ls 2>/dev/null)")
725
-result=$("$FORTSH_BIN" -c "PATH=$LS_DIR; ls / >/dev/null 2>&1; echo \$?" 2>&1)
725
+result=$("$SHELL_BIN" -c "PATH=$LS_DIR; ls / >/dev/null 2>&1; echo \$?" 2>&1)
726726
 if [ "$result" = "0" ]; then
727727
     pass "PATH affects command resolution"
728728
 else
@@ -730,7 +730,7 @@ else
730730
 fi
731731
 
732732
 # Empty PATH means current directory only
733
-result=$("$FORTSH_BIN" -c 'PATH=""; ls / 2>/dev/null; echo $?' 2>&1)
733
+result=$("$SHELL_BIN" -c 'PATH=""; ls / 2>/dev/null; echo $?' 2>&1)
734734
 if [ "$result" != "0" ]; then
735735
     pass "Empty PATH prevents finding commands"
736736
 else
@@ -742,7 +742,7 @@ section "376. EVAL SPECIAL CASES"
742742
 # =====================================
743743
 
744744
 # eval with variable containing command
745
-result=$("$FORTSH_BIN" -c 'cmd="echo hello"; eval "$cmd"' 2>&1)
745
+result=$("$SHELL_BIN" -c 'cmd="echo hello"; eval "$cmd"' 2>&1)
746746
 if [ "$result" = "hello" ]; then
747747
     pass "eval executes command in variable"
748748
 else
@@ -750,7 +750,7 @@ else
750750
 fi
751751
 
752752
 # eval with multiple arguments
753
-result=$("$FORTSH_BIN" -c 'eval echo hello world' 2>&1)
753
+result=$("$SHELL_BIN" -c 'eval echo hello world' 2>&1)
754754
 if [ "$result" = "hello world" ]; then
755755
     pass "eval concatenates arguments"
756756
 else
@@ -758,7 +758,7 @@ else
758758
 fi
759759
 
760760
 # eval with variable expansion
761
-result=$("$FORTSH_BIN" -c 'x=y; y=z; eval echo \$$x' 2>&1)
761
+result=$("$SHELL_BIN" -c 'x=y; y=z; eval echo \$$x' 2>&1)
762762
 if [ "$result" = "z" ]; then
763763
     pass "eval performs double expansion"
764764
 else
@@ -766,7 +766,7 @@ else
766766
 fi
767767
 
768768
 # eval exit status
769
-result=$("$FORTSH_BIN" -c 'eval false; echo $?' 2>&1)
769
+result=$("$SHELL_BIN" -c 'eval false; echo $?' 2>&1)
770770
 if [ "$result" = "1" ]; then
771771
     pass "eval returns command exit status"
772772
 else
@@ -778,7 +778,7 @@ section "377. COMMAND EXECUTION MODES"
778778
 # =====================================
779779
 
780780
 # Command with -c flag
781
-result=$("$FORTSH_BIN" -c 'echo test' 2>&1)
781
+result=$("$SHELL_BIN" -c 'echo test' 2>&1)
782782
 if [ "$result" = "test" ]; then
783783
     pass "fortsh -c executes command"
784784
 else
@@ -786,7 +786,7 @@ else
786786
 fi
787787
 
788788
 # Command with environment var
789
-result=$(X=value "$FORTSH_BIN" -c 'echo $X' 2>&1)
789
+result=$(X=value "$SHELL_BIN" -c 'echo $X' 2>&1)
790790
 if [ "$result" = "value" ]; then
791791
     pass "env var passed to fortsh"
792792
 else
@@ -798,7 +798,7 @@ section "378. SPECIAL BUILTIN BEHAVIORS"
798798
 # =====================================
799799
 
800800
 # break outside loop
801
-result=$("$FORTSH_BIN" -c 'break 2>/dev/null; echo $?' 2>&1)
801
+result=$("$SHELL_BIN" -c 'break 2>/dev/null; echo $?' 2>&1)
802802
 if echo "$result" | grep -qE '^[0-9]'; then
803803
     pass "break outside loop returns error status"
804804
 else
@@ -806,7 +806,7 @@ else
806806
 fi
807807
 
808808
 # continue outside loop
809
-result=$("$FORTSH_BIN" -c 'continue 2>/dev/null; echo $?' 2>&1)
809
+result=$("$SHELL_BIN" -c 'continue 2>/dev/null; echo $?' 2>&1)
810810
 if echo "$result" | grep -qE '^[0-9]'; then
811811
     pass "continue outside loop returns error status"
812812
 else
@@ -814,7 +814,7 @@ else
814814
 fi
815815
 
816816
 # return outside function
817
-result=$("$FORTSH_BIN" -c 'return 2>/dev/null; echo $?' 2>&1)
817
+result=$("$SHELL_BIN" -c 'return 2>/dev/null; echo $?' 2>&1)
818818
 if echo "$result" | grep -qE '^[0-9]'; then
819819
     pass "return outside function handled"
820820
 else
@@ -826,7 +826,7 @@ section "379. REDIRECTION EDGE CASES"
826826
 # =====================================
827827
 
828828
 # Redirect to /dev/null
829
-result=$("$FORTSH_BIN" -c 'echo test > /dev/null; echo done' 2>&1)
829
+result=$("$SHELL_BIN" -c 'echo test > /dev/null; echo done' 2>&1)
830830
 if [ "$result" = "done" ]; then
831831
     pass "redirect to /dev/null works"
832832
 else
@@ -834,7 +834,7 @@ else
834834
 fi
835835
 
836836
 # Redirect stderr to stdout
837
-result=$("$FORTSH_BIN" -c 'echo stderr >&2' 2>&1)
837
+result=$("$SHELL_BIN" -c 'echo stderr >&2' 2>&1)
838838
 if [ "$result" = "stderr" ]; then
839839
     pass "redirect stderr to stdout"
840840
 else
@@ -846,7 +846,7 @@ section "380. POSITIONAL PARAMETERS EDGE CASES"
846846
 # =====================================
847847
 
848848
 # More than 9 positional params
849
-result=$("$FORTSH_BIN" -c 'set -- a b c d e f g h i j k; echo $1 ${10} ${11}' 2>&1)
849
+result=$("$SHELL_BIN" -c 'set -- a b c d e f g h i j k; echo $1 ${10} ${11}' 2>&1)
850850
 if echo "$result" | grep -q "a j k"; then
851851
     pass "access to \${10} and beyond"
852852
 else
@@ -854,7 +854,7 @@ else
854854
 fi
855855
 
856856
 # shift with count
857
-result=$("$FORTSH_BIN" -c 'set -- a b c d e; shift 3; echo $1' 2>&1)
857
+result=$("$SHELL_BIN" -c 'set -- a b c d e; shift 3; echo $1' 2>&1)
858858
 if [ "$result" = "d" ]; then
859859
     pass "shift with count"
860860
 else
@@ -866,7 +866,7 @@ section "381. ARITHMETIC EDGE CASES"
866866
 # =====================================
867867
 
868868
 # Negative numbers
869
-result=$("$FORTSH_BIN" -c 'echo $((-5))' 2>&1)
869
+result=$("$SHELL_BIN" -c 'echo $((-5))' 2>&1)
870870
 if [ "$result" = "-5" ]; then
871871
     pass "negative numbers in arithmetic"
872872
 else
@@ -874,7 +874,7 @@ else
874874
 fi
875875
 
876876
 # Parentheses for grouping
877
-result=$("$FORTSH_BIN" -c 'echo $(( (2+3) * 4 ))' 2>&1)
877
+result=$("$SHELL_BIN" -c 'echo $(( (2+3) * 4 ))' 2>&1)
878878
 if [ "$result" = "20" ]; then
879879
     pass "parentheses in arithmetic"
880880
 else
@@ -882,14 +882,14 @@ else
882882
 fi
883883
 
884884
 # Comparison operators return 0/1
885
-result=$("$FORTSH_BIN" -c 'echo $((5 > 3))' 2>&1)
885
+result=$("$SHELL_BIN" -c 'echo $((5 > 3))' 2>&1)
886886
 if [ "$result" = "1" ]; then
887887
     pass "arithmetic comparison returns 1 for true"
888888
 else
889889
     fail "arithmetic comparison returns 1 for true" "1" "$result"
890890
 fi
891891
 
892
-result=$("$FORTSH_BIN" -c 'echo $((3 > 5))' 2>&1)
892
+result=$("$SHELL_BIN" -c 'echo $((3 > 5))' 2>&1)
893893
 if [ "$result" = "0" ]; then
894894
     pass "arithmetic comparison returns 0 for false"
895895
 else
@@ -901,7 +901,7 @@ section "382. VARIABLE ASSIGNMENT EDGE CASES"
901901
 # =====================================
902902
 
903903
 # Assignment with empty value
904
-result=$("$FORTSH_BIN" -c 'X=; echo "[$X]"' 2>&1)
904
+result=$("$SHELL_BIN" -c 'X=; echo "[$X]"' 2>&1)
905905
 if [ "$result" = "[]" ]; then
906906
     pass "empty variable assignment"
907907
 else
@@ -909,7 +909,7 @@ else
909909
 fi
910910
 
911911
 # Assignment with quotes
912
-result=$("$FORTSH_BIN" -c 'X="hello world"; echo $X' 2>&1)
912
+result=$("$SHELL_BIN" -c 'X="hello world"; echo $X' 2>&1)
913913
 if [ "$result" = "hello world" ]; then
914914
     pass "quoted variable assignment"
915915
 else
@@ -917,7 +917,7 @@ else
917917
 fi
918918
 
919919
 # Multiple assignments on one line
920
-result=$("$FORTSH_BIN" -c 'A=1 B=2 C=3; echo $A $B $C' 2>&1)
920
+result=$("$SHELL_BIN" -c 'A=1 B=2 C=3; echo $A $B $C' 2>&1)
921921
 if [ "$result" = "1 2 3" ]; then
922922
     pass "multiple assignments"
923923
 else
@@ -929,7 +929,7 @@ section "383. QUOTING EDGE CASES"
929929
 # =====================================
930930
 
931931
 # Single quotes preserve literally
932
-result=$("$FORTSH_BIN" -c "echo '\$HOME'" 2>&1)
932
+result=$("$SHELL_BIN" -c "echo '\$HOME'" 2>&1)
933933
 if [ "$result" = '$HOME' ]; then
934934
     pass "single quotes preserve dollar"
935935
 else
@@ -937,7 +937,7 @@ else
937937
 fi
938938
 
939939
 # Double quotes allow expansion
940
-result=$("$FORTSH_BIN" -c 'X=test; echo "$X"' 2>&1)
940
+result=$("$SHELL_BIN" -c 'X=test; echo "$X"' 2>&1)
941941
 if [ "$result" = "test" ]; then
942942
     pass "double quotes allow expansion"
943943
 else
@@ -945,7 +945,7 @@ else
945945
 fi
946946
 
947947
 # Mixed quoting
948
-result=$("$FORTSH_BIN" -c "X=val; echo 'literal'\"\$X\"'more'" 2>&1)
948
+result=$("$SHELL_BIN" -c "X=val; echo 'literal'\"\$X\"'more'" 2>&1)
949949
 if [ "$result" = "literalvalmore" ]; then
950950
     pass "mixed quoting works"
951951
 else
@@ -957,7 +957,7 @@ section "384. PIPELINE EDGE CASES"
957957
 # =====================================
958958
 
959959
 # Pipeline with three stages
960
-result=$("$FORTSH_BIN" -c 'echo test | cat | cat' 2>&1)
960
+result=$("$SHELL_BIN" -c 'echo test | cat | cat' 2>&1)
961961
 if [ "$result" = "test" ]; then
962962
     pass "three-stage pipeline"
963963
 else
@@ -965,7 +965,7 @@ else
965965
 fi
966966
 
967967
 # Pipeline with grep
968
-result=$("$FORTSH_BIN" -c 'echo "hello world" | grep hello' 2>&1)
968
+result=$("$SHELL_BIN" -c 'echo "hello world" | grep hello' 2>&1)
969969
 if [ "$result" = "hello world" ]; then
970970
     pass "pipeline with grep"
971971
 else
@@ -977,7 +977,7 @@ section "385. CASE STATEMENT EDGE CASES"
977977
 # =====================================
978978
 
979979
 # Case with wildcards
980
-result=$("$FORTSH_BIN" -c 'x=hello; case $x in h*) echo match;; esac' 2>&1)
980
+result=$("$SHELL_BIN" -c 'x=hello; case $x in h*) echo match;; esac' 2>&1)
981981
 if [ "$result" = "match" ]; then
982982
     pass "case with wildcard pattern"
983983
 else
@@ -985,7 +985,7 @@ else
985985
 fi
986986
 
987987
 # Case with multiple patterns
988
-result=$("$FORTSH_BIN" -c 'x=b; case $x in a|b|c) echo abc;; esac' 2>&1)
988
+result=$("$SHELL_BIN" -c 'x=b; case $x in a|b|c) echo abc;; esac' 2>&1)
989989
 if [ "$result" = "abc" ]; then
990990
     pass "case with multiple patterns"
991991
 else
@@ -993,7 +993,7 @@ else
993993
 fi
994994
 
995995
 # Case with default
996
-result=$("$FORTSH_BIN" -c 'x=z; case $x in a) echo a;; *) echo default;; esac' 2>&1)
996
+result=$("$SHELL_BIN" -c 'x=z; case $x in a) echo a;; *) echo default;; esac' 2>&1)
997997
 if [ "$result" = "default" ]; then
998998
     pass "case with default pattern"
999999
 else
@@ -1005,7 +1005,7 @@ section "386. LOOP EDGE CASES"
10051005
 # =====================================
10061006
 
10071007
 # For loop with break
1008
-result=$("$FORTSH_BIN" -c 'for i in 1 2 3 4 5; do [ $i -eq 3 ] && break; echo $i; done' 2>&1)
1008
+result=$("$SHELL_BIN" -c 'for i in 1 2 3 4 5; do [ $i -eq 3 ] && break; echo $i; done' 2>&1)
10091009
 expected="1
10101010
 2"
10111011
 if [ "$result" = "$expected" ]; then
@@ -1015,7 +1015,7 @@ else
10151015
 fi
10161016
 
10171017
 # For loop with continue
1018
-result=$("$FORTSH_BIN" -c 'for i in 1 2 3 4 5; do [ $i -eq 3 ] && continue; echo $i; done' 2>&1)
1018
+result=$("$SHELL_BIN" -c 'for i in 1 2 3 4 5; do [ $i -eq 3 ] && continue; echo $i; done' 2>&1)
10191019
 if echo "$result" | grep -q "1" && echo "$result" | grep -q "4" && ! echo "$result" | grep -q "3"; then
10201020
     pass "for loop with continue"
10211021
 else
@@ -1027,7 +1027,7 @@ section "387. SUBSHELL EDGE CASES"
10271027
 # =====================================
10281028
 
10291029
 # Subshell variable isolation
1030
-result=$("$FORTSH_BIN" -c 'X=outer; (X=inner; echo $X); echo $X' 2>&1)
1030
+result=$("$SHELL_BIN" -c 'X=outer; (X=inner; echo $X); echo $X' 2>&1)
10311031
 expected="inner
10321032
 outer"
10331033
 if [ "$result" = "$expected" ]; then
@@ -1037,7 +1037,7 @@ else
10371037
 fi
10381038
 
10391039
 # Subshell exit status
1040
-result=$("$FORTSH_BIN" -c '(exit 42); echo $?' 2>&1)
1040
+result=$("$SHELL_BIN" -c '(exit 42); echo $?' 2>&1)
10411041
 if [ "$result" = "42" ]; then
10421042
     pass "subshell exit status captured"
10431043
 else
@@ -1049,7 +1049,7 @@ section "388. FUNCTION EDGE CASES"
10491049
 # =====================================
10501050
 
10511051
 # Function with local-like behavior (via subshell)
1052
-result=$("$FORTSH_BIN" -c 'X=global; f() { (X=local; echo $X); }; f; echo $X' 2>&1)
1052
+result=$("$SHELL_BIN" -c 'X=global; f() { (X=local; echo $X); }; f; echo $X' 2>&1)
10531053
 expected="local
10541054
 global"
10551055
 if [ "$result" = "$expected" ]; then
@@ -1059,7 +1059,7 @@ else
10591059
 fi
10601060
 
10611061
 # Recursive function
1062
-result=$("$FORTSH_BIN" -c 'count() { if [ $1 -gt 0 ]; then echo $1; count $(($1-1)); fi; }; count 3' 2>&1)
1062
+result=$("$SHELL_BIN" -c 'count() { if [ $1 -gt 0 ]; then echo $1; count $(($1-1)); fi; }; count 3' 2>&1)
10631063
 expected="3
10641064
 2
10651065
 1"
@@ -1074,7 +1074,7 @@ section "389. HERE DOCUMENT EDGE CASES"
10741074
 # =====================================
10751075
 
10761076
 # Heredoc with variable expansion
1077
-result=$("$FORTSH_BIN" -c 'X=value; cat <<EOF
1077
+result=$("$SHELL_BIN" -c 'X=value; cat <<EOF
10781078
 $X
10791079
 EOF' 2>&1)
10801080
 if [ "$result" = "value" ]; then
@@ -1084,7 +1084,7 @@ else
10841084
 fi
10851085
 
10861086
 # Quoted heredoc (no expansion)
1087
-result=$("$FORTSH_BIN" -c 'cat <<'\''EOF'\''
1087
+result=$("$SHELL_BIN" -c 'cat <<'\''EOF'\''
10881088
 $VAR
10891089
 EOF' 2>&1)
10901090
 if [ "$result" = '$VAR' ]; then
@@ -1098,7 +1098,7 @@ section "390. COMMAND SUBSTITUTION EDGE CASES"
10981098
 # =====================================
10991099
 
11001100
 # Nested command substitution
1101
-result=$("$FORTSH_BIN" -c 'echo $(echo $(echo nested))' 2>&1)
1101
+result=$("$SHELL_BIN" -c 'echo $(echo $(echo nested))' 2>&1)
11021102
 if [ "$result" = "nested" ]; then
11031103
     pass "nested command substitution"
11041104
 else
@@ -1106,7 +1106,7 @@ else
11061106
 fi
11071107
 
11081108
 # Command substitution with quotes
1109
-result=$("$FORTSH_BIN" -c 'echo "$(echo "hello world")"' 2>&1)
1109
+result=$("$SHELL_BIN" -c 'echo "$(echo "hello world")"' 2>&1)
11101110
 if [ "$result" = "hello world" ]; then
11111111
     pass "command substitution with quotes"
11121112
 else
@@ -1114,7 +1114,7 @@ else
11141114
 fi
11151115
 
11161116
 # Backtick substitution
1117
-result=$("$FORTSH_BIN" -c 'echo `echo backtick`' 2>&1)
1117
+result=$("$SHELL_BIN" -c 'echo `echo backtick`' 2>&1)
11181118
 if [ "$result" = "backtick" ]; then
11191119
     pass "backtick command substitution"
11201120
 else
@@ -1125,28 +1125,28 @@ fi
11251125
 section "391. EXPR COMMAND"
11261126
 # =====================================
11271127
 
1128
-result=$("$FORTSH_BIN" -c 'expr 5 + 3' 2>&1)
1128
+result=$("$SHELL_BIN" -c 'expr 5 + 3' 2>&1)
11291129
 if [ "$result" = "8" ]; then
11301130
     pass "expr addition"
11311131
 else
11321132
     fail "expr addition" "8" "$result"
11331133
 fi
11341134
 
1135
-result=$("$FORTSH_BIN" -c 'expr 10 - 4' 2>&1)
1135
+result=$("$SHELL_BIN" -c 'expr 10 - 4' 2>&1)
11361136
 if [ "$result" = "6" ]; then
11371137
     pass "expr subtraction"
11381138
 else
11391139
     fail "expr subtraction" "6" "$result"
11401140
 fi
11411141
 
1142
-result=$("$FORTSH_BIN" -c 'expr 6 \* 7' 2>&1)
1142
+result=$("$SHELL_BIN" -c 'expr 6 \* 7' 2>&1)
11431143
 if [ "$result" = "42" ]; then
11441144
     pass "expr multiplication"
11451145
 else
11461146
     fail "expr multiplication" "42" "$result"
11471147
 fi
11481148
 
1149
-result=$("$FORTSH_BIN" -c 'expr 20 / 4' 2>&1)
1149
+result=$("$SHELL_BIN" -c 'expr 20 / 4' 2>&1)
11501150
 if [ "$result" = "5" ]; then
11511151
     pass "expr division"
11521152
 else
@@ -1157,28 +1157,28 @@ fi
11571157
 section "392. TEST COMMAND VARIATIONS"
11581158
 # =====================================
11591159
 
1160
-result=$("$FORTSH_BIN" -c 'test -f /etc/passwd && echo yes' 2>&1)
1160
+result=$("$SHELL_BIN" -c 'test -f /etc/passwd && echo yes' 2>&1)
11611161
 if [ "$result" = "yes" ]; then
11621162
     pass "test -f regular file"
11631163
 else
11641164
     fail "test -f regular file" "yes" "$result"
11651165
 fi
11661166
 
1167
-result=$("$FORTSH_BIN" -c 'test -d /tmp && echo yes' 2>&1)
1167
+result=$("$SHELL_BIN" -c 'test -d /tmp && echo yes' 2>&1)
11681168
 if [ "$result" = "yes" ]; then
11691169
     pass "test -d directory"
11701170
 else
11711171
     fail "test -d directory" "yes" "$result"
11721172
 fi
11731173
 
1174
-result=$("$FORTSH_BIN" -c 'test 5 -eq 5 && echo yes' 2>&1)
1174
+result=$("$SHELL_BIN" -c 'test 5 -eq 5 && echo yes' 2>&1)
11751175
 if [ "$result" = "yes" ]; then
11761176
     pass "test numeric equal"
11771177
 else
11781178
     fail "test numeric equal" "yes" "$result"
11791179
 fi
11801180
 
1181
-result=$("$FORTSH_BIN" -c 'test "abc" = "abc" && echo yes' 2>&1)
1181
+result=$("$SHELL_BIN" -c 'test "abc" = "abc" && echo yes' 2>&1)
11821182
 if [ "$result" = "yes" ]; then
11831183
     pass "test string equal"
11841184
 else
@@ -1189,28 +1189,28 @@ fi
11891189
 section "393. BASENAME AND DIRNAME SIMULATION"
11901190
 # =====================================
11911191
 
1192
-result=$("$FORTSH_BIN" -c 'X=/path/to/file.txt; echo ${X##*/}' 2>&1)
1192
+result=$("$SHELL_BIN" -c 'X=/path/to/file.txt; echo ${X##*/}' 2>&1)
11931193
 if [ "$result" = "file.txt" ]; then
11941194
     pass "basename via parameter expansion"
11951195
 else
11961196
     fail "basename via parameter expansion" "file.txt" "$result"
11971197
 fi
11981198
 
1199
-result=$("$FORTSH_BIN" -c 'X=/path/to/file.txt; echo ${X%/*}' 2>&1)
1199
+result=$("$SHELL_BIN" -c 'X=/path/to/file.txt; echo ${X%/*}' 2>&1)
12001200
 if [ "$result" = "/path/to" ]; then
12011201
     pass "dirname via parameter expansion"
12021202
 else
12031203
     fail "dirname via parameter expansion" "/path/to" "$result"
12041204
 fi
12051205
 
1206
-result=$("$FORTSH_BIN" -c 'X=file.tar.gz; echo ${X%.gz}' 2>&1)
1206
+result=$("$SHELL_BIN" -c 'X=file.tar.gz; echo ${X%.gz}' 2>&1)
12071207
 if [ "$result" = "file.tar" ]; then
12081208
     pass "remove extension"
12091209
 else
12101210
     fail "remove extension" "file.tar" "$result"
12111211
 fi
12121212
 
1213
-result=$("$FORTSH_BIN" -c 'X=file.tar.gz; echo ${X%%.*}' 2>&1)
1213
+result=$("$SHELL_BIN" -c 'X=file.tar.gz; echo ${X%%.*}' 2>&1)
12141214
 if [ "$result" = "file" ]; then
12151215
     pass "remove all extensions"
12161216
 else
@@ -1221,21 +1221,21 @@ fi
12211221
 section "394. COMPLEX PIPELINES"
12221222
 # =====================================
12231223
 
1224
-result=$("$FORTSH_BIN" -c 'echo "hello world" | tr " " "\n" | wc -l' 2>&1)
1224
+result=$("$SHELL_BIN" -c 'echo "hello world" | tr " " "\n" | wc -l' 2>&1)
12251225
 if [ "$result" -eq 2 ] 2>/dev/null; then
12261226
     pass "pipeline with tr and wc"
12271227
 else
12281228
     fail "pipeline with tr and wc" "2" "$result"
12291229
 fi
12301230
 
1231
-result=$("$FORTSH_BIN" -c 'printf "c\na\nb\n" | sort | head -1' 2>&1)
1231
+result=$("$SHELL_BIN" -c 'printf "c\na\nb\n" | sort | head -1' 2>&1)
12321232
 if [ "$result" = "a" ]; then
12331233
     pass "pipeline sort and head"
12341234
 else
12351235
     fail "pipeline sort and head" "a" "$result"
12361236
 fi
12371237
 
1238
-result=$("$FORTSH_BIN" -c 'echo "test" | cat | cat | cat' 2>&1)
1238
+result=$("$SHELL_BIN" -c 'echo "test" | cat | cat | cat' 2>&1)
12391239
 if [ "$result" = "test" ]; then
12401240
     pass "triple cat pipeline"
12411241
 else
@@ -1246,21 +1246,21 @@ fi
12461246
 section "395. COMMAND GROUPING"
12471247
 # =====================================
12481248
 
1249
-result=$("$FORTSH_BIN" -c '{ echo a; echo b; echo c; } | wc -l' 2>&1)
1249
+result=$("$SHELL_BIN" -c '{ echo a; echo b; echo c; } | wc -l' 2>&1)
12501250
 if [ "$result" -eq 3 ] 2>/dev/null; then
12511251
     pass "brace group to pipeline"
12521252
 else
12531253
     fail "brace group to pipeline" "3" "$result"
12541254
 fi
12551255
 
1256
-result=$("$FORTSH_BIN" -c '(echo x; echo y) | wc -l' 2>&1)
1256
+result=$("$SHELL_BIN" -c '(echo x; echo y) | wc -l' 2>&1)
12571257
 if [ "$result" -eq 2 ] 2>/dev/null; then
12581258
     pass "subshell to pipeline"
12591259
 else
12601260
     fail "subshell to pipeline" "2" "$result"
12611261
 fi
12621262
 
1263
-result=$("$FORTSH_BIN" -c 'X=1; { X=2; echo $X; }; echo $X' 2>&1)
1263
+result=$("$SHELL_BIN" -c 'X=1; { X=2; echo $X; }; echo $X' 2>&1)
12641264
 expected=$(printf "2\n2")
12651265
 if [ "$result" = "$expected" ]; then
12661266
     pass "brace group modifies parent var"
@@ -1272,21 +1272,21 @@ fi
12721272
 section "396. WORD EXPANSION ORDER"
12731273
 # =====================================
12741274
 
1275
-result=$("$FORTSH_BIN" -c 'X="a b c"; echo $X' 2>&1)
1275
+result=$("$SHELL_BIN" -c 'X="a b c"; echo $X' 2>&1)
12761276
 if [ "$result" = "a b c" ]; then
12771277
     pass "unquoted var word splits"
12781278
 else
12791279
     fail "unquoted var word splits" "a b c" "$result"
12801280
 fi
12811281
 
1282
-result=$("$FORTSH_BIN" -c 'X="a b c"; echo "$X"' 2>&1)
1282
+result=$("$SHELL_BIN" -c 'X="a b c"; echo "$X"' 2>&1)
12831283
 if [ "$result" = "a b c" ]; then
12841284
     pass "quoted var preserves spaces"
12851285
 else
12861286
     fail "quoted var preserves spaces" "a b c" "$result"
12871287
 fi
12881288
 
1289
-result=$("$FORTSH_BIN" -c 'echo ~ | grep -c "^/"' 2>&1)
1289
+result=$("$SHELL_BIN" -c 'echo ~ | grep -c "^/"' 2>&1)
12901290
 if [ "$result" = "1" ]; then
12911291
     pass "tilde expands to home"
12921292
 else
@@ -1297,21 +1297,21 @@ fi
12971297
 section "397. SIGNAL NAMES"
12981298
 # =====================================
12991299
 
1300
-result=$("$FORTSH_BIN" -c 'kill -l | grep -c HUP' 2>&1)
1300
+result=$("$SHELL_BIN" -c 'kill -l | grep -c HUP' 2>&1)
13011301
 if [ "$result" -ge 1 ]; then
13021302
     pass "kill -l shows HUP"
13031303
 else
13041304
     fail "kill -l shows HUP"
13051305
 fi
13061306
 
1307
-result=$("$FORTSH_BIN" -c 'kill -l | grep -c INT' 2>&1)
1307
+result=$("$SHELL_BIN" -c 'kill -l | grep -c INT' 2>&1)
13081308
 if [ "$result" -ge 1 ]; then
13091309
     pass "kill -l shows INT"
13101310
 else
13111311
     fail "kill -l shows INT"
13121312
 fi
13131313
 
1314
-result=$("$FORTSH_BIN" -c 'kill -l | grep -c TERM' 2>&1)
1314
+result=$("$SHELL_BIN" -c 'kill -l | grep -c TERM' 2>&1)
13151315
 if [ "$result" -ge 1 ]; then
13161316
     pass "kill -l shows TERM"
13171317
 else
@@ -1322,7 +1322,7 @@ fi
13221322
 section "398. EXEC WITH FD"
13231323
 # =====================================
13241324
 
1325
-result=$("$FORTSH_BIN" -c 'exec 3>&1; echo test >&3; exec 3>&-' 2>&1)
1325
+result=$("$SHELL_BIN" -c 'exec 3>&1; echo test >&3; exec 3>&-' 2>&1)
13261326
 if [ "$result" = "test" ]; then
13271327
     pass "exec fd redirect"
13281328
 else
@@ -1333,21 +1333,21 @@ fi
13331333
 section "399. COMPLEX FUNCTIONS"
13341334
 # =====================================
13351335
 
1336
-result=$("$FORTSH_BIN" -c 'max() { [ $1 -gt $2 ] && echo $1 || echo $2; }; max 5 3' 2>&1)
1336
+result=$("$SHELL_BIN" -c 'max() { [ $1 -gt $2 ] && echo $1 || echo $2; }; max 5 3' 2>&1)
13371337
 if [ "$result" = "5" ]; then
13381338
     pass "function max returns larger"
13391339
 else
13401340
     fail "function max returns larger" "5" "$result"
13411341
 fi
13421342
 
1343
-result=$("$FORTSH_BIN" -c 'sum() { echo $(($1 + $2)); }; sum 10 20' 2>&1)
1343
+result=$("$SHELL_BIN" -c 'sum() { echo $(($1 + $2)); }; sum 10 20' 2>&1)
13441344
 if [ "$result" = "30" ]; then
13451345
     pass "function sum"
13461346
 else
13471347
     fail "function sum" "30" "$result"
13481348
 fi
13491349
 
1350
-result=$("$FORTSH_BIN" -c 'greet() { echo "Hello, $1!"; }; greet World' 2>&1)
1350
+result=$("$SHELL_BIN" -c 'greet() { echo "Hello, $1!"; }; greet World' 2>&1)
13511351
 if [ "$result" = "Hello, World!" ]; then
13521352
     pass "function with string interpolation"
13531353
 else
@@ -1358,7 +1358,7 @@ fi
13581358
 section "400. ADVANCED REDIRECTIONS"
13591359
 # =====================================
13601360
 
1361
-result=$("$FORTSH_BIN" -c 'echo out; echo err >&2' 2>&1)
1361
+result=$("$SHELL_BIN" -c 'echo out; echo err >&2' 2>&1)
13621362
 expected=$(printf "out\nerr")
13631363
 if [ "$result" = "$expected" ]; then
13641364
     pass "stdout and stderr"
@@ -1366,7 +1366,7 @@ else
13661366
     fail "stdout and stderr"
13671367
 fi
13681368
 
1369
-result=$("$FORTSH_BIN" -c '{ echo a; echo b >&2; } 2>&1 | wc -l' 2>&1)
1369
+result=$("$SHELL_BIN" -c '{ echo a; echo b >&2; } 2>&1 | wc -l' 2>&1)
13701370
 if [ "$result" -eq 2 ] 2>/dev/null; then
13711371
     pass "redirect stderr to stdout in pipeline"
13721372
 else
suites/posix/posix_compliance_test.shmodified
@@ -27,13 +27,13 @@ FAILED_TESTS_LIST=""
2727
 
2828
 # Get script directory (POSIX way)
2929
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
30
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
30
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
3131
 BASH_REF="${BASH_REF:-bash}"
3232
 
3333
 # Check if fortsh exists
34
-if [ ! -x "$FORTSH_BIN" ]; then
35
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
36
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
34
+if [ ! -x "$SHELL_BIN" ]; then
35
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
36
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3737
     exit 1
3838
 fi
3939
 
@@ -85,7 +85,7 @@ compare_posix_output() {
8585
     "$BASH_REF" -c "$command" > "$posix_file" 2>&1 || true
8686
 
8787
     # Run in fortsh
88
-    "$FORTSH_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
88
+    "$SHELL_BIN" -c "$command" > "$fortsh_file" 2>&1 || true
8989
 
9090
     # Compare outputs
9191
     if diff -q "$posix_file" "$fortsh_file" > /dev/null 2>&1; then
@@ -105,7 +105,7 @@ compare_posix_exit_code() {
105105
     "$BASH_REF" -c "$command" > /dev/null 2>&1
106106
     posix_exit=$?
107107
 
108
-    "$FORTSH_BIN" -c "$command" > /dev/null 2>&1
108
+    "$SHELL_BIN" -c "$command" > /dev/null 2>&1
109109
     fortsh_exit=$?
110110
 
111111
     if [ "$posix_exit" -eq "$fortsh_exit" ]; then
@@ -371,7 +371,7 @@ section "34. POSIX TIMES"
371371
 
372372
 # times is optional but common
373373
 # times output contains variable timing values, so just verify format
374
-_times_out=$("$FORTSH_BIN" -c 'times' 2>/dev/null)
374
+_times_out=$("$SHELL_BIN" -c 'times' 2>/dev/null)
375375
 if echo "$_times_out" | grep -qE '[0-9]+m[0-9]+\.[0-9]+s'; then
376376
     pass "times output exists"
377377
 else
suites/posix/posix_compliance_untested.shmodified
@@ -23,13 +23,13 @@ FAILED_TESTS_LIST=""
2323
 
2424
 # Get script directory (POSIX way)
2525
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
26
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
26
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2727
 BASH_REF="${BASH_REF:-bash}"
2828
 
2929
 # Check if fortsh exists
30
-if [ ! -x "$FORTSH_BIN" ]; then
31
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
30
+if [ ! -x "$SHELL_BIN" ]; then
31
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
32
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3333
     exit 1
3434
 fi
3535
 
@@ -79,7 +79,7 @@ compare_posix_output() {
7979
     posix_exit=$?
8080
 
8181
     # Run with fortsh
82
-    fortsh_output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1)
82
+    fortsh_output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1)
8383
     fortsh_exit=$?
8484
 
8585
     # Compare outputs
@@ -104,7 +104,7 @@ compare_posix_error() {
104104
     posix_output=$(FORTSH_RC_FILE=/dev/null "$BASH_REF" -c "$test_cmd" 2>&1)
105105
     posix_exit=$?
106106
 
107
-    fortsh_output=$(FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" 2>&1)
107
+    fortsh_output=$(FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" 2>&1)
108108
     fortsh_exit=$?
109109
 
110110
     posix_norm=$(normalize_error "$posix_output")
@@ -122,7 +122,7 @@ test_accepts() {
122122
     test_name="$1"
123123
     test_cmd="$2"
124124
 
125
-    if FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" >/dev/null 2>&1; then
125
+    if FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" >/dev/null 2>&1; then
126126
         pass "$test_name"
127127
     else
128128
         fail "$test_name" "should succeed" "failed or not implemented"
@@ -134,7 +134,7 @@ test_fails() {
134134
     test_name="$1"
135135
     test_cmd="$2"
136136
 
137
-    if ! FORTSH_RC_FILE=/dev/null "$FORTSH_BIN" -c "$test_cmd" >/dev/null 2>&1; then
137
+    if ! FORTSH_RC_FILE=/dev/null "$SHELL_BIN" -c "$test_cmd" >/dev/null 2>&1; then
138138
         pass "$test_name"
139139
     else
140140
         fail "$test_name" "should fail" "succeeded unexpectedly"
suites/posix/posix_gaps_arithmetic.shmodified
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -61,7 +61,7 @@ normalize_output() { sed -e 's|^[^ ]*bash: |sh: |' -e 's|^[^ ]*fortsh: |sh: |' -
6161
 compare_posix_output() {
6262
     test_name="$1"; command="$2"
6363
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
64
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
64
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
6565
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
6666
     else fail "$test_name" "$posix_out" "$fortsh_out"; fi
6767
 }
@@ -69,7 +69,7 @@ compare_posix_output() {
6969
 compare_posix_exit_code() {
7070
     test_name="$1"; command="$2"
7171
     "$BASH_REF" -c "$command" >/dev/null 2>&1; posix_code=$?
72
-    "$FORTSH_BIN" -c "$command" >/dev/null 2>&1; fortsh_code=$?
72
+    "$SHELL_BIN" -c "$command" >/dev/null 2>&1; fortsh_code=$?
7373
     if [ "$posix_code" = "$fortsh_code" ]; then pass "$test_name"
7474
     else fail "$test_name" "exit $posix_code" "exit $fortsh_code"; fi
7575
 }
suites/posix/posix_gaps_builtins.shmodified
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -61,7 +61,7 @@ normalize_output() { sed -e 's|^[^ ]*bash: |sh: |' -e 's|^[^ ]*fortsh: |sh: |' -
6161
 compare_posix_output() {
6262
     test_name="$1"; command="$2"
6363
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
64
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
64
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
6565
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
6666
     else fail "$test_name" "$posix_out" "$fortsh_out"; fi
6767
 }
@@ -69,7 +69,7 @@ compare_posix_output() {
6969
 compare_posix_exit_code() {
7070
     test_name="$1"; command="$2"
7171
     "$BASH_REF" -c "$command" >/dev/null 2>&1; posix_code=$?
72
-    "$FORTSH_BIN" -c "$command" >/dev/null 2>&1; fortsh_code=$?
72
+    "$SHELL_BIN" -c "$command" >/dev/null 2>&1; fortsh_code=$?
7373
     if [ "$posix_code" = "$fortsh_code" ]; then pass "$test_name"
7474
     else fail "$test_name" "exit $posix_code" "exit $fortsh_code"; fi
7575
 }
@@ -77,7 +77,7 @@ compare_posix_exit_code() {
7777
 compare_posix_error() {
7878
     test_name="$1"; command="$2"
7979
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
80
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
80
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
8181
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
8282
     else fail "$test_name" "$posix_out" "$fortsh_out"; fi
8383
 }
suites/posix/posix_gaps_charclass.shmodified
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -61,7 +61,7 @@ normalize_output() { sed -e 's|^[^ ]*bash: |sh: |' -e 's|^[^ ]*fortsh: |sh: |' -
6161
 compare_posix_output() {
6262
     test_name="$1"; command="$2"
6363
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
64
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
64
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
6565
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
6666
     else fail "$test_name" "$posix_out" "$fortsh_out"; fi
6767
 }
suites/posix/posix_gaps_control.shmodified
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -61,7 +61,7 @@ normalize_output() { sed -e 's|^[^ ]*bash: |sh: |' -e 's|^[^ ]*fortsh: |sh: |' -
6161
 compare_posix_output() {
6262
     test_name="$1"; command="$2"
6363
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
64
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
64
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
6565
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
6666
     else fail "$test_name" "$posix_out" "$fortsh_out"; fi
6767
 }
@@ -99,7 +99,7 @@ compare_posix_output "for with continue" 'for i in 1 2 3; do if [ $i = 2 ]; then
9999
 # Inline test with debug output for CI diagnosis
100100
 _glob_cmd="touch /tmp/posix_gaps_for1_$$.txt /tmp/posix_gaps_for2_$$.txt /tmp/posix_gaps_for3_$$.txt 2>/dev/null; for f in /tmp/posix_gaps_for*_$$.txt; do test -f \$f && echo yes; done | head -1; rm -f /tmp/posix_gaps_for*_$$.txt"
101101
 _glob_posix=$("$BASH_REF" -c "$_glob_cmd" 2>&1)
102
-_glob_fortsh=$("$FORTSH_BIN" -c "$_glob_cmd" 2>&1)
102
+_glob_fortsh=$("$SHELL_BIN" -c "$_glob_cmd" 2>&1)
103103
 _glob_debug="[DEBUG glob] posix_hex=[$(printf '%s' "$_glob_posix" | od -A n -t x1 | tr -d '\n')] fortsh_hex=[$(printf '%s' "$_glob_fortsh" | od -A n -t x1 | tr -d '\n')] posix_raw=[$_glob_posix] fortsh_raw=[$_glob_fortsh]"
104104
 _glob_posix_n=$(printf '%s' "$_glob_posix" | normalize_output)
105105
 _glob_fortsh_n=$(printf '%s' "$_glob_fortsh" | normalize_output)
suites/posix/posix_gaps_heredoc.shmodified
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -61,7 +61,7 @@ normalize_output() { sed -e 's|^[^ ]*bash: |sh: |' -e 's|^[^ ]*fortsh: |sh: |' -
6161
 compare_posix_output() {
6262
     test_name="$1"; command="$2"
6363
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
64
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
64
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
6565
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
6666
     else fail "$test_name" "$posix_out" "$fortsh_out"; fi
6767
 }
@@ -69,7 +69,7 @@ compare_posix_output() {
6969
 compare_posix_exit_code() {
7070
     test_name="$1"; command="$2"
7171
     "$BASH_REF" -c "$command" >/dev/null 2>&1; posix_code=$?
72
-    "$FORTSH_BIN" -c "$command" >/dev/null 2>&1; fortsh_code=$?
72
+    "$SHELL_BIN" -c "$command" >/dev/null 2>&1; fortsh_code=$?
7373
     if [ "$posix_code" = "$fortsh_code" ]; then pass "$test_name"
7474
     else fail "$test_name" "exit $posix_code" "exit $fortsh_code"; fi
7575
 }
suites/posix/posix_gaps_quoting.shmodified
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -61,7 +61,7 @@ normalize_output() { sed -e 's|^[^ ]*bash: |sh: |' -e 's|^[^ ]*fortsh: |sh: |' -
6161
 compare_posix_output() {
6262
     test_name="$1"; command="$2"
6363
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
64
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
64
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
6565
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
6666
     else fail "$test_name" "$posix_out" "$fortsh_out"; fi
6767
 }
suites/posix/posix_gaps_redirect.shmodified
@@ -24,13 +24,13 @@ FAILED_TESTS_LIST=""
2424
 
2525
 # Get script directory (POSIX way)
2626
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
27
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
27
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2828
 BASH_REF="${BASH_REF:-bash}"
2929
 
3030
 # Check if fortsh exists
31
-if [ ! -x "$FORTSH_BIN" ]; then
32
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
33
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
31
+if [ ! -x "$SHELL_BIN" ]; then
32
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
33
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3434
     exit 1
3535
 fi
3636
 
@@ -61,7 +61,7 @@ normalize_output() { sed -e 's|^[^ ]*bash: |sh: |' -e 's|^[^ ]*fortsh: |sh: |' -
6161
 compare_posix_output() {
6262
     test_name="$1"; command="$2"
6363
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
64
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
64
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
6565
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
6666
     else fail "$test_name" "$posix_out" "$fortsh_out"; fi
6767
 }
@@ -69,7 +69,7 @@ compare_posix_output() {
6969
 compare_posix_exit_code() {
7070
     test_name="$1"; command="$2"
7171
     "$BASH_REF" -c "$command" >/dev/null 2>&1; posix_code=$?
72
-    "$FORTSH_BIN" -c "$command" >/dev/null 2>&1; fortsh_code=$?
72
+    "$SHELL_BIN" -c "$command" >/dev/null 2>&1; fortsh_code=$?
7373
     if [ "$posix_code" = "$fortsh_code" ]; then pass "$test_name"
7474
     else fail "$test_name" "exit $posix_code" "exit $fortsh_code"; fi
7575
 }
suites/posix/posix_gaps_special.shmodified
@@ -25,13 +25,13 @@ DEBUG_INFO=""
2525
 
2626
 # Get script directory (POSIX way)
2727
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
28
-FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
28
+SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}"
2929
 BASH_REF="${BASH_REF:-bash}"
3030
 
3131
 # Check if fortsh exists
32
-if [ ! -x "$FORTSH_BIN" ]; then
33
-    printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
34
-    printf "Please run 'make' first or set FORTSH_BIN environment variable\n"
32
+if [ ! -x "$SHELL_BIN" ]; then
33
+    printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
34
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
3535
     exit 1
3636
 fi
3737
 
@@ -62,7 +62,7 @@ normalize_output() { sed -e 's|^[^ ]*bash: |sh: |' -e 's|^[^ ]*fortsh: |sh: |' -
6262
 compare_posix_output() {
6363
     test_name="$1"; command="$2"
6464
     posix_out=$("$BASH_REF" -c "$command" 2>&1 | normalize_output)
65
-    fortsh_out=$("$FORTSH_BIN" -c "$command" 2>&1 | normalize_output)
65
+    fortsh_out=$("$SHELL_BIN" -c "$command" 2>&1 | normalize_output)
6666
     if [ "$posix_out" = "$fortsh_out" ]; then pass "$test_name"
6767
     else
6868
         fail "$test_name" "$posix_out" "$fortsh_out"
suites/posix/run_posix_tests.shmodified
@@ -19,9 +19,9 @@ NC='\033[0m'
1919
 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
2020
 
2121
 # Find fortsh binary - check multiple locations
22
-if [ -n "$FORTSH_BIN" ] && [ -x "$FORTSH_BIN" ]; then
22
+if [ -n "$SHELL_BIN" ] && [ -x "$SHELL_BIN" ]; then
2323
     # Use environment variable if set
24
-    FORTSH_PATH="$FORTSH_BIN"
24
+    FORTSH_PATH="$SHELL_BIN"
2525
 elif [ -x "$SCRIPT_DIR/../bin/fortsh" ]; then
2626
     # Look in ../bin/fortsh (relative to tests/)
2727
     FORTSH_PATH="$SCRIPT_DIR/../bin/fortsh"
@@ -32,17 +32,17 @@ elif [ -x "$(pwd)/bin/fortsh" ]; then
3232
     # Look in current working directory
3333
     FORTSH_PATH="$(pwd)/bin/fortsh"
3434
 else
35
-    printf "${RED}ERROR: fortsh binary not found!${NC}\n"
35
+    printf "${RED}ERROR: shell binary not found!${NC}\n"
3636
     printf "Searched locations:\n"
37
-    printf "  - FORTSH_BIN environment variable\n"
37
+    printf "  - SHELL_BIN environment variable\n"
3838
     printf "  - %s/bin/fortsh\n" "$SCRIPT_DIR/.."
3939
     printf "  - ./bin/fortsh\n"
4040
     printf "  - $(pwd)/bin/fortsh\n"
41
-    printf "\nPlease build fortsh first with 'make' or set FORTSH_BIN\n"
41
+    printf "\nPlease build fortsh first with 'make' or set SHELL_BIN\n"
4242
     exit 1
4343
 fi
4444
 
45
-export FORTSH_BIN="$FORTSH_PATH"
45
+export SHELL_BIN="$FORTSH_PATH"
4646
 
4747
 # Test suite files
4848
 TEST_SUITES="
@@ -60,7 +60,7 @@ posix_compliance_untested.sh
6060
 printf "${CYAN}========================================\n"
6161
 printf "POSIX Compliance Test Suite Runner\n"
6262
 printf "========================================${NC}\n"
63
-printf "fortsh binary: ${GREEN}%s${NC}\n" "$FORTSH_BIN"
63
+printf "fortsh binary: ${GREEN}%s${NC}\n" "$SHELL_BIN"
6464
 printf "Test directory: %s\n" "$SCRIPT_DIR"
6565
 printf "\n"
6666
 
suites/test_harness.shmodified
@@ -54,7 +54,7 @@ BASH_REF="${BASH_REF:-bash}"
5454
 # Check if fortsh exists
5555
 if [ ! -x "$SHELL_BIN" ]; then
5656
     printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n"
57
-    printf "Please run 'make' first or set SHELL_BIN environment variable\n"
57
+    printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n"
5858
     exit 1
5959
 fi
6060