kvisc/ka/crt/fmt/strtol.k

168 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)
;
2019-09-07 16:45:03 +02:00
; eax = integer extracted from str
; edx = pointer to first invalid byte
2019-06-23 20:56:04 +02:00
;
strtol:
mov ax2, 1
jmp strtoq
;
; int strtoul(const char *str, int base)
;
2019-09-07 16:45:03 +02:00
; eax = integer extracted from str
; edx = pointer to first invalid byte
2019-06-23 20:56:04 +02:00
;
strtoul:
2019-08-14 20:23:05 +02:00
nul ax2
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-09-07 16:45:03 +02:00
nul eax, esi
mov edx, ax0
2019-06-23 20:56:04 +02:00
; make sure base is in [2, 32]
2019-08-14 09:52:39 +02:00
beq ax1, 1, .bad
bltu 36, ax1, .bad
2019-06-23 20:56:04 +02:00
; empty string?
2019-09-07 16:45:03 +02:00
bzr b[edx], .done
2019-06-23 20:56:04 +02:00
.skip_spc:
2019-09-07 16:45:03 +02:00
bne b[edx], ' ', .no_spc
inc edx
2019-08-14 09:52:39 +02:00
jmp .skip_spc
2019-06-23 20:56:04 +02:00
2019-08-14 09:52:39 +02:00
.no_spc:
2019-06-23 20:56:04 +02:00
; skip +
2019-09-07 16:45:03 +02:00
bne b[edx], '+', .no_plus
inc edx
2019-06-23 20:56:04 +02:00
2019-08-14 09:52:39 +02:00
.no_plus:
; unsigned?
bzr ax2, .unsigned
2019-06-23 20:56:04 +02:00
; parse '-'
2019-09-07 16:45:03 +02:00
bne b[edx], '-', .unsigned
inc edx
mov esi, 1
2019-06-23 20:56:04 +02:00
.unsigned:
; base 0
2019-08-14 09:52:39 +02:00
bzr ax1, .base_0
2019-06-23 20:56:04 +02:00
; base prefix?
2019-09-07 16:45:03 +02:00
bne b[edx], '0', .main_loop
2019-06-23 20:56:04 +02:00
2019-09-07 16:45:03 +02:00
inc edx
movzx ecx, b[edx]
2019-06-23 20:56:04 +02:00
2019-07-02 20:13:05 +02:00
; "0x"/"0b" prefix
2019-09-08 19:04:07 +02:00
jecxz .done ; "0"
2019-09-07 16:45:03 +02:00
beq ecx, 'x', .parsed_0x
beq ecx, '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?
2019-09-07 16:45:03 +02:00
; if not, leave eax = 0 and *edx = 'x'
2019-08-14 09:52:39 +02:00
bne ax1, 16, .done
2019-06-23 20:56:04 +02:00
; else
2019-09-07 16:45:03 +02:00
inc edx
2019-06-23 20:56:04 +02:00
jmp .main_loop
.parsed_0b:
; are we in base 2?
2019-09-07 16:45:03 +02:00
; if not, leave eax = 0 and *edx = 'b'
2019-08-14 09:52:39 +02:00
bne ax1, 2, .done
2019-06-23 20:56:04 +02:00
; else
2019-09-07 16:45:03 +02:00
inc edx
2019-06-23 20:56:04 +02:00
jmp .main_loop
.base_0:
; guess base
2019-09-07 16:45:03 +02:00
beq b[edx], '0', .b0_not10
2019-08-14 09:52:39 +02:00
; must be base 10
mov ax1, 10
jmp .main_loop
.b0_not10:
2019-09-07 16:45:03 +02:00
inc edx
2019-06-23 20:56:04 +02:00
2019-09-07 16:45:03 +02:00
bne b[edx], 'x', .b0_not16
inc edx
2019-08-14 09:52:39 +02:00
mov ax1, 16
jmp .main_loop
2019-06-23 20:56:04 +02:00
2019-08-14 09:52:39 +02:00
.b0_not16:
2019-09-07 16:45:03 +02:00
bne b[edx], 'b', .b0_not2
inc edx
2019-08-14 09:52:39 +02:00
mov ax1, 2
jmp .main_loop
2019-06-23 20:56:04 +02:00
2019-08-14 09:52:39 +02:00
.b0_not2:
; take octal by default
2019-06-23 20:56:04 +02:00
mov ax1, 8
.main_loop:
2019-09-07 16:45:03 +02:00
movzx ecx, b[edx]
inc edx
2019-06-23 20:56:04 +02:00
2019-08-14 09:52:39 +02:00
; between 0 and 9?
2019-09-07 16:45:03 +02:00
bltu ecx, '0', .done
bltu '9', ecx, .not_digit10
2019-08-14 09:52:39 +02:00
; yes
2019-09-07 16:45:03 +02:00
sub ecx, '0'
2019-08-14 09:52:39 +02:00
jmp .next
2019-06-23 20:56:04 +02:00
2019-08-14 09:52:39 +02:00
.not_digit10:
2019-09-07 16:45:03 +02:00
bltu ecx, 'A', .done
bltu 'Z', ecx, .not_digitAZ
2019-06-23 20:56:04 +02:00
2019-09-07 16:45:03 +02:00
sub ecx, 55 ; 'A' - 10
2019-08-14 09:52:39 +02:00
jmp .next
.not_digitAZ:
2019-09-07 16:45:03 +02:00
bltu ecx, 'a', .done
bltu 'z', ecx, .done
2019-08-14 09:52:39 +02:00
2019-09-07 16:45:03 +02:00
sub ecx, 87 ; 'a' - 10
2019-08-14 09:52:39 +02:00
jmp .next
2019-06-23 20:56:04 +02:00
.next:
; too large for base?
2019-09-07 16:45:03 +02:00
blteu ax1, ecx, .done
2019-06-23 20:56:04 +02:00
2019-09-07 16:45:03 +02:00
mul eax, ax1
add eax, ecx
2019-06-23 20:56:04 +02:00
jmp .main_loop
.done:
; negative?
2019-09-07 16:45:03 +02:00
bzr esi, .r
2019-06-23 20:56:04 +02:00
; yes
2019-09-07 16:45:03 +02:00
neg eax
2019-08-14 09:52:39 +02:00
.r:
2019-06-23 20:56:04 +02:00
ret
.bad:
ret