strtoul, strtol
This commit is contained in:
parent
0c5b34b8d0
commit
f7c3154b8a
3 changed files with 129 additions and 2 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
12
05/parse.b
12
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
|
||||
|
|
113
05/stdc_common.h
113
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue