diff --git a/src/file.S b/src/file.S index b8da07d..76ccae6 100644 --- a/src/file.S +++ b/src/file.S @@ -1,53 +1,76 @@ .data -cat_buf: .space 4096 -endings_buf: .space 4097 +mod_buf_0: .space 36864 +mod_buf_1: .space 36864 .section .text -.globl cat_file, open_fd, cat_stdin +.globl cat_file, open_fd # Cat out the given file to stdout -# @param[in] a0: ptr to null-terminated file str. +# @param[in] a0: ptr to null-terminated file str. 0 = stdin # @param[out] a0: result code. cat_file: - addi sp, sp, -24 - sd s0, 0(sp) + addi sp, sp, -32 + sd s0, 0(sp) sd ra, 8(sp) - sd s1, 16(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 - addi sp, sp, -8 - sd ra, 0(sp) + beqz a0, 1f call open_fd - ld ra, 0(sp) - addi sp, sp, 8 + j 2f + 1: + li s0, 0 # stdin fd + 2: mv s0, a1 # put fd in s0 - la t1, show_ends - lb s1, 0(t1) # store if we show ends into s1 beqz a0, .LReadFileBlock # if we don't have an error, jump to reading li a0, 1 j .LCatFileRet - .LReadFileBlock: mv a0, s0 - la a1, cat_buf + 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 - beqz s1, .LNoEndingsWrite - mv a1, a0 - la a0, cat_buf - call _stdout_add_endings - j .LReadFileBlock + mv s2, a0 + li s1, 1 - .LNoEndingsWrite: - mv a2, a0 # load the amount of bytes read in previous step into bytes needed to write + 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 - la a1, cat_buf li a7, 64 ecall j .LReadFileBlock @@ -61,46 +84,8 @@ cat_file: ld s0, 0(sp) ld ra, 8(sp) ld s1, 16(sp) - addi sp, sp, 24 - ret - -# Cat out stdin to stdout -# @param[in] a0: Not used. -# @param[out] a0: Not used. -cat_stdin: - addi sp, sp, -16 - sd ra, 0(sp) - sd s0, 8(sp) - - la t1, show_ends - lb s0, 0(t1) # store if we show ends into s1 - - .LReadStdinBlock: - li a0, 0 - la a1, cat_buf - li a2, 4096 - li a7, 63 - ecall - blez a0, .LCatStdinRet # if we haven't read any bytes, EOF, close FD - - beqz s0, .LNoEndingsStdinWrite - mv a1, a0 - la a0, cat_buf - call _stdout_add_endings - j .LReadStdinBlock - - .LNoEndingsStdinWrite: - mv a2, a0 # move bytes read into bytes needed to write - li a0, 1 - la a1, cat_buf - li a7, 64 - ecall - j .LReadStdinBlock - - .LCatStdinRet: - ld ra, 0(sp) - ld s0, 8(sp) - addi sp, sp, 16 + ld s2, 24(sp) + addi sp, sp, 32 ret # Open fd @@ -128,8 +113,10 @@ open_fd: # Print to stdout while adding "$" characters. # @param[in] a0: ptr to null-terminated str. # @param[in] a1: length of str. +# @param[in] a2: mod buf. # @param[out] a0: result code. -_stdout_add_endings: +# @param[out] a1: bytes written to mod buf. +_add_endings: addi sp, sp, -72 sd s7, 64(sp) sd s6, 56(sp) @@ -147,7 +134,7 @@ _stdout_add_endings: li s2, 0 # set the cat_buf char counter to 0 li s3, 0 # set the endings_buf char counter to 0 - la s5, endings_buf + mv s5, a2 .LStdoutEndingsProcessChunk: add s4, s0, s2 # Calculate the offset address lb t6, 0(s4) @@ -161,14 +148,6 @@ _stdout_add_endings: addi s4, s4, 1 sb t5, 0(s4) # endings_buf[s2] = \n addi s3, s3, 2 - - li a0, 1 - la a1, endings_buf - mv a2, s3 - li a7, 64 - ecall - call _zero_endings_buf - li s3, 0 # reset endings_buf char counter j 2f 1: @@ -179,15 +158,9 @@ _stdout_add_endings: 2: addi s2, s2, 1 # inc cat_buf pointer blt s2, s1, .LStdoutEndingsProcessChunk - beqz s3, .LSkipEndingsPrint - li a0, 1 - la a1, endings_buf - mv a2, s3 - li a7, 64 - ecall - .LSkipEndingsPrint: li a0, 0 + mv a1, s3 ld s0, 0(sp) ld s1, 8(sp) @@ -200,16 +173,3 @@ _stdout_add_endings: ld s7, 64(sp) addi sp, sp, 72 ret - -_zero_endings_buf: - li t0, 0 - li t1, 4097 - - .LZeroEndingsBufByte: - la t2, endings_buf - add t2, t2, t0 - sb x0, 0(t2) - addi t0, t0, 1 - blt t0, t1, .LZeroEndingsBufByte - - ret diff --git a/src/main.S b/src/main.S index 3540ebb..def4c09 100644 --- a/src/main.S +++ b/src/main.S @@ -19,7 +19,7 @@ help: .equ HELP_LEN, . - help version: - .ascii "cat 1.1.0\n" + .ascii "cat 1.2.0\n" .ascii "Copyright (C) 2026 lexzach\n" .ascii "License MIT\n" .ascii "This is free software: you are free to change and redistribute it.\n" @@ -61,9 +61,9 @@ _start: addi sp, sp, -8 sd a0, 0(sp) call _is_known_flag - bnez a1, .LSkipArg # check if arg is flag ld a0, 0(sp) addi sp, sp, 8 + bnez a1, .LSkipArg # check if arg is flag call cat_file addi s2, s2, 1 bnez a0, .LReturnFileErr # error if failed @@ -74,7 +74,8 @@ _start: j .LMainReturnOk .LProcessStdin: - call cat_stdin + li a0, 0 + call cat_file j .LMainReturnOk .LReturnFileErr: