kvisc/ka/crt/fmt/doprnt.k

200 lines
3.3 KiB
Plaintext
Raw Normal View History

2019-06-17 20:59:30 +02:00
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; typedef int (*PUTC)(int ch)
2019-06-19 13:50:53 +02:00
; int doprnt(PUTC putc, int n, const char *fmt, va_list ap)
2019-06-17 20:59:30 +02:00
;
2019-06-19 13:50:53 +02:00
doprnt:
2019-06-17 20:59:30 +02:00
enter 8
2019-07-04 20:33:49 +02:00
2019-06-17 20:59:30 +02:00
mov q[rbp-8], rbx
mov q[rbp-16], nx0
mov q[rbp-24], nx1
2019-07-17 22:25:50 +02:00
mov q[rbp-32], rdi
mov q[rbp-40], rsi
mov q[rbp-48], nx3
2019-06-17 20:59:30 +02:00
mov rbx, ax2 ; fmt
mov nx3, ax0 ; putc
mov nx0, ax1 ; n
2019-07-17 22:25:50 +02:00
mov rsi, ax3 ; va_list
mov nx1, zero ; return value
2019-06-17 20:59:30 +02:00
.main_loop:
; find '%' or null-terminator
mov rcx, STRLEN_MAX
mov rdi, rbx
scasb.rep.nz rdi, '%'
; everything below rdi is a regular character; print it
2019-07-15 20:46:00 +02:00
.print_regular:
b.z rbx, rdi, .check_modf
2019-06-17 20:59:30 +02:00
mov ax0, b[rbx]
call .doput
inc rbx
jmp .print_regular
.check_modf:
; did we find a '%' ?
2019-07-02 20:13:05 +02:00
; if not, then we found fmt's null-terminator; we're done
b.nz b[rbx], '%', .epilogue
2019-06-17 20:59:30 +02:00
; we did find a modifier / '%'
mov rax, b[rbx+1]
2019-07-17 22:25:50 +02:00
add rbx, rbx, 2
2019-06-17 20:59:30 +02:00
2019-07-15 20:46:00 +02:00
b.z rax, 's', .modf_s
b.z rax, 'c', .modf_c
b.z rax, 'p', .modf_p
b.z rax, 'x', .modf_x
b.z rax, 'd', .modf_d
b.z rax, 'o', .modf_o
b.z rax, 'b', .modf_b
b.z rax, '%', .modf_percent
2019-07-02 20:13:05 +02:00
2019-06-17 20:59:30 +02:00
; unrecognized
jmp .bad_modifier
.modf_s:
; get string address
2019-07-17 22:25:50 +02:00
mov rdi, q[rsi]
add rsi, rsi, 8
2019-06-17 20:59:30 +02:00
2019-07-17 22:25:50 +02:00
cmp rdi, zero
jmp.z .nullstring
2019-06-17 20:59:30 +02:00
.print_string:
mov ax0, b[rdi]
2019-07-17 22:25:50 +02:00
cmp ax0, zero
jmp.z .main_loop
2019-06-17 20:59:30 +02:00
inc rdi
call .doput
jmp .print_string
.modf_c:
2019-07-17 22:25:50 +02:00
mov ax0, q[rsi]
add rsi, rsi, 8
2019-06-17 20:59:30 +02:00
call .doput
jmp .main_loop
.modf_p:
mov ax0, '0'
call .doput
mov ax0, 'x'
call .doput
; Fallthrough
.modf_x:
mov ax2, 16
jmp .print_number
.modf_d:
mov ax2, 10
jmp .print_number
.modf_o:
mov ax2, 8
jmp .print_number
.modf_b:
mov ax2, 2
jmp .print_number
.print_number:
2019-06-18 12:58:26 +02:00
; allocate itoa conversion buffer
2019-07-17 22:25:50 +02:00
sub rsp, rsp, 80
2019-06-17 20:59:30 +02:00
mov rdi, rsp
2019-06-20 12:31:36 +02:00
; assume modifier already set up ax2
2019-06-17 20:59:30 +02:00
mov ax0, rsp
2019-07-17 22:25:50 +02:00
mov ax1, q[rsi]
2019-06-20 12:31:36 +02:00
call itoa
2019-07-17 22:25:50 +02:00
add rsi, rsi, 8
2019-06-17 20:59:30 +02:00
.print_itoa_buf:
mov ax0, b[rdi]
2019-07-04 20:33:49 +02:00
2019-07-17 22:25:50 +02:00
cmp ax0, zero
add.z rsp, rsp, 80
jmp.z .main_loop
2019-06-17 20:59:30 +02:00
inc rdi
call .doput
jmp .print_itoa_buf
.modf_percent:
mov ax0, '%'
call .doput
jmp .main_loop
.bad_modifier:
; print "%?" to clearly indicate that something is wrong
2019-06-27 23:00:35 +02:00
mov ax0, '%'
2019-06-17 20:59:30 +02:00
call .doput
mov ax0, '?'
call .doput
jmp .main_loop
.nullstring:
; %s was passed a NULL
mov ax0, '('
call .doput
mov ax0, 'n'
call .doput
mov ax0, 'u'
call .doput
mov ax0, 'l'
call .doput
mov ax0, 'l'
call .doput
mov ax0, ')'
call .doput
jmp .main_loop
.epilogue:
mov rax, nx1
mov rbx, q[rbp-8]
mov nx0, q[rbp-16]
mov nx1, q[rbp-24]
2019-07-17 22:25:50 +02:00
mov rdi, q[rbp-32]
mov rsi, q[rbp-40]
mov nx3, q[rbp-48]
2019-06-17 20:59:30 +02:00
leave
ret
;
; prints ax0
;
.doput:
; update print count
inc nx1
; if n==0, don't print
; we follow the C convention that sprintf()-like functions
; should return the number of characters that would have
; been printed/written if 'n' were big enough
2019-07-17 22:25:50 +02:00
cmp nx0, zero
2019-06-17 20:59:30 +02:00
ret.z
2019-06-27 23:00:35 +02:00
2019-06-17 20:59:30 +02:00
; if n>0, decrement n and print
dec nx0
call nx3
; did putc fail?
2019-07-17 22:25:50 +02:00
cmp rax, zero
mov.nz nx0, zero ; yes, so artificially set n=0
2019-06-17 20:59:30 +02:00
ret