kvisc/ka/usr/cmd/dir.k

163 lines
2.6 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, r13
push r14, r15
nul r12 # no. of files found
nul r13 # no. of directories found
nul r14 # total amount of bytes 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:
jraxz .end
mov r15, rcx ; file size
inc r14, rcx
; directory?
bnz rdx, .is_dir
; found a file
inc r12, 1
; separate extension from file name
mov rcx, FNAME_MAX
mov rsi, .buf
mov rdi, rsi
scasb rsi, '.'
; print file name
sub ax1, rsi, rdi
dec ax1, 1
call nprint, rdi
; calculate where to put extension
sub rdi, rsi, .buf
dec rdi, 1
.ext_pad:
; print at least N non-space characters before extension
blte N, rdi, .print_ext
prn ' '
inc rdi, 1
jmp .ext_pad
.print_ext:
; here we print at least 4 characters excluding '.'
mov rcx, 4
prn ' '
bne b[rsi], '.', .print_ext.1
inc rsi, 1
.print_ext.1:
bzr b[rsi], .print_ext.2
; print and decrease rcx, unless it's already 0
prn b[rsi]
inc rsi, 1
jrcxz .print_ext.1
dec rcx, 1
jmp .print_ext.1
.print_ext.2:
; did we print at least 4 bytes?
jrcxz .print_bytes ; yes, carry on
.pe2.l:
prn ' '
loop .pe2.l
.print_bytes:
; print file size in bytes
prn ' '
prn ' '
prn ' '
shr rax, r15, 10
and r15, 1023
push r15, rax
call printf, .bytesstr
inc rsp, 16
.prepare_next:
; go find next entry
prn 10
jmp .next
.end:
shr rax, r14, 10
shr rdx, rax, 10
and rax, 1023
and r14, 1023
push r14, rax, rdx
call printf, .endstr0
inc rsp, 24
push r13, r12
call printf, .endstr1
inc rsp, 16
pop r15, r14
pop r13, r12
leave
ret
; special case: direcory
.is_dir:
inc r13, 1
; use printf instead of print
; because it returns # of printed
; characters
call printf, .buf
blte N, rax, .dir_no_pad
sub rcx, N, rax
dec rcx, 1
.dir.l:
prn ' '
loop .dir.l
.dir_no_pad:
call print, .dir_ext
jmp .print_bytes
.buf = [FNAME_MAX]
.dir_ext = " <DIR> "
.endstr0 = " total %dMB + %dKB + %dB\n"
.endstr1 = " found %d file(s), %d dir(s)\n"
.dirmsg = "Directory of C:\\\n\n"
.bytesstr = "%d kilobytes + %d bytes"
# .bytesstr = "%dMB + %dKB + %dB" # too soon