kvisc/ka/usr/cmd/dir.k

141 lines
2.2 KiB
Plaintext

; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
N := 11
builtins.dir:
push rbp
mov rbp, rsp
push r12
push r13
mov r12, zero # no. of files found
call print, .dirmsg
.first:
mov rax, Sys.FindFirst
mov ax0, .buf
mov ax1, FNAME_MAX
trap 0
jmp .list
.next:
mov rax, Sys.FindNext
mov ax0, .buf
mov ax1, FNAME_MAX
trap 0
.list:
mov r13, rcx # file size
jmp.axz .end
; found something
inc r12, 1
; directory?
jmp.dxnz .is_dir
; separate extension from file name
mov rcx, FNAME_MAX
mov rsi, .buf
mov rdi, rsi
scasb.rep.nz rsi, '.'
; print file name
sub rcx, rsi, rdi
prns.rep rdi
; calculate where to put extension
sub rdi, rsi, .buf
dec rdi, 1
.ext_pad:
; print at least N non-space characters before extension
b.ae rdi, N, .print_ext
prn ' '
inc rdi, 1
jmp .ext_pad
.print_ext:
; here we print at least 4 characters excluding '.'
mov rcx, 4
prn ' '
cmp b[rsi], '.'
inc.z rsi, 1
.print_ext.1:
b.z b[rsi], 0, .print_ext.2
; print and decrease rcx, unless it's already 0
prn b[rsi]
inc rsi, 1
dec.cxnz rcx, 1
jmp .print_ext.1
.print_ext.2:
; did we print at least 4 bytes?
jmp.cxz .print_bytes ; yes, carry on
prn.rep ' '
.print_bytes:
; print file size in bytes
mov rcx, 3
prn.rep ' '
shr rax, r13, 10
and r13, r13, 1023
push r13
push rax
call printf, .bytesstr
inc rsp, 16
.prepare_next:
; go find next entry
prn 10
jmp .next
.end:
push r12
call printf, .endstr1
inc rsp, 8
call print, .endstr2
pop r13
pop r12
leave
ret
; special case: direcory
.is_dir:
mov rcx, STRLEN_MAX
mov rdx, .buf
prns.rep.nz rdx
sub rcx, STRLEN_MAX, rcx
b.ae rcx, N, .is_dir.print_ext
sub rcx, N, rcx
prn.rep ' '
.is_dir.print_ext:
call print, .dir_ext
jmp .print_bytes
.buf = [FNAME_MAX]
.dir_ext = " <DIR>"
.endstr1 = " %d file(s)\n"
.endstr2 = " 0 dir(s)\n"
.dirmsg = "Directory of C:\\\n\n"
.bytesstr = "%d kilobytes + %d bytes"