; 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: mov ax2, zero jmp strtoq ; ; int strtoq(const char *str, int base, bool signed) ; ; guesses base when 'base'=0 ; strtoq: mov rax, zero mov rdx, ax0 ; make sure base is in [2, 32] b.z ax1, 1, .bad b.a ax1, 36, .bad ; empty string? b.z b[rdx], zero, .done .skip_spc: cmp b[rdx], ' ' inc.z rdx jmp.z .skip_spc ; skip + cmp b[rdx], '+' inc.z rdx ; signed? cmp ax2, zero mov.z r10, zero jmp.z .unsigned ; parse '-' cmp b[rdx], '-' inc.z rdx mov.z r10, 1 mov.nz r10, zero .unsigned: ; base 0 b.z ax1, 0, .base_0 ; base prefix? b.nz b[rdx], '0', .main_loop inc rdx movzx rcx, b[rdx] ; "0x"/"0b" prefix b.z rcx, zero, .done ; "0" b.z rcx, 'x', .parsed_0x b.z rcx, 'b', .parsed_0b ; may be octal, but we don't care ; we accept "0110101010" (despite base=2) for instance jmp .main_loop .parsed_0x: ; are we in base 16? ; if not, leave rax = 0 and *rdx = 'x' b.nz ax1, 16, .done ; else inc rdx jmp .main_loop .parsed_0b: ; are we in base 2? ; if not, leave rax = 0 and *rdx = 'b' b.nz ax1, 2, .done ; else inc rdx jmp .main_loop .base_0: ; guess base cmp b[rdx], '0' mov.nz ax1, 10 jmp.nz .main_loop inc rdx cmp b[rdx], 'x' inc.z rdx mov.z ax1, 16 jmp.z .main_loop cmp b[rdx], 'b' inc.z rdx mov.z ax1, 2 jmp.z .main_loop mov ax1, 8 .main_loop: movzx r12, b[rdx] inc rdx cmp r12, '0' jmp.b .done cmp.ae r12, '9' sub.be r12, r12, '0' jmp.be .next cmp r12, 'A' cmp.ae r12, 'Z' sub.be r12, r12, 55 ; 'A' - 10 jmp.be .next cmp r12, 'a' jmp.b .next cmp.ae r12, 'z' sub.be r12, r12, 87 ; 'a' - 10 jmp.be .next .next: ; too large for base? b.ae r12, ax1, .done mul rax, rax, ax1 add rax, rax, r12 jmp .main_loop .done: ; negative? cmp r10, zero ret.z ; yes neg rax, rax ret .bad: mov q[errno], EINVAL ret