char* find_define(define *d, char* m) { define *curr = d; while (curr != NULL) { if (strcmp(curr->macro, m) == 0) { /* we have to recursively check for nested defines */ if (find_define(d, curr->expansion) != NULL) return find_define(d, curr->expansion); return curr->expansion; } curr = curr->next; } return NULL; }
void add_simple_define( char * macro, char *text ) { int code = identifier_search_or_add( macro ); if ( find_define( code ) != -1 ) compile_error( MSG_MACRO_ERROR, identifier_name( code ) ); /* Allocate the macro */ if ( defines_allocated == defines_count ) { defines_allocated += 8; defines = ( DEFINE * ) realloc( defines, sizeof( DEFINE ) * defines_allocated ); } defines[defines_count].param_count = -1; defines[defines_count].code = code; defines[defines_count].text = strdup( text ); defines_count++; }
void preprocessor() { int i, ifdef; char * ptr; int actual_line_count; static int initialized = 0; if ( !initialized ) { id_define = identifier_search_or_add( "DEFINE" ); id_undef = identifier_search_or_add( "UNDEF" ); id_ifdef = identifier_search_or_add( "IFDEF" ); id_ifndef = identifier_search_or_add( "IFNDEF" ); id_else = identifier_search_or_add( "ELSE" ); id_endif = identifier_search_or_add( "ENDIF" ); id_if = identifier_search_or_add( "IF" ); initialized = 1; } token_next(); if ( token.type != IDENTIFIER ) compile_error( MSG_UNKNOWN_PREP ); /* #define TEXT value */ if ( token.code == id_define ) { disable_expand_defines++; token_next(); if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_IDENTIFIER ); if ( find_define( token.code ) != -1 ) compile_error( MSG_MACRO_ERROR, identifier_name( token.code ) ); /* Allocate the macro */ if ( defines_allocated == defines_count ) { defines_allocated += 8; defines = ( DEFINE * ) realloc( defines, sizeof( DEFINE ) * defines_allocated ); } defines[defines_count].code = token.code; /* Check for parameters: no space allowed between name and ( */ if ( *source_ptr == '(' ) { source_ptr++; for ( defines[defines_count].param_count = i = 0; *source_ptr != ')'; ) { if ( !*source_ptr ) compile_error( MSG_EXPECTED, ")" ); if ( i == MAX_MACRO_PARAMS ) compile_error( MSG_TOO_MANY_PARAMS ); token_next(); if ( token.type != IDENTIFIER || token.code < reserved_words ) compile_error( MSG_INVALID_IDENTIFIER ); defines[defines_count].param_id[i++] = token.code; defines[defines_count].param_count++; SKIP_SPACES; if ( *source_ptr == ',' ) source_ptr++; } source_ptr++; } else { /* No parameters and no parenthesis */ defines[defines_count].param_count = -1; } SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; ptr = ( char * ) source_ptr; while ( *ptr && *ptr != '\n' ) if ( *ptr == '\\' && *( ptr + 1 ) == '\n' ) { *ptr = ' '; ptr++; *ptr = ' '; ptr++; line_count++; } else ptr++; while ( ptr > source_ptr && ( !*ptr || ISSPACE( *ptr ) ) ) ptr--; defines[defines_count].text = ( char * )calloc( ptr - source_ptr + 2, sizeof( char ) ); strncpy( defines[defines_count].text, source_ptr, ptr - source_ptr + 1 ); defines[defines_count].text[ptr - source_ptr + 1] = 0; defines_count++; source_ptr = ptr + 1; disable_expand_defines--; return; } /* #undef TEXT */ if ( token.code == id_undef ) { disable_expand_defines++; token_next(); if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_IDENTIFIER ); if (( i = find_define( token.code ) ) != -1 ) { defines_count--; if ( defines[i].text ) free( defines[i].text ); memmove( &defines[i], &defines[i+1], ( defines_count - i ) * sizeof( DEFINE ) ); } disable_expand_defines--; return; } /* #ifdef CONST / #ifndef CONST*/ if ( token.code == id_ifdef || token.code == id_ifndef ) { ifdef = token.code == id_ifdef; prepro_stack[prepro_sp++] = token.code; disable_expand_defines++; token_next(); disable_expand_defines--; if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_IDENTIFIER ); SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; if ( *source_ptr && *source_ptr != '\n' ) { if ( ifdef ) compile_warning( "extra tokens at end of #ifdef directive" ); else compile_warning( "extra tokens at end of #ifndef directive" ); SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; } if ( *source_ptr == '\n' ) line_count--; for ( i = 0; i < defines_count; i++ ) { if ( defines[i].code == token.code ) { if ( ifdef ) return; break; } } if ( !ifdef && i == defines_count ) return; preprocessor_jumpto( id_else, id_endif ); SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; if ( *source_ptr && *source_ptr != '\n' ) { if ( token.code == id_else ) compile_warning( "extra tokens at end of #else directive" ); else if ( token.code == id_endif ) compile_warning( "extra tokens at end of #endif directive" ); SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; } if ( *source_ptr == '\n' ) line_count--; return; } /* #if */ if ( token.code == id_if ) { int actual_sources; expresion_result res; char c; prepro_stack[prepro_sp++] = token.code; ptr = ( char * ) source_ptr; while ( *ptr && *ptr != '\n' && *ptr != ';' ) if ( *ptr == '\\' && *( ptr + 1 ) == '\n' ) { *ptr = ' '; ptr++; *ptr = ' '; ptr++; line_count++; } else ptr++; c = *ptr; *ptr = '\0'; actual_line_count = line_count; actual_sources = sources; token_init( source_ptr, current_file ); identifiers_as_strings = 1; res = compile_expresion( 0, 0, 1, TYPE_DWORD ); identifiers_as_strings = 0; /* printf ("exp: asignation: [%d] call: [%d] lvalue: [%d] constant: [%d] value: [%d] lvalue: [%f] type: [%d]\n", res.asignation, res.call, res.lvalue, res.constant, res.value, res.fvalue, typedef_base(res.type)); */ if ( sources != actual_sources ) token_endfile(); *ptr = c; source_ptr = ptr; line_count = actual_line_count; SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; if ( *source_ptr && *source_ptr != '\n' ) { compile_warning( "extra tokens at end of #if directive" ); SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; } if ( *source_ptr == '\n' ) line_count--; use_saved = 0; if ( !res.constant ) compile_error( MSG_CONSTANT_EXP ); if ( !res.value ) { preprocessor_jumpto( id_else, id_endif ); SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; if ( *source_ptr && *source_ptr != '\n' ) { if ( token.code == id_else ) compile_warning( "extra tokens at end of #else directive" ); else if ( token.code == id_endif ) compile_warning( "extra tokens at end of #endif directive" ); SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; } if ( *source_ptr == '\n' ) line_count--; } return; } /* #else */ if ( token.code == id_else ) { if ( !prepro_sp ) compile_error( "#else without #if" ); int stck_code = prepro_stack[--prepro_sp]; if ( prepro_sp < 0 || ( stck_code != id_if && stck_code != id_ifdef && stck_code != id_ifndef ) ) { if ( stck_code == id_else ) { compile_error( "#else after #else" ); } else { compile_error( "#else without #if" ); } } prepro_stack[prepro_sp++] = token.code; SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; if ( *source_ptr && *source_ptr != '\n' ) { compile_warning( "extra tokens at end of #else directive" ); SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; } if ( *source_ptr == '\n' ) line_count--; preprocessor_jumpto( id_endif, 0 ); SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; if ( *source_ptr && *source_ptr != '\n' ) { compile_warning( "extra tokens at end of #endif directive" ); SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; } if ( *source_ptr == '\n' ) line_count--; return; } /* #endif */ if ( token.code == id_endif ) { int stck_code = prepro_stack[--prepro_sp]; if ( prepro_sp < 0 || ( stck_code != id_else && stck_code != id_if && stck_code != id_ifdef && stck_code != id_ifndef ) ) compile_error( "#endif without #if" ); SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; if ( *source_ptr == '\n' ) line_count--; return; } /* Unknown preprocessor directive */ compile_error( MSG_UNKNOWN_PREP ); }