863 lines
25 KiB
C++
863 lines
25 KiB
C++
/*
|
|
* Mr. 4th Dimention - Allen Webster
|
|
*
|
|
* 30.11.2015
|
|
*
|
|
* CPP preprocessor
|
|
*
|
|
*/
|
|
|
|
// TOP
|
|
|
|
#define byte unsigned char
|
|
|
|
struct Cpp_PP_Step{
|
|
int error_code;
|
|
int finished;
|
|
int early_out;
|
|
|
|
int mem_size;
|
|
int mem_type;
|
|
|
|
int emit;
|
|
int file_index;
|
|
int token_index;
|
|
};
|
|
|
|
enum Cpp_PP_Expansion_Type{
|
|
PPExp_Normal,
|
|
// never below this
|
|
PPExp_Count
|
|
};
|
|
struct Cpp_PP_Expansion_Header{
|
|
int prev_frame;
|
|
int type;
|
|
};
|
|
struct Cpp_PP_Expansion_Normal{
|
|
int file_offset;
|
|
int current_token;
|
|
int end_token;
|
|
int file_level;
|
|
};
|
|
|
|
struct Cpp_PP_State{
|
|
byte *base;
|
|
int top, frame, max;
|
|
|
|
int substep;
|
|
|
|
struct{
|
|
union{
|
|
int name_index;
|
|
int param_count;
|
|
int macro_offset;
|
|
} define;
|
|
} vars;
|
|
|
|
Debug(int did_advance);
|
|
};
|
|
|
|
internal int
|
|
cpp__push_expansion_normal(Cpp_PP_State *state, int file, int start, int end, int file_level){
|
|
Cpp_PP_Expansion_Header *header;
|
|
Cpp_PP_Expansion_Normal *expansion;
|
|
int added_size;
|
|
int prev_frame;
|
|
int result;
|
|
|
|
added_size = sizeof(Cpp_PP_Expansion_Header) + sizeof(Cpp_PP_Expansion_Normal);
|
|
|
|
if (state->top + added_size <= state->max){
|
|
result = 1;
|
|
|
|
prev_frame = state->frame;
|
|
state->frame = state->top;
|
|
state->top += added_size;
|
|
|
|
header = (Cpp_PP_Expansion_Header*)(state->base + state->frame);
|
|
expansion = (Cpp_PP_Expansion_Normal*)(header + 1);
|
|
|
|
header->prev_frame = prev_frame;
|
|
header->type = PPExp_Normal;
|
|
expansion->file_offset = file;
|
|
expansion->current_token = start;
|
|
expansion->end_token = end;
|
|
expansion->file_level = file_level;
|
|
}
|
|
else{
|
|
result = 0;
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal int
|
|
cpp__pop_expansion(Cpp_PP_State *state){
|
|
Cpp_PP_Expansion_Header *header;
|
|
int result;
|
|
|
|
if (state->top >= sizeof(Cpp_PP_Expansion_Header)){
|
|
Assert(state->top - state->frame >= sizeof(Cpp_PP_Expansion_Header));
|
|
result = 1;
|
|
|
|
header = (Cpp_PP_Expansion_Header*)(state->base + state->frame);
|
|
state->top = state->frame;
|
|
state->frame = header->prev_frame;
|
|
}
|
|
else{
|
|
result = 0;
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
enum Cpp_PP_Memory_Type{
|
|
PPMem_None,
|
|
PPMem_Definition_Items,
|
|
PPMem_Definition_Table,
|
|
PPMem_Spare_File_String,
|
|
PPMem_Spare_File_Tokens,
|
|
// never below this
|
|
PPMem_Count
|
|
};
|
|
|
|
internal void
|
|
cpp__pp_memory_request(Cpp_PP_Step *step, int amount, int type){
|
|
Assert(!step->early_out);
|
|
step->early_out = 1;
|
|
step->mem_size = amount;
|
|
step->mem_type = type;
|
|
}
|
|
|
|
enum Cpp_PP_Table_Entry_Type{
|
|
PPItem_Unset,
|
|
PPItem_File,
|
|
PPItem_Macro,
|
|
// never below this
|
|
PPItem_Count
|
|
};
|
|
struct Cpp_PP_Table_Entry{
|
|
int name_start, name_size;
|
|
int type;
|
|
unsigned int hash;
|
|
int item_offset;
|
|
};
|
|
struct Cpp_PP_Table{
|
|
Cpp_PP_Table_Entry *entries;
|
|
unsigned int count, max;
|
|
};
|
|
|
|
struct Cpp_PP_File{
|
|
Cpp_File file;
|
|
Cpp_Token_Stack tokens;
|
|
};
|
|
struct Cpp_PP_Macro{
|
|
int self_start;
|
|
int name_start;
|
|
int name_size;
|
|
int param_count;
|
|
int variadic;
|
|
int body_start;
|
|
int body_end;
|
|
};
|
|
|
|
struct Cpp_PP_Definitions{
|
|
byte *items;
|
|
int pos, restore_pos, max;
|
|
Cpp_PP_File *spare_file;
|
|
int spare_pos;
|
|
|
|
Cpp_PP_Table table;
|
|
};
|
|
|
|
internal unsigned int
|
|
cpp__hash(char *name, int size, int type){
|
|
unsigned int x;
|
|
int i;
|
|
|
|
x = 5381;
|
|
x = ((x << 5) + x) ^ ('A' + type);
|
|
for (i = 0; i < size; ++i, ++name){
|
|
x = ((x << 5) + x) ^ *name;
|
|
}
|
|
|
|
return(x);
|
|
}
|
|
|
|
internal unsigned int
|
|
cpp__hash(Cpp_PP_Definitions *definitions, int name_start, int name_size, int type){
|
|
unsigned int x;
|
|
char *s;
|
|
s = definitions->spare_file->file.data + name_start;
|
|
x = cpp__hash(s, name_size, type);
|
|
return(x);
|
|
}
|
|
|
|
internal int
|
|
cpp__table_can_add(Cpp_PP_Table *table){
|
|
int result;
|
|
result = 0;
|
|
if (table->count*8 < table->max*7) result = 1;
|
|
return(result);
|
|
}
|
|
|
|
internal void
|
|
cpp__table_add_direct(Cpp_PP_Table *table, Cpp_PP_Table_Entry entry){
|
|
unsigned int i, j;
|
|
i = entry.hash % table->max;
|
|
j = i - 1;
|
|
if (i <= 1) j += table->max;
|
|
|
|
for (; i != j; ++i){
|
|
if (i == table->max) i = 0;
|
|
if (table->entries[i].type == PPItem_Unset){
|
|
table->entries[i] = entry;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Assert(i != j);
|
|
}
|
|
|
|
internal void
|
|
cpp__table_add(Cpp_PP_Definitions *definitions, Cpp_PP_Table *table,
|
|
int name_start, int name_size, int type, int offset){
|
|
Cpp_PP_Table_Entry entry;
|
|
unsigned int hash;
|
|
|
|
Assert(cpp__table_can_add(table));
|
|
|
|
hash = cpp__hash(definitions, name_start, name_size, type);
|
|
entry.name_start = name_start;
|
|
entry.name_size = name_size;
|
|
entry.type = type;
|
|
entry.hash = hash;
|
|
entry.item_offset = offset;
|
|
|
|
cpp__table_add_direct(table, entry);
|
|
}
|
|
|
|
internal int
|
|
cpp__str_match(char *a, char *b, int size){
|
|
char *e;
|
|
int result;
|
|
result = 0;
|
|
for(e = a + size; a < e && *a == *b; ++a, ++b);
|
|
if (a == e) result = 1;
|
|
return(result);
|
|
}
|
|
|
|
internal int
|
|
cpp__table_find_hash_pos(Cpp_PP_Definitions *definitions, Cpp_PP_Table *table,
|
|
char *name, int name_size, int typ e, unsigned int *hash_index){
|
|
Cpp_PP_Table_Entry *entry;
|
|
int result;
|
|
unsigned int hash;
|
|
unsigned int i, j;
|
|
|
|
result = 0;
|
|
hash = cpp__hash(name, name_size, type);
|
|
i = hash % table->max;
|
|
j = i - 1;
|
|
if (i <= 1) j += table->max;
|
|
|
|
for (; i != j; ++i){
|
|
if (i == table->max) i = 0;
|
|
entry = table->entries + i;
|
|
if (entry->type == PPItem_Unset) break;
|
|
if (entry->hash == hash && entry->type == type && entry->name_size == name_size &&
|
|
cpp__str_match(name, definitions->spare_file->file.data + entry->name_start, name_size)){
|
|
result = 1;
|
|
*hash_index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal int
|
|
cpp__table_find(Cpp_PP_Definitions *definitions, Cpp_PP_Table *table,
|
|
char *name, int name_size, int type, int *offset){
|
|
int result;
|
|
unsigned int hash_index;
|
|
|
|
result = 0;
|
|
if (cpp__table_find_hash_pos(definitions, table, name, name_size, type, &hash_index)){
|
|
result = 1;
|
|
*offset = table->entries[hash_index].item_offset;
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal void
|
|
cpp__table_cpy(Cpp_PP_Table *dest, Cpp_PP_Table *src){
|
|
Cpp_PP_Table_Entry *entry;
|
|
unsigned int i;
|
|
|
|
Assert(dest->max >= src->max);
|
|
for (i = 0, entry = src->entries; i < src->max; ++i, ++entry){
|
|
if (entry->type != PPItem_Unset){
|
|
cpp__table_add_direct(dest, *entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void
|
|
cpp__def_begin_uncertain(Cpp_PP_Definitions *definitions){
|
|
definitions->restore_pos = definitions->pos;
|
|
}
|
|
internal void
|
|
cpp__def_success_uncertain(Cpp_PP_Definitions *definitions){
|
|
definitions->restore_pos = 0;
|
|
}
|
|
internal void
|
|
cpp__def_fail_uncertain(Cpp_PP_Definitions *definitions){
|
|
if (definitions->restore_pos != 0){
|
|
definitions->pos = definitions->restore_pos;
|
|
}
|
|
}
|
|
|
|
internal int
|
|
cpp__def_can_save_strings(Cpp_PP_Definitions *definitions, int total_size){
|
|
int result;
|
|
Cpp_PP_File *file;
|
|
file = definitions->spare_file;
|
|
|
|
if (definitions->spare_pos + total_size <= file->file.size) result = 1;
|
|
else result = 0;
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal int
|
|
cpp__def_can_save_item(Cpp_PP_Definitions *definitions, int size){
|
|
int result;
|
|
|
|
if (definitions->pos + size <= definitions->max) result = 1;
|
|
else result = 0;
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal int
|
|
cpp__def_save_string(Cpp_PP_Step *step, Cpp_PP_Definitions *definitions,
|
|
char *str, int size){
|
|
int result;
|
|
Cpp_PP_File *file;
|
|
file = definitions->spare_file;
|
|
|
|
Assert(definitions->spare_pos + size <= file->file.size);
|
|
memcpy(file->file.data + definitions->spare_pos, str, size);
|
|
result = definitions->spare_pos;
|
|
definitions->spare_pos += size;
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal int
|
|
cpp__mem_up(int x){
|
|
int xx;
|
|
xx = x / 1024;
|
|
if (xx*1024 < x){
|
|
xx += 1;
|
|
}
|
|
xx = xx << 10;
|
|
return(xx);
|
|
}
|
|
|
|
internal int
|
|
cpp__def_begin_macro(Cpp_PP_Step *step, Cpp_PP_Definitions *definitions,
|
|
char *str, int size){
|
|
int result, str_pos;
|
|
Cpp_PP_Macro *macro_item;
|
|
|
|
result = 0;
|
|
if (cpp__def_can_save_strings(definitions, size)){
|
|
if (cpp__def_can_save_item(definitions, sizeof(Cpp_PP_Macro))){
|
|
str_pos = cpp__def_save_string(step, definitions, str, size);
|
|
|
|
Assert(definitions->pos + sizeof(Cpp_PP_Macro) <= definitions->max);
|
|
result = definitions->pos;
|
|
definitions->pos += sizeof(Cpp_PP_Macro);
|
|
|
|
macro_item = (Cpp_PP_Macro*)(definitions->items + result);
|
|
*macro_item = {};
|
|
macro_item->self_start = result;
|
|
macro_item->name_start = str_pos;
|
|
macro_item->name_size = size;
|
|
}
|
|
else{
|
|
cpp__pp_memory_request(step, cpp__mem_up(definitions->max + 1), PPMem_Definition_Items);
|
|
}
|
|
}
|
|
else{
|
|
cpp__pp_memory_request(step, cpp__mem_up(definitions->spare_file->file.size + size),
|
|
PPMem_Spare_File_String);
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal void
|
|
cpp__def_set_macro_params(Cpp_PP_Definitions *definitions, int macro_offset, int param_count){
|
|
Cpp_PP_Macro *macro_item;
|
|
macro_item = (Cpp_PP_Macro*)(definitions->items + macro_offset);
|
|
macro_item->param_count = param_count;
|
|
}
|
|
|
|
internal void
|
|
cpp__def_set_macro_variadic(Cpp_PP_Definitions *definitions, int macro_offset, int variadic){
|
|
Cpp_PP_Macro *macro_item;
|
|
macro_item = (Cpp_PP_Macro*)(definitions->items + macro_offset);
|
|
macro_item->variadic = variadic;
|
|
}
|
|
|
|
internal void
|
|
cpp__def_set_macro_body_start(Cpp_PP_Definitions *definitions, int macro_offset, int body_start){
|
|
Cpp_PP_Macro *macro_item;
|
|
macro_item = (Cpp_PP_Macro*)(definitions->items + macro_offset);
|
|
macro_item->body_start = body_start;
|
|
}
|
|
|
|
internal void
|
|
cpp__def_set_macro_body_end(Cpp_PP_Definitions *definitions, int macro_offset, int body_end){
|
|
Cpp_PP_Macro *macro_item;
|
|
macro_item = (Cpp_PP_Macro*)(definitions->items + macro_offset);
|
|
macro_item->body_end = body_end;
|
|
}
|
|
|
|
internal void
|
|
cpp__def_end_macro(Cpp_PP_Step *step, Cpp_PP_Definitions *definitions){
|
|
if (cpp__table_can_add(&definitions->table)){
|
|
Cpp_PP_Macro *macro_item;
|
|
macro_item = (Cpp_PP_Macro*)(definitions->items + definitions->restore_pos);
|
|
|
|
cpp__table_add(definitions, &definitions->table,
|
|
macro_item->name_start, macro_item->name_size,
|
|
PPItem_Macro, macro_item->self_start);
|
|
}
|
|
else{
|
|
cpp__pp_memory_request(step,
|
|
cpp__mem_up(definitions->table.max*sizeof(Cpp_PP_Table_Entry)+1),
|
|
PPMem_Definition_Table);
|
|
}
|
|
}
|
|
|
|
internal Cpp_PP_File*
|
|
cpp_preproc_get_pp_file(Cpp_PP_Definitions *definitions, int file_offset){
|
|
Cpp_PP_File *result;
|
|
result = (Cpp_PP_File*)(definitions->items+file_offset);
|
|
return(result);
|
|
}
|
|
|
|
internal Cpp_File*
|
|
cpp_preproc_get_file(Cpp_PP_Definitions *definitions, int file_offset){
|
|
Cpp_PP_File *pp_file;
|
|
Cpp_File *result;
|
|
pp_file = cpp_preproc_get_pp_file(definitions, file_offset);
|
|
result = &pp_file->file;
|
|
return(result);
|
|
}
|
|
|
|
internal Cpp_Token*
|
|
cpp_preproc_get_token(Cpp_PP_Definitions *definitions, int file_offset, int token_index){
|
|
Cpp_PP_File *pp_file;
|
|
Cpp_Token *result;
|
|
pp_file = cpp_preproc_get_pp_file(definitions, file_offset);
|
|
result = &pp_file->tokens.tokens[token_index];
|
|
return(result);
|
|
}
|
|
|
|
internal int
|
|
cpp__define_file(Cpp_PP_Definitions *definitions, Cpp_File file, Cpp_Token_Stack tokens){
|
|
int result;
|
|
Cpp_PP_File *file_item;
|
|
|
|
Assert(definitions->pos + sizeof(Cpp_PP_File) <= definitions->max);
|
|
result = definitions->pos;
|
|
definitions->pos += sizeof(Cpp_PP_File);
|
|
|
|
file_item = (Cpp_PP_File*)(definitions->items + result);
|
|
file_item->file = file;
|
|
file_item->tokens = tokens;
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal void
|
|
cpp_preproc_set_spare_space(Cpp_PP_Definitions *definitions,
|
|
int str_size, void *str_mem,
|
|
int token_size, void *token_mem){
|
|
Cpp_PP_File pp_file;
|
|
pp_file.file.size = str_size;
|
|
pp_file.file.data = (char*)str_mem;
|
|
pp_file.tokens.max_count = token_size;
|
|
pp_file.tokens.count = 0;
|
|
pp_file.tokens.tokens = (Cpp_Token*)token_mem;
|
|
|
|
int pos = cpp__define_file(definitions, pp_file.file, pp_file.tokens);
|
|
Cpp_PP_File *spare_file = cpp_preproc_get_pp_file(definitions, pos);
|
|
definitions->spare_file = spare_file;
|
|
definitions->spare_pos = 0;
|
|
}
|
|
|
|
internal void
|
|
cpp_preproc_target(Cpp_PP_State *state, Cpp_PP_Definitions *definitions,
|
|
Cpp_File file, Cpp_Token_Stack tokens){
|
|
int file_index;
|
|
|
|
Assert(state->top == 0);
|
|
|
|
file_index = cpp__define_file(definitions, file, tokens);
|
|
cpp__push_expansion_normal(state, file_index, 0, tokens.count, 1);
|
|
}
|
|
|
|
internal void*
|
|
cpp_preproc_provide_memory(Cpp_PP_State *state, Cpp_PP_Definitions *definitions,
|
|
int type, int size, void *memory){
|
|
Cpp_PP_Table new_table;
|
|
Cpp_PP_File *spare;
|
|
void *result;
|
|
result = 0;
|
|
|
|
|
|
|
|
switch (type){
|
|
case PPMem_None: Assert(0); break;
|
|
|
|
case PPMem_Definition_Items:
|
|
Assert(size > definitions->max);
|
|
memcpy(memory, definitions->items, definitions->pos);
|
|
result = definitions->items;
|
|
definitions->items = (byte*)memory;
|
|
break;
|
|
|
|
case PPMem_Definition_Table:
|
|
Assert(size > definitions->table.max * sizeof(*new_table.entries));
|
|
new_table.entries = (Cpp_PP_Table_Entry*)memory;
|
|
new_table.max = size/sizeof(*new_table.entries);
|
|
new_table.count = 0;
|
|
cpp__table_cpy(&new_table, &definitions->table);
|
|
result = definitions->table.entries;
|
|
definitions->table = new_table;
|
|
break;
|
|
|
|
case PPMem_Spare_File_String:
|
|
spare = definitions->spare_file;
|
|
Assert(size > spare->file.size);
|
|
memcpy(memory, spare->file.data, definitions->spare_pos);
|
|
result = spare->file.data;
|
|
spare->file.data = (char*)memory;
|
|
break;
|
|
|
|
case PPMem_Spare_File_Tokens:
|
|
spare = definitions->spare_file;
|
|
Assert(size > spare->tokens.count*sizeof(Cpp_Token));
|
|
memcpy(memory, spare->tokens.tokens, spare->tokens.count*sizeof(Cpp_Token));
|
|
result = spare->tokens.tokens;
|
|
spare->tokens.tokens = (Cpp_Token*)memory;
|
|
break;
|
|
|
|
default: Assert(0); break;
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
enum Cpp_PP_Error{
|
|
PPErr_None,
|
|
PPErr_Define_Identifier_Missing,
|
|
PPErr_Parameter_Identifier_Missing,
|
|
PPErr_Preprocessor_Directive_In_Expansion,
|
|
PPErr_Expected_Comma_Or_Parenthese,
|
|
PPErr_Unfinished_Parameters,
|
|
// never below this
|
|
PPErr_Count
|
|
};
|
|
|
|
internal char*
|
|
cpp_preproc_error_str(int error_code){
|
|
char *result = 0;
|
|
|
|
switch (error_code){
|
|
case PPErr_None:
|
|
result = "no error"; break;
|
|
|
|
case PPErr_Define_Identifier_Missing:
|
|
result = "define identifier missing"; break;
|
|
|
|
case PPErr_Parameter_Identifier_Missing:
|
|
result = "parameter identifier missing"; break;
|
|
|
|
case PPErr_Preprocessor_Directive_In_Expansion:
|
|
result = "preprocessor directive in expansion"; break;
|
|
|
|
case PPErr_Expected_Comma_Or_Parenthese:
|
|
result = "expected comma or parenthese"; break;
|
|
|
|
case PPErr_Unfinished_Parameters:
|
|
result = "unfinished parameter list"; break;
|
|
|
|
default:
|
|
result = "unknown error code";
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
internal int
|
|
cpp_preproc_recommend_termination(int error_code){
|
|
int result = 0;
|
|
|
|
return(result);
|
|
}
|
|
|
|
struct Cpp__PP_Visit{
|
|
int file_offset;
|
|
int token_index;
|
|
};
|
|
|
|
internal void
|
|
cpp__pp_next_token(Cpp_PP_State *state, Cpp_PP_Expansion_Normal *expansion){
|
|
++expansion->current_token;
|
|
Debug(state->did_advance = 1);
|
|
}
|
|
|
|
enum Cpp_PP_State_Step{
|
|
PPState_None,
|
|
PPState_Define,
|
|
PPState_Name,
|
|
PPState_Define_Body,
|
|
PPState_Define_Parameter,
|
|
PPState_Define_Parameter_Comma,
|
|
PPState_Error_Recovery,
|
|
// never below this
|
|
PPState_Count
|
|
};
|
|
|
|
internal int
|
|
cpp__pp_require_identifier(Cpp_PP_State *state, Cpp_Token token){
|
|
int result;
|
|
result = PPErr_None;
|
|
if ((token.flags & CPP_TFLAG_PP_BODY) == 0){
|
|
result = PPErr_Define_Identifier_Missing;
|
|
state->substep = PPState_None;
|
|
Debug(state->did_advance = 1);
|
|
}
|
|
else if (token.type != CPP_TOKEN_IDENTIFIER &&
|
|
(token.flags & CPP_TFLAG_IS_KEYWORD) == 0){
|
|
result = PPErr_Define_Identifier_Missing;
|
|
state->substep = PPState_Error_Recovery;
|
|
Debug(state->did_advance = 1);
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
internal Cpp_PP_Step
|
|
cpp__pp_step_normal(Cpp_PP_State *state, Cpp_PP_Definitions *definitions,
|
|
Cpp_PP_Expansion_Normal *expansion){
|
|
Cpp__PP_Visit visit;
|
|
Cpp_PP_Step result;
|
|
Cpp_Token token;
|
|
Cpp_PP_File pp_file;
|
|
int void_step;
|
|
|
|
visit = {};
|
|
result = {};
|
|
void_step = 0;
|
|
|
|
if (expansion->current_token < expansion->end_token){
|
|
visit.file_offset = expansion->file_offset;
|
|
visit.token_index = expansion->current_token;
|
|
}
|
|
else{
|
|
void_step = 1;
|
|
cpp__pop_expansion(state);
|
|
}
|
|
|
|
if (!void_step){
|
|
pp_file = *cpp_preproc_get_pp_file(definitions, visit.file_offset);
|
|
Assert(visit.token_index >= 0 && visit.token_index < pp_file.tokens.count);
|
|
token = pp_file.tokens.tokens[visit.token_index];
|
|
|
|
|
|
|
|
Debug(state->did_advance = 0);
|
|
if (token.type == CPP_TOKEN_COMMENT || token.type == CPP_TOKEN_JUNK){
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
else{
|
|
switch (state->substep){
|
|
case PPState_None:
|
|
{
|
|
if (expansion->file_level == 0 && (token.flags & CPP_TFLAG_PP_DIRECTIVE)){
|
|
result.error_code = PPErr_Preprocessor_Directive_In_Expansion;
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
else{
|
|
switch (token.type){
|
|
case CPP_PP_DEFINE:
|
|
{
|
|
state->substep = PPState_Define;
|
|
state->vars = {};
|
|
cpp__pp_next_token(state, expansion);
|
|
}break;
|
|
|
|
default:
|
|
{
|
|
result.emit = 1;
|
|
result.file_index = visit.file_offset;
|
|
result.token_index = visit.token_index;
|
|
cpp__pp_next_token(state, expansion);
|
|
}break;
|
|
|
|
}
|
|
}
|
|
}break;
|
|
|
|
case PPState_Define:
|
|
{
|
|
result.error_code = cpp__pp_require_identifier(state, token);
|
|
if (result.error_code == PPErr_None){
|
|
|
|
cpp__def_begin_uncertain(definitions);
|
|
state->vars.define.macro_offset =
|
|
cpp__def_begin_macro(&result, definitions,
|
|
pp_file.file.data + token.start,
|
|
token.size);
|
|
if (result.early_out) goto cpp__pp_step_early_out;
|
|
|
|
state->substep = PPState_Name;
|
|
state->vars.define.name_index = visit.token_index;
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
}break;
|
|
|
|
case PPState_Name:
|
|
{
|
|
if ((token.flags & CPP_TFLAG_PP_BODY) == 0){
|
|
cpp__def_end_macro(&result, definitions);
|
|
if (result.early_out) goto cpp__pp_step_early_out;
|
|
cpp__def_success_uncertain(definitions);
|
|
state->substep = PPState_None;
|
|
Debug(state->did_advance = 1);
|
|
}
|
|
else if (token.type == CPP_TOKEN_PARENTHESE_OPEN){
|
|
state->substep = PPState_Define_Parameter;
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
else{
|
|
state->substep = PPState_Define_Body;
|
|
}
|
|
}break;
|
|
|
|
case PPState_Define_Parameter:
|
|
{
|
|
if (token.type == CPP_TOKEN_PARENTHESE_CLOSE &&
|
|
(token.flags & CPP_TFLAG_PP_BODY) &&
|
|
state->vars.define.param_count == 0){
|
|
state->substep = PPState_Define_Body;
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
else{
|
|
result.error_code = cpp__pp_require_identifier(state, token);
|
|
if (result.error_code == PPErr_None){
|
|
state->substep = PPState_Define_Parameter_Comma;
|
|
cpp__pp_next_token(state, expansion);
|
|
++state->vars.define.param_count;
|
|
}
|
|
else{
|
|
result.error_code = PPErr_Parameter_Identifier_Missing;
|
|
// NOTE(allen): Here I do not do the work I normally do when
|
|
// setting an error, because that work was done earlier, this is
|
|
// just translating the error code.
|
|
}
|
|
}
|
|
}break;
|
|
|
|
case PPState_Define_Parameter_Comma:
|
|
{
|
|
if ((token.flags & CPP_TFLAG_PP_BODY) == 0){
|
|
result.error_code = PPErr_Unfinished_Parameters;
|
|
state->substep = PPState_None;
|
|
Debug(state->did_advance = 1);
|
|
}
|
|
else{
|
|
if (token.type == CPP_TOKEN_COMMA){
|
|
state->substep = PPState_Define_Parameter;
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
else if (token.type == CPP_TOKEN_PARENTHESE_CLOSE){
|
|
state->substep = PPState_Define_Body;
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
else{
|
|
state->substep = PPState_Error_Recovery;
|
|
result.error_code = PPErr_Expected_Comma_Or_Parenthese;
|
|
Debug(state->did_advance = 1);
|
|
}
|
|
}
|
|
}break;
|
|
|
|
case PPState_Define_Body:
|
|
{
|
|
if ((token.flags & CPP_TFLAG_PP_BODY) == 0){
|
|
// TODO(allen): define macro
|
|
state->substep = PPState_None;
|
|
Debug(state->did_advance = 1);
|
|
}
|
|
else{
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
}break;
|
|
|
|
case PPState_Error_Recovery:
|
|
{
|
|
if ((token.flags & CPP_TFLAG_PP_BODY) == 0){
|
|
state->substep = PPState_None;
|
|
Debug(state->did_advance = 1);
|
|
}
|
|
else{
|
|
cpp__pp_next_token(state, expansion);
|
|
}
|
|
}break;
|
|
|
|
}
|
|
}
|
|
|
|
Assert(state->did_advance == 1);
|
|
}
|
|
|
|
cpp__pp_step_early_out:
|
|
return(result);
|
|
}
|
|
|
|
internal Cpp_PP_Step
|
|
cpp_preproc_step_nonalloc(Cpp_PP_State *state, Cpp_PP_Definitions *definitions){
|
|
Cpp_PP_Step result;
|
|
Cpp_PP_Expansion_Header *header;
|
|
|
|
Assert(state->top >= sizeof(Cpp_PP_Expansion_Header));
|
|
|
|
result = {};
|
|
header = (Cpp_PP_Expansion_Header*)(state->base + state->frame);
|
|
switch (header->type){
|
|
case PPExp_Normal:
|
|
result = cpp__pp_step_normal(state, definitions,
|
|
(Cpp_PP_Expansion_Normal*)(header + 1));
|
|
break;
|
|
default: Assert(0);
|
|
}
|
|
|
|
if (state->top == 0) result.finished = 1;
|
|
|
|
return(result);
|
|
}
|
|
|
|
#undef byte
|
|
|
|
// BOTTOM
|
|
|