From b34a2528c8efb95e0f0970d208fbb0d3ffb4c4ec Mon Sep 17 00:00:00 2001 From: Jeremiah Orians Date: Sat, 25 Dec 2021 09:06:57 -0500 Subject: [PATCH] Basic #include functionality imported --- M2libc | 2 +- cc_macro.c | 7 +- cc_reader.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 182 insertions(+), 16 deletions(-) diff --git a/M2libc b/M2libc index 222726e..c684e92 160000 --- a/M2libc +++ b/M2libc @@ -1 +1 @@ -Subproject commit 222726e4f8d6b3898da41e6052a95b6599e1c864 +Subproject commit c684e9275ff4b8ef45a970990e0a2959cef9a8c5 diff --git a/cc_macro.c b/cc_macro.c index 7395c43..c6822eb 100644 --- a/cc_macro.c +++ b/cc_macro.c @@ -568,7 +568,12 @@ void handle_define() return; } - require(NULL != hold, "#define got something it can't handle\n"); + if(NULL == hold) + { + fputs("#define got something it can't handle\n", stderr); + line_error_token(macro_token); + exit(EXIT_FAILURE); + } expansion_end = macro_token; diff --git a/cc_reader.c b/cc_reader.c index 556eb59..eaec6a0 100644 --- a/cc_reader.c +++ b/cc_reader.c @@ -17,12 +17,40 @@ */ #include "cc.h" +char* env_lookup(char* variable); +char* int2str(int x, int base, int signed_p); + +struct visited +{ + struct visited* prev; + char* name; +}; /* Globals */ FILE* input; struct token_list* token; int line; char* file; +struct visited* vision; + +int previously_seen(char* s) +{ + struct visited* v = vision; + while(NULL != v) + { + if(match(v->name, s)) return TRUE; + v = v->prev; + } + return FALSE; +} + +void just_seen(char* s) +{ + struct visited* hold = calloc(1, sizeof(struct visited)); + hold->prev = vision; + hold->name = s; + vision = hold; +} int grab_byte() { @@ -93,7 +121,7 @@ int preserve_keyword(int c, char* S) void reset_hold_string() { int i = string_index + 2; - while(0 != i) + while(0 <= i) { hold_string[i] = 0; i = i - 1; @@ -207,17 +235,30 @@ struct token_list* remove_preprocessor_directives(struct token_list* head) return first; } -int get_token(int c) +void new_token(char* s, int size) { struct token_list* current = calloc(1, sizeof(struct token_list)); require(NULL != current, "Exhausted memory while getting token\n"); + /* More efficiently allocate memory for string */ + current->s = calloc(size, sizeof(char)); + require(NULL != current->s, "Exhausted memory while trying to copy a token\n"); + copy_string(current->s, s, MAX_STRING); + + current->prev = token; + current->next = token; + current->linenumber = line; + current->filename = file; + token = current; +} + +int get_token(int c) +{ reset_hold_string(); string_index = 0; if(c == EOF) { - free(current); return c; } else if((32 == c) || (9 == c) || (c == '\n')) @@ -314,16 +355,7 @@ int get_token(int c) c = consume_byte(c); } - /* More efficiently allocate memory for string */ - current->s = calloc(string_index + 2, sizeof(char)); - require(NULL != current->s, "Exhausted memory while trying to copy a token\n"); - copy_string(current->s, hold_string, MAX_STRING); - - current->prev = token; - current->next = token; - current->linenumber = line; - current->filename = file; - token = current; + new_token(hold_string, string_index + 2); return c; } @@ -341,6 +373,131 @@ struct token_list* reverse_list(struct token_list* head) return root; } +int read_include(int c) +{ + reset_hold_string(); + string_index = 0; + int done = FALSE; + int ch; + + while(!done) + { + if(c == EOF) + { + fputs("we don't support EOF as a filename in #include statements\n", stderr); + exit(EXIT_FAILURE); + } + else if((32 == c) || (9 == c) || (c == '\n')) + { + c = grab_byte(); + } + else if(('"' == c) || ('<' == c)) + { + if('<' == c) c = '>'; + ch = c; + do + { + c = consume_byte(c); + require(EOF != c, "Unterminated filename in #include\n"); + } while(c != ch); + if('>' == ch) hold_string[0] = '<'; + done = TRUE; + } + } + + /* with just a little extra to put in the matching at the end */ + new_token(hold_string, string_index + 3); + return c; +} + +struct token_list* read_all_tokens(FILE* a, struct token_list* current, char* filename); +int include_file(int ch) +{ + /* The old state to restore to */ + char* hold_filename = file; + FILE* hold_input = input; + char* hold_line; + int hold_number; + + /* The new file to load */ + char* new_filename; + FILE* new_file; + + require(EOF != ch, "#include failed to receive filename\n"); + /* Remove the #include */ + token = token->next; + + /* Get new filename */ + read_include(ch); + ch = ' '; + new_filename = token->s; + /* Remove name from stream */ + token = token->next; + + /* Try to open the file */ + if('<' == new_filename[0]) + { + char* path = env_lookup("M2LIBC_PATH"); + if(NULL == path) path = "./M2libc"; + reset_hold_string(); + strcat(hold_string, path); + strcat(hold_string, "/"); + strcat(hold_string, new_filename + 1); + strcat(new_filename, ">"); + new_file = fopen(hold_string, "r"); + } + else + { + new_file = fopen(new_filename+1, "r"); + strcat(new_filename, "\""); + } + + /* prevent multiple visits */ + if(previously_seen(new_filename)) return ch; + just_seen(new_filename); + + /* special case this compatibility crap */ + if(match("\"../gcc_req.h\"", new_filename) || match("\"gcc_req.h\"", new_filename)) return ch; + + fputs("reading file: ", stderr); + fputs(new_filename, stderr); + fputc('\n', stderr); + + /* catch garbage input */ + if(NULL == new_file) + { + fputs("unable to read file: ", stderr); + fputs(new_filename, stderr); + fputs("\nAborting hard!\n", stderr); + exit(EXIT_FAILURE); + } + + + /* Replace token */ + new_token("//", 4); + new_token(" // #FILENAME", 11); + new_token(new_filename, strlen(new_filename) + 2); + new_token("1", 3); + new_token("\n", 3); + /* make sure to store return line number right after include */ + hold_line = int2str(line + 1, 10, FALSE); + hold_number = line + 1; + read_all_tokens(new_file, token, new_filename); + + /* put back old file info */ + new_token("//", 4); + new_token(" // #FILENAME", 11); + new_token(hold_filename, strlen(hold_filename)+2); + new_token(hold_line, strlen(hold_line)+2); + new_token("\n", 3); + + /* resume reading old file */ + input = hold_input; + line = hold_number; + file = hold_filename; + return ch; +} + struct token_list* read_all_tokens(FILE* a, struct token_list* current, char* filename) { input = a; @@ -348,7 +505,11 @@ struct token_list* read_all_tokens(FILE* a, struct token_list* current, char* fi file = filename; token = current; int ch = grab_byte(); - while(EOF != ch) ch = get_token(ch); + while(EOF != ch) + { + ch = get_token(ch); + if(match("#include", token->s)) ch = include_file(ch); + } return token; }