strtoul, strtol

This commit is contained in:
pommicket 2022-02-14 22:43:25 -05:00
parent 0c5b34b8d0
commit f7c3154b8a
3 changed files with 129 additions and 2 deletions

View file

@ -1,7 +1,13 @@
#define _STDLIB_DEBUG
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
int main(void) { int main(void) {
char s[] = " -0XAh.\n";
char *end;
errno = 0;
printf("%ld\n", strtol(s, &end, 0));
printf("%d:%s",errno,end);
return 0; return 0;
} }

View file

@ -802,7 +802,9 @@ function parse_statement
:local_decl_initializer :local_decl_initializer
token += 16 token += 16
if *1token == SYMBOL_LBRACE goto local_init_lbrace if *1token == SYMBOL_LBRACE goto local_const_init
if *1token == TOKEN_STRING_LITERAL goto maybe_string_init
:not_string_init
n = token_next_semicolon_comma_rbracket(token) n = token_next_semicolon_comma_rbracket(token)
out += 24 out += 24
p = expressions_end p = expressions_end
@ -813,7 +815,13 @@ function parse_statement
type_decay_array_to_pointer_in_place(*4p) ; fix typing for `int[] x = {5,6}; int *y = x;` type_decay_array_to_pointer_in_place(*4p) ; fix typing for `int[] x = {5,6}; int *y = x;`
token = n token = n
goto local_decl_continue goto local_decl_continue
:local_init_lbrace :maybe_string_init
; check if we have char x[] = "hello"; or char *x = "hello"; (we'll use parse_constant_initializer for that)
p = token + 16
if *1p == SYMBOL_SEMICOLON goto local_const_init
if *1p == SYMBOL_COMMA goto local_const_init
goto not_string_init
:local_const_init
rwdata_end_addr += 7 rwdata_end_addr += 7
rwdata_end_addr >= 3 rwdata_end_addr >= 3
rwdata_end_addr <= 3 rwdata_end_addr <= 3

View file

@ -1,6 +1,11 @@
#ifndef _STDC_COMMON_H #ifndef _STDC_COMMON_H
#define _STDC_COMMON_H #define _STDC_COMMON_H
#ifdef _STDLIB_DEBUG
int printf(char *);
#endif
#define signed #define signed
#define volatile #define volatile
#define register #define register
@ -20,6 +25,35 @@ typedef long ptrdiff_t;
typedef unsigned long uintptr_t; typedef unsigned long uintptr_t;
typedef long intptr_t; typedef long intptr_t;
#define INT8_MAX 0x7f
#define INT8_MIN (-0x80)
#define INT16_MAX 0x7fff
#define INT16_MIN (-0x8000)
#define INT32_MAX 0x7fffffff
#define INT32_MIN (-0x80000000)
#define INT64_MAX 0x7fffffffffffffff
#define INT64_MIN (-0x8000000000000000)
#define UINT8_MAX 0xff
#define UINT16_MAX 0xffff
#define UINT32_MAX 0xffffffff
#define UINT64_MAX 0xffffffffffffffff
#define CHAR_BIT 8
#define MB_LEN_MAX 4
#define CHAR_MIN INT8_MIN
#define CHAR_MAX INT8_MAX
#define SCHAR_MIN INT8_MIN
#define SCHAR_MAX INT8_MAX
#define INT_MIN INT32_MIN
#define INT_MAX INT32_MAX
#define LONG_MIN INT64_MIN
#define LONG_MAX INT64_MAX
#define SHRT_MIN INT16_MIN
#define SHRT_MAX INT16_MAX
#define UCHAR_MAX UINT8_MAX
#define USHRT_MAX UINT16_MAX
#define UINT_MAX UINT32_MAX
#define ULONG_MAX UINT64_MAX
static unsigned char __syscall_data[] = { static unsigned char __syscall_data[] = {
// mov rax, [rsp+24] // mov rax, [rsp+24]
0x48, 0x8b, 0x84, 0x24, 24, 0, 0, 0, 0x48, 0x8b, 0x84, 0x24, 24, 0, 0, 0,
@ -141,6 +175,85 @@ size_t strlen(char *s) {
return t - s; return t - s;
} }
int isspace(int c) {
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
}
unsigned long strtoul(const char *nptr, char **endptr, int base) {
unsigned long value = 0, newvalue;
int overflow = 0;
while (isspace(*nptr)) ++nptr;
if (*nptr == '+') ++nptr;
if (base == 0) {
if (*nptr == '0') {
++nptr;
switch (*nptr) {
case 'x':
case 'X':
base = 16;
++nptr;
break;
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
base = 8;
break;
default:
// this must just be the number 0.
if (endptr) *endptr = nptr;
return 0;
}
} else {
base = 10;
}
}
while (1) {
int c = *nptr;
unsigned v;
if (c >= '0' && c <= '9')
v = c - '0';
else if (c >= 'a' && c <= 'z')
v = c - 'a' + 10;
else if (c >= 'A' && c <= 'Z')
v = c - 'A' + 10;
else break;
if (v >= base) break;
unsigned long newvalue = value * base + v;
if (newvalue < value) overflow = 1;
value = newvalue;
++nptr;
}
*endptr = nptr;
if (overflow) {
errno = ERANGE;
return ULONG_MAX;
} else {
return value;
}
}
long strtol(const char *nptr, char **endptr, int base) {
int sign = 1;
while (isspace(*nptr)) ++nptr;
if (*nptr == '-') {
sign = -1;
++nptr;
}
unsigned long mag = strtoul(nptr, endptr, base);
if (sign > 0) {
if (mag > LONG_MAX) {
errno = ERANGE;
return LONG_MIN;
}
return (long)mag;
} else {
if (mag > (unsigned long)LONG_MAX + 1) {
errno = ERANGE;
return LONG_MIN;
}
return -(long)mag;
}
}
typedef struct { typedef struct {
int fd; int fd;