# trip.rc -- take a tour of rc
# Invoke as "path-to-new-rc < trip.rc"

rc=$0
echo tripping $rc $version

tmpdir=''
fn fail {
	echo >[1=2] trip took a wrong turn: $*
	rm -rf $tmpdir
	fn sigexit
	exit 1
}
fn expect {
	echo >[1=2] -n expect $^*^': '
}
fn submatch {
	if (!~ $#* 3)
		fail incorrect invocation of submatch
	got = `` $nl { prompt=$nl $rc -ic $1>[2=1] }
	if (!~ $^got $2) {
		echo got $got expected $2
		fail $3
	}
}
fn sigexit sigint sigquit sigsegv
fn sigexit {
	echo trip complete
}
tmpdir=`{ mktemp -d -t rc-trip.XXXXXX }
tmp=$tmpdir/tmp
nl='
'

#
# rc -c
#

if ($rc -c >[2]/dev/null) fail 'rc -c didn''t report a bad exit status'
x=`{$rc -c 'echo $0 $2 $#*' a b c d e f}
if (false) {					# WARNING: this differs from sh
	if (!~ $x(1) a) fail rc -c reports '$0' incorrectly as $x(1)
	if (!~ $x(2) c) fail rc -c reports '$2' incorrectly as $x(2)
	if (!~ $x(3) 5) fail rc -c reports '$#' incorrectly as $x(3)
} else {
	if (!~ $x(1) $rc) fail rc -c reports '$0' incorrectly as $x(1)
	if (!~ $x(2) b) fail rc -c reports '$2' incorrectly as $x(2)
	if (!~ $x(3) 6) fail rc -c reports '$#' incorrectly as $x(3)
}

#
# umask
#

umask 0
> $tmp
x=`{ls -l $tmp}
if (!~ $x(1) -rw-rw-rw-*) fail umask 0 produced incorrect result: $x(1)
rm -f $tmp
umask 027
> $tmp
y=`{ls -l $tmp}
if (!~ $y(1) -rw-r-----*) fail umask 027 produced incorrect file: $y(1)
rm -f $tmp
if (!~ `umask 027) fail umask reported bad value: `umask

submatch 'umask bad' 'bad umask' 'bad umask'
submatch 'umask -027' 'bad umask' 'bad umask'
submatch 'umask 999999' 'bad umask' 'bad umask'
submatch 'umask hi there' 'rc: too many arguments to umask' 'umask arg count'

if (!~ `umask 027) fail bad umask changed umask value to `umask

#
# redirections
#

fn bytes { for (i) x=`{wc -c $i} echo $x(1) }
echo foo > foo > bar
if (!~ `{bytes foo} 0) fail double redirection created non-empty empty file
if (!~ `{bytes bar} 4) fail double redirection created wrong sized file: `{bytes bar}
rm -f foo bar
echo -n >1 >[2]2 >[1=2] foo
x = `` '' {cat 1}
if (!~ $#x 0) fail dup created non-empty empty file: `` '' {cat 1}
if (!~ `` '' {cat 2} foo) fail dup put wrong contents in file : `` '' {cat 2}
rm -f 1 2

expect error from cat, closing stdin
cat >[0=]

submatch 'cat>(1 2 3)' 'rc: multi-word filename in redirection' 'redirection error'
submatch 'cat>()' 'rc: null filename in redirection' 'redirection error'

#
# blow the input stack
#

if (!~ hi `{
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval eval eval \
eval eval eval eval eval eval eval eval eval eval eval echo hi
})
	fail huge eval

#
# heredocs and herestrings
#

bigfile=$tmpdir/big.$pid
od $rc | sed 5000q > $bigfile
abc=(this is a)
x=()
result='this is a heredoc
this is an heredoc
'
if (!~ `` '' {<<[5] EOF cat <[0=5]} $result) fail unquoted heredoc
$abc heredoc$x
$abc^n $x^here$x^doc
EOF
{if (!~ `` $nl cat '	') fail quoted heredoc} << ' '
	
 

<<<[9] ``''{cat $bigfile} \
{
	if(!~ ``''{cat <[0=9]}``'' cat)fail large herestrings
} < \
$bigfile

rm -f $bigfile

if (!~ `{cat<<eof
$$
eof
} '$')
	fail quoting '$' in heredoc

submatch 'cat<<eof' 'rc: heredoc incomplete' 'incomplete heredoc'
submatch 'cat<<eof
' 'rc: heredoc incomplete' 'incomplete heredoc'

submatch 'cat<<(eof eof)' 'rc: eof-marker not a single literal word' 'bad heredoc marker'

#
# lexical analysis
#

expect warning
./tripping 0 > $tmp
$rc $tmp
rm -f $tmp

echo here_is_a_really_long_word.It_has_got_to_be_longer_than_1000_characters_for_the_lexical_analyzers_buffer_to_overflow_but_that_should_not_be_too_difficult_to_do.Let_me_start_writing_some_Lewis_Carroll.Twas_brillig_and_the_slithy_toves,Did_gyre_and_gimble_in_the_wabe.All_mimsy_were_the_borogoves,And_the_mome-raths_outgrabe.Beware_the_Jabberwock_my_son,The_jaws_that_bite,the_claws_that_catch.Beware_the_Jub-jub_bird,and_shun_The_frumious_Bandersnatch.He_took_his_vorpal_sword_in_hand,Long_time_the_manxome_foe_he_sought,So_rested_he_by_the_Tumtum_tree,And_stood_awhile_in_thought.And_as_in_uffish_thought_he_stood,The_Jabberwock,with_eyes_of_flame,Came_whiffling_through_the_tulgey_wood,And_burbled_as_it_came.One_two,one_two.And_through_and_through_The_vorpal_blade_went_snicker-snack.He_left_it_dead_and_with_its_head,He_went_galumphing_back.And_hast_thou_slain_the_Jabberwock?Come_to_my_arms,my_beamish_boy,Oh_frabjous_day.Callooh_callay.He_chortled_in_his_joy.Twas_brillig,and_the_slithy_toves,Did_gyre_and_gimble_in_the_wabe,All_mimsy_were_the_borogoves,And_the_mome-raths_outgrabe. > $tmpdir/$pid.lw

echo 'here_is_a_really_long_word.It_has_got_to_be_longer_than_1000_characters_for_the_lexical_analyzers_buffer_to_overflow_but_that_should_not_be_too_difficult_to_do.Let_me_start_writing_some_Lewis_Carroll.Twas_brillig_and_the_slithy_toves,Did_gyre_and_gimble_in_the_wabe.All_mimsy_were_the_borogoves,And_the_mome-raths_outgrabe.Beware_the_Jabberwock_my_son,The_jaws_that_bite,the_claws_that_catch.Beware_the_Jub-jub_bird,and_shun_The_frumious_Bandersnatch.He_took_his_vorpal_sword_in_hand,Long_time_the_manxome_foe_he_sought,So_rested_he_by_the_Tumtum_tree,And_stood_awhile_in_thought.And_as_in_uffish_thought_he_stood,The_Jabberwock,with_eyes_of_flame,Came_whiffling_through_the_tulgey_wood,And_burbled_as_it_came.One_two,one_two.And_through_and_through_The_vorpal_blade_went_snicker-snack.He_left_it_dead_and_with_its_head,He_went_galumphing_back.And_hast_thou_slain_the_Jabberwock?Come_to_my_arms,my_beamish_boy,Oh_frabjous_day.Callooh_callay.He_chortled_in_his_joy.Twas_brillig,and_the_slithy_toves,Did_gyre_and_gimble_in_the_wabe,All_mimsy_were_the_borogoves,And_the_mome-raths_outgrabe.' > $tmpdir/$pid.lq

if (!~ ``(){cat $tmpdir/$pid.lw} ``(){cat $tmpdir/$pid.lq})
	fail expected long string and long word to be identical
if (! x=`{wc -c $tmpdir/$pid.lw} ~ $x(1) 1088)
	fail expected long word to be 1088 bytes
if (! x=`{wc -c $tmpdir/$pid.lq} ~ $x(1) 1088)
	fail expected long quote to be 1088 bytes

rm $tmpdir/$pid.lw
rm $tmpdir/$pid.lq

submatch 'echo hi |[2' 'rc: expected ''='' or '']'' after digit' 'scan error'
submatch 'echo hi |[92=]' 'rc: expected digit after ''=''' 'scan error'
submatch 'echo hi |[a]' 'rc: expected digit after ''[''' 'scan error'
submatch 'echo hi |[2-' 'rc: expected ''='' or '']'' after digit' 'scan error'
submatch 'echo hi |[2=99a]' 'rc: expected '']'' after digit' 'scan error'
submatch 'echo hi |[2=a99]' 'rc: expected digit or '']'' after ''=''' 'scan error'
submatch 'echo ''hi' 'rc: eof in quoted string' 'scan error'

ifs='' {
	if (!~ 'h i' `{echo -n h\
i})
		fail backslash-newline to space conversion
	if (!~ $rc^\rc `{echo -n $rc\rc})
		fail backslash after variable name did not terminate variable name scan
	if (!~ $rc^' rc' `{echo -n $rc\
rc})
		fail backslash-newline after variable name space conversion
	if (!~ 'h\i' `{echo -n h\i})
		fail backslash in the middle of word
	if (!~ 'h \ i' `{echo -n h \ i})
		fail free-standing backslash
}

if (! $rc -c '# eof in comment')
	fail eof in comment exited with nonzero status

# test the syntax error printer

prompt='' if (!~ `` $nl {$rc -cif>[2=1]} 'rc: line 1: '*' error near if')
	fail print syntax error

prompt='' if (!~ `` $nl {$rc -icif>[2=1]} *' error')
	fail print syntax error

#
# builtins
#

fn foo {
	return sigfpe
}

foo
if (!~ $status sigfpe)
	fail return builtin did not return sigfpe

fn foo # test deleting of function
fn bar {
	for (i in 1 2 3 4 5)
		if (~ $i 3)
			return
}

bar
if (!~ $i 3)
	fail return inside loop inside function failed

submatch return 'rc: return outside of function' 'return outside of function'
submatch 'break 1' 'rc: too many arguments to break' 'break arg count'
submatch break 'rc: break outside of loop' 'break outside of loop'
submatch 'fn f{@{return;echo xxx}};f;echo yyy' 'rc: return outside of function yyy' 'return outside of function'
submatch 'for(i in 1 2){echo $i;break >/dev/null}' '1 rc: break outside of loop 2 rc: break outside of loop' 'break outside of loop'

for (i in 1 2 3 4 5)
	if (~ $i 2)
		break
if (!~ $i 2)
	fail break out of loop

if (~ `{echo -n} ?)
	fail echo -n
if (!~ `` '' {echo --} $nl)
	fail echo --

pwd=`{/bin/pwd -P} cdpath=/ { # some local assignments
	home=/tmp cd
	if (!~ `{/bin/pwd -P} `{sh -c 'cd /tmp; /bin/pwd -P'})
		fail could not cd to '$home'

	cdpath=/ cd tmp
	if (!~ `{/bin/pwd -P} `{sh -c 'cd /tmp; /bin/pwd -P'})
		fail could not cd to /tmp

	cd $pwd
	if (!~ `{/bin/pwd -P} `{sh -c 'cd $pwd; /bin/pwd -P'})
		fail could not cd to current directory!
}

# Test that cd to a directory found via cdpath produces output
# when interactive.
submatch 'cdpath=/ cd tmp' /tmp 'cdpath produced wrong output'

*=(1 2 3 4 5) {
	expect bad number
	shift foo
	expect arg count
	shift 1 2 3
	expect shift overflow
	shift 123
	shift 3
	if (!~ $#* 2)
		fail shift 3 of '(1 2 3 4 5)' failed
	shift
	if (!~ $* 5)
		fail shift failed to shift left-to-right
}

false
eval && fail null eval reset '$status'

if (!~ `{rm=(); fn rm; path=(. /bin); whatis rm} /bin/rm)
	fail rm isn''''t in bin!?

expect list of signal handlers
whatis -s

expect list of variables and functions
whatis

submatch 'whatis -x' 'whatis: bad option: -x' 'bad option to whatis'

submatch 'whatis /frobnatz' '/frobnatz not found' 'search for /frobnatz'

if (~ `{whatis limit >[2]/dev/null} builtin) {
	limit coredumpsize 0
	if (!~ `{limit coredumpsize} 0*)
		fail failed to set coredumpsize to zero
	if (!~ `` () {limit coredumpsize} `` () {limit|grep coredumpsize})
		fail limit limit
	submatch 'limit foo' 'no such limit' 'bad limit'
}

fn cd

submatch 'cd a b c' 'rc: too many arguments to cd' 'cd arg count'
$rc -c 'cdpath=() cd /frobnatz' >[2]/dev/null && fail 'cd to /frobnatz succeeded!?'
submatch 'cdpath='''' cd frobnatz' 'couldn''t cd to frobnatz' 'cd to frobnatz succeeded!?'

'if'=keyword {
	{whatis if | fgrep '''if''=keyword' >/dev/null} || fail whatis of keyword is not quoted
}

#
# wait
#

submatch 'wait foo' 'rc: `foo'' is a bad number' 'bogus argument to wait'
$rc -c 'wait 1' >[2]/dev/null && fail wait 1

sleep 2&
~ $#apid 1 || fail 'empty $apid'
~ $apid $"apids || fail '$apid should match $apids'
wait $apid || fail 'wait 1 arg'

submatch 'exec >[2]/dev/null;true&false&true&true&false& wait $apids; echo $status' '0 1 0 0 1' 'multi wait'
submatch 'wait 0' 'rc: `0'' is not a child' 'multi wait invalid pid'

if (~ `` '' {wait} ?)
	fail waiting for nothing

#
# matching
#
touch $tmpdir/abc.$pid $tmpdir/bbc.$pid
mkdir $tmpdir/dir.$pid $tmpdir/dip.$pid
touch $tmpdir/dir.$pid/^(a b c) $tmpdir/dip.$pid/^(a b c)

if (!~ 123 [~x]?[0-9])
	fail match
if (!~ () *)
	fail match of null list with '*'
if (~ () *v*)
	fail match of null list with '*v*' succeeded
if (!~ (foo bar zar) *****z*****)
	fail match of list by one pattern failed
if (~ (foo bar zar) *c*)
	fail bad match
if (!~ [aaa [aaa)
	fail bad rangematch
if (!~ ']' []])
	fail match right bracket
if (~ x [y])
	fail rangematch out of range
if (~ x x?)
	fail too many characters in pattern

sh -c 'test -f /////$tmpdir//////a?c.'^$pid || fail glob with many slashes
if (!~ /////$tmpdir//////a*.$pid /////$tmpdir//////a?c.$pid)
	fail glob with many slashes
if (!~ ////$tmpdir////di?.$pid////* ////$tmpdir////dir.$pid////*b*)
	fail glob with more slashes
if (! @{cd $tmpdir; ~ *.$pid/a d*/*})
	fail glob in current directory
if (!~ $tmpdir/?bc.$pid $tmpdir/bbc.$pid)
	fail match of bbc.$pid against '('abc.$pid bbc.$pid')'

rm $tmpdir/abc.$pid $tmpdir/bbc.$pid
rm -rf $tmpdir/dir.$pid $tmpdir/dip.$pid

#
# signals
#
fn sigint {eval}
kill -2 $pid
fn sigint

#
# path searching
#
$rc -c /frobnatz >[2]/dev/null && fail 'search error'

touch $tmpdir/noexec.$pid
chmod a-x $tmpdir/noexec.$pid
$rc -c $tmpdir/noexec.$pid >[2]/dev/null && fail $tmpdir/noexec.$pid is found!?
rm $tmpdir/noexec.$pid

submatch 'path='''' frobnatz' 'rc: cannot find `frobnatz''' 'search error'

{path=() /bin/sh -c 'exit 0'} || fail abs pathname with path set to null

#
# options
#

# this test is meaningless; not really a trip
expect prompt, echo hi
home=/frobnatz $rc -nolpeivdxc 'echo hi'
if (!~ `` $nl {$rc -c>[2=1]} *': option requires an argument -- c')
	fail getopt on -c
if (!~ `` $nl {$rc -q>[2=1]} *': bad option: -q')
	fail getopt on -q (bogus option)
if (!~ `{echo '#echo' | $rc -v |[2] sed 's/#//'} echo)
	fail rc -v

#
# dot
#

if (~ `` '' . ?*)
	fail null dot
if (~ `` '' {. -i} ?*)
	fail null dot -i

cat > $tmpdir/dot.$pid << eof
echo hi
eof

prompt=';' if (!~ `` '' {. -i $tmpdir/dot.$pid>[2=1]} ';hi'^$nl';')
	fail dot -i
submatch .' '$tmpdir/dot.$pid hi dot

rm $tmpdir/dot.$pid

$rc -c '. /frobnatz' >[2]/dev/null && fail 'dot of a nonexistent file'

#
# stdin
#
if (!~ `{echo echo hi | $rc} hi)
	fail piping stdin to rc

#
# functions, variables & environment
#
fn --- {for(i)a|[2=3]b>>c<<<e&f>[2=1]}

if (whatis printenv >/dev/null>[2=1]) {
	printenv=printenv
} else if (whatis env >/dev/null>[2=1]) {
	printenv=env
} else
	printenv=()

if (~ $#printenv 1 && !~ `` $nl {$printenv | grep fn___2d__2d__2d} 'fn___2d__2d__2d={for(i in $*)a|[2=3]b >>c <<<e&f >[2=1]}')
	fail protect_env

fn --- {replace}
~ `{whatis -- ---} *replace* || fail replace a function definition
fn ---
whatis -- --- >[2]/dev/null && fail function deletion
foo=bar *=bar
foo=nest *=nest {
	~ $foo nest || fail local assignment
	~ $* nest || fail local assignment to '$*'
	foo=()
	*=()
	~ $foo () || fail local deletion
	~ $* () || fail local deletion to '$*'
}
~ $foo bar || fail restore of global after local group
~ $* bar || fail restore of '$*' after local group
~ `{exec>[2=1];$rc -xc 'foo=()'} 'foo=()' || fail -x echo of variable deletion

fn_ff='{' prompt='' if (!~ `` $nl {$rc -cff>[2=1]} 'rc: line 1: '*' error near eof')
	fail 'bogus function in environment'

#
# statuses
#
~ `{$rc -ec 'sleep 10&kill -9 $apid;wait'>[2=1]} killed ||
	fail status diagnostic

$rc -c 'exit 0 sigfpe' && fail exit of bad pipeline is true

submatch 'exit foo' 'bad status' 'exit diagnostic'

#
# control structures
#
if (!~ `{false || echo hi} hi)
	fail '||'
if (!~ `{true && echo hi} hi)
	fail '&&'
if (~ `{true || echo hi} hi)
	fail '||'
if (~ `{false && echo hi} hi)
	fail '&&'

while (false)
	fail false while
while (true) {
	break
	fail break in while
}

switch (foo) {
	case bar
		fail matched bar in switch
	case foo
		eval
	case *
		fail match foo in switch
}

switch (nothing) {
	case bar
		fail matched bar in switch
	case *
		i=frobnatz
}

~ $i frobnatz || fail match '*' in switch

submatch '()=()' 'rc: null variable name' 'assignment diagnostic'
submatch 'fn () {eval}' 'rc: null function name' 'assigning null function name'

#
# prompt
#
fn prompt {echo hi}
prompt=() if (!~ `{$rc -i /dev/null>[2]/dev/null} hi) fail fn prompt
fn prompt

#
# history
#
history=$tmpdir/hist.$pid prompt='' echo 'history=()' | $rc -i

if (!~ `{cat $tmpdir/hist.$pid} 'history=()')
	fail output to history file

history=$tmpdir/hist.$pid prompt='' echo 'history=()' | $rc -i

if (!~ `` () {cat $tmpdir/hist.$pid} 'history=()
history=()
')
	fail append to history file

rm $tmpdir/hist.$pid

if (!~ `{history=/frobnatz/foo prompt='' echo eval | $rc -i >[2=1]} ?*)
	fail accessing bad history file

#
# regression
#

expect date
{ date & wait } |cat

# Making rc's input non-blocking should have no untoward side effects.
x=`{ { sleep 1; echo echo foo } | { ./tripping n; $rc >[2=1] } }
if (!~ foo $x)
	fail input file descriptor nonblocking

# `rc -s' reads from stdin, but should not imply `-i'
expect foo bar qux
$rc -s foo bar qux <<'eof'
echo $*
eof

# Believe it or not, I broke root directory globbing in rc-1.6b1.
x=/*
~ '/*' $^x && fail root directory globbing

# fn sigexit should be cleared in children

x = ()
expect rc: cannot find '`nonesuch'''
x = `{true | nonesuch}; if (~ $x trip) fail sigexit in children
x = `{ < /dev/null wc |grep xxx }; if (~ $x trip) fail sigexit in children
x = `{{ wc | wc } < /dev/null }; if (~ $x trip) fail sigexit in children

# core dumps in glob.c
~ () '*' && fail globber problem
~ () '**' && fail globber problem

# check for ctrl-a bug
x=`{./tripping a}
~ `{$rc -c 'echo $x'} $x || fail ctrl-a bug detected

# check for hilarious quoting bug introduced while fixing ctrl-a
x=('#' '#' '#')
eval z^`{whatis -v x}
~ $#zx 3 || fail hilarious quoting bug

# parens bypass quote detector bug
fn x {echo x.y $(x.y)}
~ ``''{whatis -f x} 'fn x {echo x.y $(x^.y)}
' || fail sneaky parens bug

# before rc-1.7.1, certain glob patterns could fail on broken symlinks
mkdir $tmpdir/qux
ln -s /frobnatz $tmpdir/qux/foo
x=$tmpdir/qux/foo*
~ $x $tmpdir/qux/foo || { rm -rf $tmpdir/qux; fail broken symlink globbing }
x=$tmpdir/qux*/foo
~ $x $tmpdir/qux/foo || { rm -rf $tmpdir/qux; fail broken symlink globbing }

rm -rf $tmpdir

#############################################################################
## Check builtin continue in while loop.
#############################################################################
q=''''
C=$q^while-continue$q
L=()

save_star = *
ten = a^(1 2 3 4 5 6 7 8 9 10)
* = $ten
while (! ~ $#* 0) {
  n = $1; shift
  if (~ $n a2 a3) {
    continue
  }
  L=($L $n)
}
* = $save_star; save_star = ()

if (!~ $#L 8) {
  fail Wrong length of list from $C: $#L
}
if (!~ $L(1) a1) {
  fail First element of $C list is not a1: $L(1)
}
if (!~ $L(2) a4) {
  fail Second element of $C list is not a4: $L(2)
}
C=() L=()

#############################################################################
## Check builtin continue in for loop.
#############################################################################
C=$q^for-continue$q
L=()

for (x in a b c d e f g) {
  if (~ $x c f) {
    continue
  }
  L=($L $x)
}
if (!~ $#L 5) {
  fail Wrong length of list from $C
}
if (!~ $L(1) a) {
  fail First element of $C list is not a: $L(1)
}
if (!~ $L(3) d) {
  fail Third element of $C list is not d: $L(3)
}
if (!~ $L(5) g) {
  fail Fifth element of $C list is not g: $L(5)
}
C=() L=()

submatch continue 'rc: continue outside of loop' 'continue outside of loop'

#############################################################################
## check builtin continue in for loop (2)
#############################################################################
L=()
for (x in a b c d e f g) {
  if (~ $x b d) {
    continue
  }
  L=($L $x)
  if (~ $x f) {
    break;
  }
}

if (!~ $^L 'a c e f') {
  fail List should be '(a c e f)', but is $L
}

# test support for unquoted =
submatch 'echo foo = bar' 'foo = bar' 'unquoted equals 1'
submatch 'echo foo=bar' 'foo=bar' 'unquoted equals 2'
submatch 'echo foo=' 'foo=' 'unquoted equals 3'
submatch 'echo =bar; whatis -v echo' 'echo=bar' 'unquoted equals 4'

# test for github issue #34
X=`{ $rc -ec 'b=true; while($b){b=false}; echo YYY' }
if (! ~ $X YYY) {
    fail '"rc -e" exits when condition in the while statement fails in the second iteration'
}

# test for counter intuitive redirection parse
A=``($nl){ $rc -c 'mkdir / >[2=1] | tr a-z A-Z' }
B=``($nl){ $rc -c '>[2=1] mkdir / | tr a-z A-Z' }
~ $A $B || fail counter intuitive redirection bug, $A '!=' $B

# test for github issue #40
$rc -ec 'false | false'
if (~ $status 0) {
	fail '"rc -e" exits with zero status when command in pipeline returns non-zero'
}
$rc -ec 'X=`{false}'
if (~ $status 0) {
	fail '"rc -e" exits with zero status when backquote command returns non-zero'
}

# exercise flag builtin
submatch 'flag' 'rc: not enough arguments to flag' 'flag no args'
submatch 'flag a b c' 'usage: flag f [ + | - ]' 'flag 3 args'
submatch 'flag xx' 'usage: flag f [ + | - ]' 'flag wrong first arg'
submatch 'flag x x' 'usage: flag f [ + | - ]' 'flag wrong second arg'
submatch 'flag c && echo yes' yes 'flag c'
submatch 'flag x +; flag x -' 'flag x -' 'setting x flag'
