char *filter_macros(char *line) { if(*line == '#'){ handle_macro(line); free(line); return NULL; }else{ filter_macro(&line); return line; } }
/* * handle_cl_macro * * handle for closing macro */ static BOOL handle_cl_macro(HSCPRC * hp, HSCTAG * tag) { return (handle_macro(hp, tag, FALSE)); }
/* * handle_op_macro * * handle for opening macro */ static BOOL handle_op_macro(HSCPRC * hp, HSCTAG * tag) { return (handle_macro(hp, tag, TRUE)); }
void handle_macro(preprocessor_state* preproc, int macro) { FILE* input = preproc->input; FILE* output = preproc->output; lexer_state* lexer = &preproc->lexer; rsw_cstr expansion; init_cstr_str(&expansion, preproc->values.a[macro], strlen(preproc->values.a[macro])); macro_params* p = GET_PARAM(&preproc->params, macro); //do initial argument expansion if (p->num_params >= 0) parse_params(preproc, macro, &expansion); cvector_i valid_macros; cvec_i(&valid_macros, preproc->macros.size, preproc->macros.size); for (int i=0; i < preproc->macros.size; ++i) { valid_macros.a[i] = i; } rescan_expansion(preproc, &expansion, &valid_macros, macro); lexer_state save_lex; long fpos; token_lex t; save_lex = *lexer; if ((fpos = ftell(input)) == -1) { perror("ftell error in handle_macro"); exit(0); } t = read_token(input, lexer, NULL); *lexer = save_lex; if (fseek(input, fpos, SEEK_SET)) { perror("fseek failure in handle_macro"); exit(0); } if (t.tok.type == LPAREN) { char* search, *found; search = expansion.a; int len; for (int i=0; i < preproc->macros.size; ++i) { if (i == macro) continue; len = strlen(preproc->macros.a[i]); search = expansion.a; while (1) { found = strstr(search, preproc->macros.a[i]); if (!found) break; if (found[len]) { search = found + len; continue; } if (found != expansion.a) { if (isalpha(found[-1]) || found[-1] == '_') { search = found + len; continue; } } //don't need to check the end because we already did p = GET_PARAM(&preproc->params, i); if (p->num_params != -1) { *found = 0; //cut off matched macro fprintf(output, "%s", expansion.a); handle_macro(preproc, i); goto exit; } search = found + len; } } } else if (t.tok.type == ID || t.tok.type == STR_LITERAL) { free(t.tok.v.id); } fprintf(output, "%s", expansion.a); exit: free_cstr(&expansion); cvec_free_i(&valid_macros); }
void preprocess_file(preprocessor_state* preproc) { lexer_state save_lexer, *lexer = &preproc->lexer; long fpos; int c; token_lex tlex[10]; FILE* input = preproc->input; FILE* output = preproc->output; // if not -P fprintf(output, "# 0 \"%s\"\n", lexer->cur_file); tlex[0] = read_token(input, lexer, output); for ( ; tlex[0].tok.type != END; tlex[0] = read_token(input, lexer, output)) { if (tlex[0].tok.type == ID) { int is_macro = look_up_macro_loc(preproc, tlex[0].tok.v.id); if (is_macro >= 0) { macro_params* p = GET_PARAM(&preproc->params, is_macro); //for a function style macro if the name isn't followed by a ( it's not an error //it's just not an invocation so just print it out if (p->num_params >= 0) { save_lexer = *lexer; if ((fpos = ftell(input)) == -1) { perror("ftell failure in preprocess_file"); exit(0); } tlex[1] = read_token(input, lexer, NULL); if (tlex[1].tok.type != LPAREN) { *lexer = save_lexer; if (fseek(input, fpos, SEEK_SET)) { perror("fseek failure in preprocess_file"); exit(0); } if (tlex[1].tok.type == ID || tlex[1].tok.type == STR_LITERAL) free(tlex[1].tok.v.id); print_token(&tlex[0].tok, output, 0); free(tlex[0].tok.v.id); continue; } //restore ( for symmetry in handle_macro *lexer = save_lexer; if (fseek(input, fpos, SEEK_SET)) { perror("fseek failure in preprocess_file"); exit(0); } } handle_macro(preproc, is_macro); } else { print_token(&tlex[0].tok, output, 0); } free(tlex[0].tok.v.id); } else if (tlex[0].tok.type == POUND) { //has to be the first token if (lexer->cur_tok != 1) { preprocessor_error(NULL, lexer, "Error: stray # in program\n"); } save_lexer = *lexer; if ((fpos = ftell(input)) == -1) { perror("ftell failure in preprocess_file"); exit(0); } tlex[1] = read_token(input, lexer, NULL); if (tlex[0].line != tlex[1].line) { //null directive (EOF is always on it's own line) if (tlex[1].tok.type == POUND) { tlex[0] = tlex[1]; continue; } else if (tlex[1].tok.type == ID || tlex[1].tok.type == STR_LITERAL) { free(tlex[1].tok.v.id); } *lexer = save_lexer; if (fseek(input, fpos, SEEK_SET)) { perror("fseek failure in preprocess_file"); exit(0); } continue; } if (tlex[1].tok.type != ID) { preprocessor_error(&tlex[1], lexer, "expected ID as macro name,"); } if (!strcmp(tlex[1].tok.v.id, "define")) { free(tlex[1].tok.v.id); handle_define(preproc); goto eat_newline; } if (!strcmp(tlex[1].tok.v.id, "undef")) { free(tlex[1].tok.v.id); save_lexer = *lexer; fpos = ftell(input); tlex[1] = read_token(input, lexer, NULL); if (tlex[1].line != tlex[0].line) { preprocessor_error(NULL, lexer, "macro name missing in undef directive\n"); } if (tlex[1].tok.type != ID) { preprocessor_error(&tlex[1], lexer, "ID expected in undef directive,"); } int exists = look_up_macro_loc(preproc, tlex[0].tok.v.id); if (exists >= 0) { cvec_erase_str(&preproc->macros, exists, exists); cvec_erase_str(&preproc->values, exists, exists); cvec_erase_void(&preproc->params, exists, exists); } free(tlex[1].tok.v.id); goto eat_newline; } if (!strcmp(tlex[1].tok.v.id, "include")) { free(tlex[1].tok.v.id); handle_include(preproc); goto eat_newline; } if (!strcmp(tlex[1].tok.v.id, "if")) { free(tlex[1].tok.v.id); } if (!strcmp(tlex[1].tok.v.id, "ifdef")) { free(tlex[1].tok.v.id); handle_ifdef(preproc); goto eat_newline; } if (!strcmp(tlex[1].tok.v.id, "ifndef")) { free(tlex[1].tok.v.id); } if (!strcmp(tlex[1].tok.v.id, "else")) { } if (!strcmp(tlex[1].tok.v.id, "endif")) { } if (!strcmp(tlex[1].tok.v.id, "elif")) { } if (!strcmp(tlex[1].tok.v.id, "defined")) { } if (!strcmp(tlex[1].tok.v.id, "pragma")) { } if (!strcmp(tlex[1].tok.v.id, "error")) { // check for string // preprocessor_error(NULL, } eat_newline: //the newline should reset the position //but since the line of a directive should be //invisible to the final program it shouldn't affect line count do { c = getc(preproc->input); if (!isspace(c)) preprocessor_error(NULL, lexer, "extra tokens in directive\n"); } while (c != '\n'); lexer->cur_pos = 1; lexer->cur_tok = 0; } } }