Basic #include functionality imported

This commit is contained in:
Jeremiah Orians 2021-12-25 09:06:57 -05:00
parent 3d1fd538a6
commit b34a2528c8
No known key found for this signature in database
GPG Key ID: 6B3A3F198708F894
3 changed files with 182 additions and 16 deletions

2
M2libc

@ -1 +1 @@
Subproject commit 222726e4f8d6b3898da41e6052a95b6599e1c864
Subproject commit c684e9275ff4b8ef45a970990e0a2959cef9a8c5

View File

@ -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;

View File

@ -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;
}