From f7c3154b8a0108ddeecdbd5afc3ac2c99124aab6 Mon Sep 17 00:00:00 2001 From: pommicket Date: Mon, 14 Feb 2022 22:43:25 -0500 Subject: strtoul, strtol --- 05/main.c | 6 +++ 05/parse.b | 12 +++++- 05/stdc_common.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) diff --git a/05/main.c b/05/main.c index ced784d..6b7aac7 100644 --- a/05/main.c +++ b/05/main.c @@ -1,7 +1,13 @@ +#define _STDLIB_DEBUG #include #include 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; } diff --git a/05/parse.b b/05/parse.b index ec92853..9cc0f39 100644 --- a/05/parse.b +++ b/05/parse.b @@ -802,7 +802,9 @@ function parse_statement :local_decl_initializer 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) out += 24 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;` token = n 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 >= 3 rwdata_end_addr <= 3 diff --git a/05/stdc_common.h b/05/stdc_common.h index e4527b8..d9e66f1 100644 --- a/05/stdc_common.h +++ b/05/stdc_common.h @@ -1,6 +1,11 @@ #ifndef _STDC_COMMON_H #define _STDC_COMMON_H +#ifdef _STDLIB_DEBUG +int printf(char *); +#endif + + #define signed #define volatile #define register @@ -20,6 +25,35 @@ typedef long ptrdiff_t; typedef unsigned long uintptr_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[] = { // mov rax, [rsp+24] 0x48, 0x8b, 0x84, 0x24, 24, 0, 0, 0, @@ -141,6 +175,85 @@ size_t strlen(char *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 { int fd; -- cgit v1.2.3