start string initializers
This commit is contained in:
parent
44e11303be
commit
22859ac40a
3 changed files with 48 additions and 28 deletions
17
05/main.c
17
05/main.c
|
@ -27,20 +27,9 @@
|
|||
/* typedef int x[sizeof(A)+sizeof"hello"]; */
|
||||
/* typedef int y[sizeof(struct B)]; */
|
||||
|
||||
static unsigned int x;
|
||||
static unsigned int y;
|
||||
static unsigned int z[1000];
|
||||
static unsigned int w;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
} Test;
|
||||
|
||||
int a = -138;
|
||||
double f = 0;
|
||||
void *p = 0;
|
||||
int j = 3+7<<5, k = 123;
|
||||
|
||||
static unsigned int x=55;
|
||||
static char *s = "hello";
|
||||
static char *t = "goodbye";
|
||||
/*
|
||||
NOTE: THIS MUST WORK
|
||||
int x[] = {1,2,3}
|
||||
|
|
57
05/parse.b
57
05/parse.b
|
@ -229,7 +229,7 @@ function parse_tokens
|
|||
; advances *p_token to the token right after the initializer
|
||||
; if `type` refers to a sizeless array type (e.g. int x[] = {1,2,3};), it will be altered to the correct size
|
||||
; outputs the initializer data to rwdata_end_addr, and advances it accordingly.
|
||||
; after calling this, make sure you update rwdata_end_addr to a multiple of 8 if necessary
|
||||
; after calling this, make sure to align rwdata_end_addr properly
|
||||
function parse_constant_initializer
|
||||
argument p_token
|
||||
argument type
|
||||
|
@ -272,6 +272,9 @@ function parse_constant_initializer
|
|||
|
||||
if *1token == SYMBOL_LBRACE goto parse_braced_initializer
|
||||
if *1token == TOKEN_STRING_LITERAL goto parse_string_literal_initializer
|
||||
|
||||
; an ordinary expression
|
||||
|
||||
p = types + type
|
||||
if *1p > TYPE_POINTER goto expression_initializer_for_nonscalar_type
|
||||
|
||||
|
@ -284,7 +287,6 @@ function parse_constant_initializer
|
|||
c = type_sizeof(type)
|
||||
p = output_file_data + rwdata_end_addr
|
||||
rwdata_end_addr += c
|
||||
*8p_token = end
|
||||
if c == 1 goto write_initializer1
|
||||
if c == 2 goto write_initializer2
|
||||
if c == 4 goto write_initializer4
|
||||
|
@ -295,27 +297,52 @@ function parse_constant_initializer
|
|||
byte 0
|
||||
:write_initializer1
|
||||
*1p = value
|
||||
return
|
||||
goto const_init_ret
|
||||
:write_initializer2
|
||||
*2p = value
|
||||
return
|
||||
goto const_init_ret
|
||||
:write_initializer4
|
||||
*4p = value
|
||||
return
|
||||
goto const_init_ret
|
||||
:write_initializer8
|
||||
*8p = value
|
||||
return
|
||||
|
||||
|
||||
goto const_init_ret
|
||||
:init_floating_check ; also checks pointer types (e.g. don't do static void *x = 1;)
|
||||
if value != 0 goto floating_initializer_other_than_0
|
||||
goto init_good
|
||||
|
||||
:const_init_ret
|
||||
*8p_token = end
|
||||
return
|
||||
|
||||
:parse_braced_initializer
|
||||
byte 0xcc ; @TODO
|
||||
:parse_string_literal_initializer
|
||||
byte 0xcc ; @TODO
|
||||
|
||||
p = token + 16
|
||||
if p != end goto stuff_after_string_literal
|
||||
p = types + type
|
||||
if *1p == TYPE_ARRAY goto string_literal_array_initializer
|
||||
if *1p != TYPE_POINTER goto string_literal_bad_type
|
||||
p += 1
|
||||
if *1p != TYPE_CHAR goto string_literal_bad_type
|
||||
token += 8
|
||||
p = output_file_data + rwdata_end_addr
|
||||
*8p = *8token
|
||||
rwdata_end_addr += 8
|
||||
goto const_init_ret
|
||||
|
||||
:string_literal_array_initializer
|
||||
byte 0xcc
|
||||
:stuff_after_string_literal
|
||||
token_error(token, .str_stuff_after_string_literal)
|
||||
:str_stuff_after_string_literal
|
||||
string Stuff after string literal in initializer.
|
||||
byte 0
|
||||
:string_literal_bad_type
|
||||
token_error(token, .str_string_literal_bad_type)
|
||||
:str_string_literal_bad_type
|
||||
string Bad type for string literal initializer (i.e. not char* or char[]).
|
||||
byte 0
|
||||
:find_init_end_eof
|
||||
token_error(token, .str_find_init_end_eof)
|
||||
:str_find_init_end_eof
|
||||
|
@ -1890,10 +1917,13 @@ function evaluate_constant_expression
|
|||
byte 0
|
||||
:eval_cast
|
||||
p = types + type
|
||||
if *1p == TYPE_VOID goto eval_cast_bad_type
|
||||
if *1p > TYPE_UNSIGNED_LONG goto eval_cast_bad_type
|
||||
expr += 8
|
||||
c = *1p
|
||||
if c == TYPE_VOID goto eval_cast_bad_type
|
||||
; @NONSTANDARD: we don't support, for example, int x[(int)(float)5];
|
||||
if c == TYPE_FLOAT goto eval_cast_bad_type
|
||||
if c == TYPE_DOUBLE goto eval_cast_bad_type
|
||||
if c > TYPE_POINTER goto eval_cast_bad_type
|
||||
expr += 8
|
||||
expr = evaluate_constant_expression(token, expr, p_value)
|
||||
goto eval_fit_to_type
|
||||
:eval_cast_bad_type
|
||||
|
@ -2124,6 +2154,7 @@ function fit_to_type
|
|||
if c == TYPE_UNSIGNED_INT goto fit_to_type_uint
|
||||
if c == TYPE_LONG goto fit_to_type_long
|
||||
if c == TYPE_UNSIGNED_LONG goto fit_to_type_ulong
|
||||
if c == TYPE_POINTER goto fit_to_type_ulong
|
||||
fputs(2, .str_bad_fit_to_type)
|
||||
exit(1)
|
||||
:str_bad_fit_to_type
|
||||
|
|
|
@ -103,7 +103,7 @@ function get_keyword_str
|
|||
; uchar info
|
||||
; ushort file
|
||||
; uint line
|
||||
; ulong data
|
||||
; ulong data -- for int/float literals, the value; for string literals, the runtime address; for identifiers, the name of the identifier
|
||||
; This corresponds to translation phases 5-6 and the first half of 7
|
||||
; IMPORTANT: this function uses pointers to pptokens, so it should NOT be freed!
|
||||
; Returns a pointer to the end of tokens.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue