Basic #include functionality imported
This commit is contained in:
parent
3d1fd538a6
commit
b34a2528c8
2
M2libc
2
M2libc
|
@ -1 +1 @@
|
|||
Subproject commit 222726e4f8d6b3898da41e6052a95b6599e1c864
|
||||
Subproject commit c684e9275ff4b8ef45a970990e0a2959cef9a8c5
|
|
@ -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;
|
||||
|
||||
|
|
189
cc_reader.c
189
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue