From 2ecbb120e26b172436f22ed639f0d63256d85ea8 Mon Sep 17 00:00:00 2001 From: Andrew Ekstedt Date: Mon, 24 Apr 2023 23:24:38 -0700 Subject: [PATCH] echo: print newline even with no args, and add some tests --- Makefile | 4 ++-- echo.s | 33 +++++++++++++++++++------------ test/echo.sh | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/true.sh | 2 +- 4 files changed, 79 insertions(+), 16 deletions(-) create mode 100755 test/echo.sh diff --git a/Makefile b/Makefile index ef7e141..730358b 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,7 @@ LD = $(TARGET)-ld .SUFFIXES: .PHONY: all -all: true false cat env hexdump -#all: echo +all: true false cat env hexdump echo %: %.o $(LD) -o $@ $(filter %.o, $^) @@ -20,3 +19,4 @@ sorttest: lib/sort.o .PHONY: test test: @BIN=. test/true.sh + @BIN=. test/echo.sh diff --git a/echo.s b/echo.s index 2ed23a6..bf20d02 100644 --- a/echo.s +++ b/echo.s @@ -3,15 +3,14 @@ .option norelax .section .rodata -space_or_newline: - .ascii " ", "\n" +space: .ascii " " +newline: .ascii "\n" .text _start: # arguments are passed on the stack: # --bottom of stack-- # dd argc - # dd argv # dd argv[0] # dd ... # dd 0 @@ -19,7 +18,6 @@ _start: # dd ... # dd 0 ld s0, 0(sp) # get argc - #ld s1, 8(sp) # get argv add s1, sp, 8 # TODO: iovec @@ -38,6 +36,7 @@ _start: # write each argument li s11, 0 mv s2, s0 + la s8, space loop: # get argv[i] slli t0, s11, 3 @@ -61,21 +60,20 @@ loop: ecall bltz a0, write_error - # if not the last argument, print a space - # otherwise print a newline - # - # a1 = space_or_newline + (argc-s11 < 2) - la a1, space_or_newline - sub t0, s0, s11 - sltiu t0, t0, 2 - add a1, a1, t0 + # increment index + # if this was the last argument, break + addi s11, s11, 1 + bge s11, s0, end + # not the last argument, so print a space and loop li a7, 64 # sys_write li a0, 1 # stdout - #la a1, newline or space + mv a1, s8 # space li a2, 1 # size ecall + bltz a0, write_error + j loop step: # increment index and loop @@ -83,6 +81,15 @@ step: blt s11, s0, loop end: + # print a newline at the end, + # regardless of whether there were any arguments or not + li a7, 64 # sys_write + li a0, 1 # stdout + la a1, newline + li a2, 1 # size + ecall + bltz a0, write_error + li a7, 93 # exit li a0, 0 ecall diff --git a/test/echo.sh b/test/echo.sh new file mode 100755 index 0000000..68170bb --- /dev/null +++ b/test/echo.sh @@ -0,0 +1,56 @@ +#!/bin/bash +set -eu +set -o pipefail + +: ${BIN:=..} +: ${EMU:=qemu-riscv64} + +cmd=$BIN/echo +name=echo + +fail=0 +err() { + echo "FAIL $name: $*" + fail=1 +} + +# the shell strips the trailing newline when capturing output, +# which makes writing tests for echo a bit difficult + +out=$($EMU $cmd) +len=$($EMU $cmd | wc -c) +stat=$? +if [ "$out" != "" ]; then + err "expected a newline" +fi +if [ "$len" -ne 1 ]; then + err "expected len 1, got len $len" +fi +if [ "$stat" -ne 0 ]; then + err "exited with status code $stat, expected 0" +fi + + +out=$($EMU $cmd a b c) +stat=$? +if [ "$out" != "a b c" ]; then + err "expected 'a b c', got '$out'" +fi +if [ "$stat" -ne 0 ]; then + err "exited with status code $stat, expected 0" +fi + + +out=$($EMU $cmd 'a b') +stat=$? +if [ "$out" != "a b" ]; then + err "expected 'a b', got '$out'" +fi +if [ "$stat" -ne 0 ]; then + err "exited with status code $stat, expected 0" +fi + + +if [ "$fail" -eq 0 ]; then + echo PASS $name +fi diff --git a/test/true.sh b/test/true.sh index 5bba19f..5a43b86 100755 --- a/test/true.sh +++ b/test/true.sh @@ -2,7 +2,7 @@ set -eu set -o pipefail -: ${BIN:-..} +: ${BIN:=..} : ${EMU:=qemu-riscv64} cmd=$BIN/true