kvisc/ka/crt/fmt/strtol.k

157 lines
2.5 KiB
Plaintext
Raw Normal View History

2019-06-23 20:56:04 +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.
;
; int strtol(const char *str, int base)
;
; rax = integer extracted from str
; rdx = pointer to first invalid byte
;
strtol:
mov ax2, 1
jmp strtoq
;
; int strtoul(const char *str, int base)
;
; rax = integer extracted from str
; rdx = pointer to first invalid byte
;
strtoul:
2019-07-17 22:25:50 +02:00
mov ax2, zero
2019-06-23 20:56:04 +02:00
jmp strtoq
;
; int strtoq(const char *str, int base, bool signed)
;
; guesses base when 'base'=0
;
strtoq:
2019-07-17 22:25:50 +02:00
mov rax, zero
2019-06-23 20:56:04 +02:00
mov rdx, ax0
; make sure base is in [2, 32]
2019-07-02 20:13:05 +02:00
b.z ax1, 1, .bad
b.a ax1, 36, .bad
2019-06-23 20:56:04 +02:00
; empty string?
2019-07-17 22:25:50 +02:00
b.z b[rdx], zero, .done
2019-06-23 20:56:04 +02:00
.skip_spc:
cmp b[rdx], ' '
2019-07-18 22:49:31 +02:00
add.z rdx, rdx, 1
2019-06-23 20:56:04 +02:00
jmp.z .skip_spc
; skip +
cmp b[rdx], '+'
2019-07-18 22:49:31 +02:00
add.z rdx, rdx, 1
2019-06-23 20:56:04 +02:00
; signed?
2019-07-17 22:25:50 +02:00
cmp ax2, zero
2019-07-22 13:18:13 +02:00
mov.z rsi, zero
2019-06-23 20:56:04 +02:00
jmp.z .unsigned
; parse '-'
cmp b[rdx], '-'
2019-07-18 22:49:31 +02:00
add.z rdx, rdx, 1
2019-07-22 13:18:13 +02:00
mov.z rsi, 1
mov.nz rsi, zero
2019-06-23 20:56:04 +02:00
.unsigned:
; base 0
2019-07-02 20:13:05 +02:00
b.z ax1, 0, .base_0
2019-06-23 20:56:04 +02:00
; base prefix?
2019-07-02 20:13:05 +02:00
b.nz b[rdx], '0', .main_loop
2019-06-23 20:56:04 +02:00
2019-07-18 22:49:31 +02:00
add rdx, rdx, 1
2019-07-02 20:13:05 +02:00
movzx rcx, b[rdx]
2019-06-23 20:56:04 +02:00
2019-07-02 20:13:05 +02:00
; "0x"/"0b" prefix
2019-07-22 14:41:50 +02:00
jmp.cxz .done ; "0"
2019-07-02 20:13:05 +02:00
b.z rcx, 'x', .parsed_0x
b.z rcx, 'b', .parsed_0b
2019-06-23 20:56:04 +02:00
; may be octal, but we don't care
2019-07-02 20:13:05 +02:00
; we accept "0110101010" (despite base=2) for instance
2019-06-23 20:56:04 +02:00
jmp .main_loop
.parsed_0x:
; are we in base 16?
; if not, leave rax = 0 and *rdx = 'x'
2019-07-02 20:13:05 +02:00
b.nz ax1, 16, .done
2019-06-23 20:56:04 +02:00
; else
2019-07-18 22:49:31 +02:00
add rdx, rdx, 1
2019-06-23 20:56:04 +02:00
jmp .main_loop
.parsed_0b:
; are we in base 2?
; if not, leave rax = 0 and *rdx = 'b'
2019-07-02 20:13:05 +02:00
b.nz ax1, 2, .done
2019-06-23 20:56:04 +02:00
; else
2019-07-18 22:49:31 +02:00
add rdx, rdx, 1
2019-06-23 20:56:04 +02:00
jmp .main_loop
.base_0:
; guess base
cmp b[rdx], '0'
mov.nz ax1, 10
jmp.nz .main_loop
2019-07-18 22:49:31 +02:00
add rdx, rdx, 1
2019-06-23 20:56:04 +02:00
cmp b[rdx], 'x'
2019-07-18 22:49:31 +02:00
add.z rdx, rdx, 1
2019-06-23 20:56:04 +02:00
mov.z ax1, 16
jmp.z .main_loop
cmp b[rdx], 'b'
2019-07-18 22:49:31 +02:00
add.z rdx, rdx, 1
2019-06-23 20:56:04 +02:00
mov.z ax1, 2
jmp.z .main_loop
mov ax1, 8
.main_loop:
2019-07-22 13:18:13 +02:00
movzx rcx, b[rdx]
2019-07-18 22:49:31 +02:00
add rdx, rdx, 1
2019-06-23 20:56:04 +02:00
2019-07-22 13:18:13 +02:00
cmp rcx, '0'
2019-06-23 20:56:04 +02:00
jmp.b .done
2019-07-22 13:18:13 +02:00
cmp.ae rcx, '9'
sub.be rcx, rcx, '0'
2019-06-23 20:56:04 +02:00
jmp.be .next
2019-07-22 13:18:13 +02:00
cmp rcx, 'A'
cmp.ae rcx, 'Z'
sub.be rcx, rcx, 55 ; 'A' - 10
2019-06-23 20:56:04 +02:00
jmp.be .next
2019-07-22 13:18:13 +02:00
cmp rcx, 'a'
2019-06-23 20:56:04 +02:00
jmp.b .next
2019-07-22 13:18:13 +02:00
cmp.ae rcx, 'z'
sub.be rcx, rcx, 87 ; 'a' - 10
2019-06-23 20:56:04 +02:00
jmp.be .next
.next:
; too large for base?
2019-07-22 13:18:13 +02:00
b.ae rcx, ax1, .done
2019-06-23 20:56:04 +02:00
2019-07-17 20:26:03 +02:00
mul rax, rax, ax1
2019-07-22 13:18:13 +02:00
add rax, rax, rcx
2019-06-23 20:56:04 +02:00
jmp .main_loop
.done:
; negative?
2019-07-22 13:18:13 +02:00
cmp rsi, zero
2019-06-23 20:56:04 +02:00
ret.z
; yes
2019-07-18 22:49:31 +02:00
sub rax, zero, rax
2019-06-23 20:56:04 +02:00
ret
.bad:
mov q[errno], EINVAL
ret