.data mod_buf_0: .space 36864 mod_buf_1: .space 36864 .section .text .globl cat_file, open_fd # Cat out the given file to stdout # @param[in] a0: ptr to null-terminated file str. 0 = stdin # @param[out] a0: result code. cat_file: addi sp, sp, -32 sd s0, 0(sp) sd ra, 8(sp) sd s1, 16(sp) # next modbuf to WRITE TO (inverse is read) 0=modbuf_0, 1=modbuf_1 sd s2, 24(sp) # current modbuf byte count mv a1, a0 # since the function takes in a0, move it to a1 for syscall li s1, 1 li s2, 0 beqz a0, 1f call open_fd j 2f 1: li s0, 0 # stdin fd 2: mv s0, a1 # put fd in s0 beqz a0, .LReadFileBlock # if we don't have an error, jump to reading li a0, 1 j .LCatFileRet .LReadFileBlock: mv a0, s0 la a1, mod_buf_0 li a2, 4096 li a7, 63 ecall blez a0, .LCloseFD # if we haven't read any bytes, EOF, close FD mv s2, a0 li s1, 1 la t1, number_nonblank lb t1, 0(t1) beqz t1, .LNoNonblankNumbers mv a1, s2 # load mod buf size to a1 beqz s1, 1f la a0, mod_buf_0 # load mod_buf_0 as read buf la a2, mod_buf_1 # load mod_buf_1 as write buf j 2f 1: la a0, mod_buf_1 # load mod_buf_1 as read buf la a2, mod_buf_0 # load mod_buf_0 as write buf 2: call add_line_numbers xori s1, s1, 1 # flip the mod buf to write to mv s2, a1 # update the current byte count j .LNoNumbers # -n and -b are exclusive .LNoNonblankNumbers: la t1, number lb t1, 0(t1) beqz t1, .LNoNumbers mv a1, s2 # load mod buf size to a1 beqz s1, 1f la a0, mod_buf_0 # load mod_buf_0 as read buf la a2, mod_buf_1 # load mod_buf_1 as write buf j 2f 1: la a0, mod_buf_1 # load mod_buf_1 as read buf la a2, mod_buf_0 # load mod_buf_0 as write buf 2: call add_line_numbers xori s1, s1, 1 # flip the mod buf to write to mv s2, a1 # update the current byte count .LNoNumbers: la t1, show_ends lb t1, 0(t1) beqz t1, .LNoEndings mv a1, s2 # load mod buf size to a1 beqz s1, 1f la a0, mod_buf_0 # load mod_buf_0 as read buf la a2, mod_buf_1 # load mod_buf_1 as write buf j 2f 1: la a0, mod_buf_1 # load mod_buf_1 as read buf la a2, mod_buf_0 # load mod_buf_0 as write buf 2: call add_endings xori s1, s1, 1 # flip the mod buf to write to mv s2, a1 # update the current byte count .LNoEndings: beqz s1, 1f la a1, mod_buf_0 j 2f 1: la a1, mod_buf_1 2: mv a2, s2 # load the amount of bytes read in previous step into bytes needed to write li a0, 1 li a7, 64 ecall j .LReadFileBlock .LCloseFD: mv a0, s0 li a7, 57 # close fd ecall .LCatFileRet: ld s0, 0(sp) ld ra, 8(sp) ld s1, 16(sp) ld s2, 24(sp) addi sp, sp, 32 ret # Open fd # @param[in] a0: ptr to null-terminated file str. # @param[out] a0: result code. (0-exists 1-doesn't exist) # @param[out] a1: fd. open_fd: mv a1, a0 # since the function takes in a0, move it to a1 for syscall li a0, -100 # relative/absolute path li a2, 0 # readonly li a7, 56 # open ecall bltz a0, 1f # file doesn't exist mv a1, a0 # move fd to a1 li a0, 0 j 2f 1: li a0, 1 2: ret