diff --git a/src/defs.h b/src/defs.h index 2c2d1350..bdbb3425 100644 --- a/src/defs.h +++ b/src/defs.h @@ -270,6 +270,17 @@ typedef struct { typedef struct basic_block basic_block_t; +/* Definition of a dynamic array structure for sources in src/globals.c + * size: Current number of elements in the array + * capacity: Number of elements that can be stored without resizing + * elements: Pointer to the array of characters + */ +typedef struct { + int size; + int capacity; + char *elements; +} source_t; + /* phase-2 IR definition */ struct ph2_ir { opcode_t op; diff --git a/src/globals.c b/src/globals.c index a4a7e996..a4703517 100644 --- a/src/globals.c +++ b/src/globals.c @@ -56,8 +56,7 @@ int aliases_idx = 0; constant_t *CONSTANTS; int constants_idx = 0; -char *SOURCE; -int source_idx = 0; +source_t *SOURCE; /* ELF sections */ @@ -837,6 +836,62 @@ void add_insn(block_t *block, bb->insn_list.tail = n; } +source_t *create_source(int init_capacity) +{ + source_t *array = malloc(sizeof(source_t)); + if (!array) + return NULL; + + array->size = 0; + array->capacity = init_capacity; + array->elements = malloc(array->capacity * sizeof(char)); + if (!array->elements) { + free(array); + return NULL; + } + + return array; +} + +bool source_expand(source_t *src) +{ + if (src->size < src->capacity) + return true; + + src->capacity <<= 1; + char *new_arr = malloc(src->capacity * sizeof(char)); + + if (!new_arr) + return false; + + memcpy(new_arr, src->elements, src->size * sizeof(char)); + + free(src->elements); + src->elements = new_arr; + + return true; +} + +bool source_push(source_t *src, char value) +{ + if (!source_expand(src)) + return false; + + src->elements[src->size] = value; + src->size++; + + return true; +} + +void source_release(source_t *src) +{ + if (!src) + return; + + free(src->elements); + free(src); +} + /* This routine is required because the global variable initializations are * not supported now. */ @@ -855,7 +910,7 @@ void global_init() BB_ARENA = arena_init(DEFAULT_ARENA_SIZE); PH2_IR_FLATTEN = malloc(MAX_IR_INSTR * sizeof(ph2_ir_t *)); LABEL_LUT = malloc(MAX_LABEL * sizeof(label_lut_t)); - SOURCE = malloc(MAX_SOURCE); + SOURCE = create_source(MAX_SOURCE); ALIASES = malloc(MAX_ALIASES * sizeof(alias_t)); CONSTANTS = malloc(MAX_CONSTANTS * sizeof(constant_t)); @@ -887,7 +942,7 @@ void global_release() arena_free(BB_ARENA); free(PH2_IR_FLATTEN); free(LABEL_LUT); - free(SOURCE); + source_release(SOURCE); free(ALIASES); free(CONSTANTS); @@ -907,18 +962,20 @@ void error(char *msg) int offset, start_idx, i = 0; char diagnostic[512 /* MAX_LINE_LEN * 2 */]; - for (offset = source_idx; offset >= 0 && SOURCE[offset] != '\n'; offset--) + for (offset = SOURCE->size; offset >= 0 && SOURCE->elements[offset] != '\n'; + offset--) ; start_idx = offset + 1; - for (offset = 0; offset < MAX_SOURCE && SOURCE[start_idx + offset] != '\n'; + for (offset = 0; + offset < MAX_SOURCE && SOURCE->elements[start_idx + offset] != '\n'; offset++) { - diagnostic[i++] = SOURCE[start_idx + offset]; + diagnostic[i++] = SOURCE->elements[start_idx + offset]; } diagnostic[i++] = '\n'; - for (offset = start_idx; offset < source_idx; offset++) { + for (offset = start_idx; offset < SOURCE->size; offset++) { diagnostic[i++] = ' '; } @@ -927,7 +984,8 @@ void error(char *msg) /* TODO: figure out the corresponding C source file path and report line * number. */ - printf("Error %s at source location %d\n%s\n", msg, source_idx, diagnostic); + printf("Error %s at source location %d\n%s\n", msg, SOURCE->size, + diagnostic); abort(); } diff --git a/src/lexer.c b/src/lexer.c index 4933ea63..7b3cadba 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -158,13 +158,14 @@ void skip_whitespace() { while (true) { if (is_linebreak(next_char)) { - source_idx += 2; - next_char = SOURCE[source_idx]; + SOURCE->size += 2; + next_char = SOURCE->elements[SOURCE->size]; continue; } if (is_whitespace(next_char) || (skip_newline && is_newline(next_char))) { - next_char = SOURCE[++source_idx]; + SOURCE->size++; + next_char = SOURCE->elements[SOURCE->size]; continue; } break; @@ -173,7 +174,8 @@ void skip_whitespace() char read_char(bool is_skip_space) { - next_char = SOURCE[++source_idx]; + SOURCE->size++; + next_char = SOURCE->elements[SOURCE->size]; if (is_skip_space) skip_whitespace(); return next_char; @@ -181,7 +183,7 @@ char read_char(bool is_skip_space) char peek_char(int offset) { - return SOURCE[source_idx + offset]; + return SOURCE->elements[SOURCE->size + offset]; } /* Lex next token and returns its token type. Parameter 'aliasing' is used for @@ -601,8 +603,8 @@ token_t lex_token_internal(bool aliasing) */ if (next_char == '\n') { if (macro_return_idx) { - source_idx = macro_return_idx; - next_char = SOURCE[source_idx]; + SOURCE->size = macro_return_idx; + next_char = SOURCE->elements[SOURCE->size]; } else next_char = read_char(true); return lex_token_internal(aliasing); diff --git a/src/parser.c b/src/parser.c index ad18b5d5..cfa0100c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -408,7 +408,7 @@ bool read_preproc_directive() if (lex_accept(T_elipsis)) macro->is_variadic = true; - macro->start_source_idx = source_idx; + macro->start_source_idx = SOURCE->size; skip_macro_body(); } else { /* Empty alias, may be dummy alias serves as include guard */ @@ -891,8 +891,8 @@ void read_expr_operand(block_t *parent, basic_block_t **bb) macro_t *mac = find_macro(token); if (!strcmp(token, "__VA_ARGS__")) { - /* 'source_idx' has pointed at the character after __VA_ARGS__ */ - int remainder, t = source_idx; + /* 'size' has pointed at the character after __VA_ARGS__ */ + int remainder, t = SOURCE->size; macro_t *macro = parent->macro; if (!macro) @@ -902,13 +902,13 @@ void read_expr_operand(block_t *parent, basic_block_t **bb) remainder = macro->num_params - macro->num_param_defs; for (int i = 0; i < remainder; i++) { - source_idx = macro->params[macro->num_params - remainder + i]; - next_char = SOURCE[source_idx]; + SOURCE->size = macro->params[macro->num_params - remainder + i]; + next_char = SOURCE->elements[SOURCE->size]; next_token = lex_token(); read_expr(parent, bb); } - source_idx = t; - next_char = SOURCE[source_idx]; + SOURCE->size = t; + next_char = SOURCE->elements[SOURCE->size]; next_token = lex_token(); } else if (mac) { if (parent->macro) @@ -918,18 +918,18 @@ void read_expr_operand(block_t *parent, basic_block_t **bb) mac->num_params = 0; lex_expect(T_identifier); - /* 'source_idx' has pointed at the first parameter */ + /* 'size' has pointed at the first parameter */ while (!lex_peek(T_close_bracket, NULL)) { - mac->params[mac->num_params++] = source_idx; + mac->params[mac->num_params++] = SOURCE->size; do { next_token = lex_token(); } while (next_token != T_comma && next_token != T_close_bracket); } - /* move 'source_idx' to the macro body */ - macro_return_idx = source_idx; - source_idx = mac->start_source_idx; - next_char = SOURCE[source_idx]; + /* move 'size' to the macro body */ + macro_return_idx = SOURCE->size; + SOURCE->size = mac->start_source_idx; + next_char = SOURCE->elements[SOURCE->size]; lex_expect(T_close_bracket); skip_newline = 0; @@ -941,13 +941,13 @@ void read_expr_operand(block_t *parent, basic_block_t **bb) macro_return_idx = 0; } else if (macro_param_idx) { /* "expand" the argument from where it comes from */ - int t = source_idx; - source_idx = macro_param_idx; - next_char = SOURCE[source_idx]; + int t = SOURCE->size; + SOURCE->size = macro_param_idx; + next_char = SOURCE->elements[SOURCE->size]; next_token = lex_token(); read_expr(parent, bb); - source_idx = t; - next_char = SOURCE[source_idx]; + SOURCE->size = t; + next_char = SOURCE->elements[SOURCE->size]; next_token = lex_token(); } else if (con) { ph1_ir = add_ph1_ir(OP_load_constant); @@ -3075,17 +3075,17 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb) mac->num_params = 0; lex_expect(T_identifier); - /* 'source_idx' has pointed at the first parameter */ + /* 'size' has pointed at the first parameter */ while (!lex_peek(T_close_bracket, NULL)) { - mac->params[mac->num_params++] = source_idx; + mac->params[mac->num_params++] = SOURCE->size; do { next_token = lex_token(); } while (next_token != T_comma && next_token != T_close_bracket); } - /* move 'source_idx' to the macro body */ - macro_return_idx = source_idx; - source_idx = mac->start_source_idx; - next_char = SOURCE[source_idx]; + /* move 'size' to the macro body */ + macro_return_idx = SOURCE->size; + SOURCE->size = mac->start_source_idx; + next_char = SOURCE->elements[SOURCE->size]; lex_expect(T_close_bracket); skip_newline = 0; @@ -3377,8 +3377,8 @@ void parse_internal() GLOBAL_FUNC.fn->bbs = calloc(1, sizeof(basic_block_t)); /* lexer initialization */ - source_idx = 0; - next_char = SOURCE[0]; + SOURCE->size = 0; + next_char = SOURCE->elements[0]; lex_expect(T_start); do { @@ -3415,8 +3415,8 @@ void load_source_file(char *file) snprintf(path + c + 1, inclusion_path_len, "%s", buffer + 10); load_source_file(path); } else { - strcpy(SOURCE + source_idx, buffer); - source_idx += strlen(buffer); + strcpy(SOURCE->elements + SOURCE->size, buffer); + SOURCE->size += strlen(buffer); } } fclose(f); diff --git a/tools/inliner.c b/tools/inliner.c index 920fd849..952c412c 100644 --- a/tools/inliner.c +++ b/tools/inliner.c @@ -95,7 +95,7 @@ int main(int argc, char *argv[]) */ write_str("void __c(char *src) {\n"); write_str(" for (int i = 0; src[i]; i++)\n"); - write_str(" SOURCE[source_idx++] = src[i];\n"); + write_str(" source_push(SOURCE, src[i]);\n"); write_str("}\n"); write_str("void libc_generate() {\n");