summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--05/main.c17
-rw-r--r--05/parse.b57
-rw-r--r--05/tokenize.b2
3 files changed, 48 insertions, 28 deletions
diff --git a/05/main.c b/05/main.c
index 1c5fb4f..1f07113 100644
--- a/05/main.c
+++ b/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}
diff --git a/05/parse.b b/05/parse.b
index 4ab47a8..d556936 100644
--- a/05/parse.b
+++ b/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
diff --git a/05/tokenize.b b/05/tokenize.b
index e52b30a..977b162 100644
--- a/05/tokenize.b
+++ b/05/tokenize.b
@@ -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.