summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-02-14 22:43:25 -0500
committerpommicket <pommicket@gmail.com>2022-02-14 22:43:25 -0500
commitf7c3154b8a0108ddeecdbd5afc3ac2c99124aab6 (patch)
treeaffb47d70d6edb2f75cca5d800baed954fb8d1e1
parent0c5b34b8d082d980f0081ce818befdec46111b0b (diff)
strtoul, strtol
-rw-r--r--05/main.c6
-rw-r--r--05/parse.b12
-rw-r--r--05/stdc_common.h113
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 <stdio.h>
#include <string.h>
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;