char * macro_expansion(struct macrotable *node, const char *match) { if (!node) return NULL; else { register int value = string_compare(match, node->name); if (value < 0) return macro_expansion(node->left, match); else if (value > 0) return macro_expansion(node->right, match); else return alloc_string(node->definition); } }
void rescan_expansion(preprocessor_state* preproc, rsw_cstr* expansion, cvector_i* valid_macros, int macro_index) { int loc, macro_name_len, macro_val_len; char* ptr, *search, *found; macro_params* p; int macro = valid_macros->a[macro_index]; cvec_erase_i(valid_macros, macro_index, macro_index); for (int i, j=0; j < valid_macros->size; ++j) { i = valid_macros->a[j]; search = expansion->a; p = GET_PARAM(&preproc->params, i); macro_name_len = strlen(preproc->macros.a[i]); macro_val_len = strlen(preproc->values.a[i]); while (1) { found = strstr(search, preproc->macros.a[i]); if (!found) break; if (found != expansion->a) { if (isalpha(found[-1]) || found[-1] == '_') { search = found + macro_name_len; continue; } } if (isalnum(found[macro_name_len]) || found[macro_name_len] == '_') { search = found + macro_name_len; continue; } if (p->num_params >= 0) { ptr = found + macro_name_len; while (isspace(*ptr)) ++ptr; if (*ptr != '(') { search = found + macro_name_len; continue; } } loc = macro_expansion(preproc, expansion, found-expansion->a, valid_macros, j); search = &expansion->a[loc]; } } cvec_insert_i(valid_macros, macro_index, macro); }
void prescan_argument(preprocessor_state* preproc, rsw_cstr* expansion) { int loc, macro_name_len, macro_val_len; char* ptr, *search, *found; macro_params* p; /* * alternative method, actually parse tokens from the string * seems like overkill for now but if I run into some issue that makes it * more reasonable I'll consider it * vector_token_lex tlex; vec_token_lex(&tlex, 0, 20, free_token_lex, NULL); token_lex tok_lex; lexer_state lex = { 1, 0, 0, 0}; tok_lex = read_token_from_str(&expansion->a[lex.cur_char], &lex, NULL); while (tok_lex.tok.type != END) { cvec_push_token_lex(&tlek, &tok_lex); tok_lex = read_token_from_str(&expansion->a[lex.cur_char], &lex, NULL); } for (int i=0; i < tlex.size; ++i ) { if (tlex.a[i].tok.type == ID) { for (int j=0; j < preproc->macros.size; ++j) { if (!strcmp(tlex.a[i].tok.v.id, preproc->values.a[j])) { p = GET_PARAM(&preproc->params, j); if (p->num_params != -1) { if (tlex.a[i+1] != LPAREN) continue; loc = tlex.a[i].char_pos - expansion->a; macro_expansion(preproc, loc, NULL, j); } else { lex = { 1, 0, 0, tlex.a[i].char_pos }; tok_lex = read_token(&preproc->values[j][lex.cur_char], &lex, NULL); while (tok_lex.tok.type != END) { } } } } } } */ cvector_i valid_macros; cvec_i(&valid_macros, preproc->macros.size, preproc->macros.size); for (int j=0; j < preproc->macros.size; ++j) { valid_macros.a[j] = j; } for (int i=0; i < preproc->macros.size; ++i) { search = expansion->a; p = GET_PARAM(&preproc->params, i); macro_name_len = strlen(preproc->macros.a[i]); macro_val_len = strlen(preproc->values.a[i]); while (1) { found = strstr(search, preproc->macros.a[i]); if (!found) break; //since we should be working in tokens not characters //I have to check that the result is not inside another identifier //check before and after TODO I think these tests are insufficient if (found != expansion->a) { if (isalpha(found[-1]) || found[-1] == '_') { search = found + macro_name_len; continue; } } if (isalnum(found[macro_name_len]) || found[macro_name_len] == '_') { search = found + macro_name_len; continue; } if (p->num_params >= 0) { ptr = found + macro_name_len; while (isspace(*ptr)) ++ptr; if (*ptr != '(') { search = found + macro_name_len; continue; } } loc = found - expansion->a; loc = macro_expansion(preproc, expansion, loc, &valid_macros, i); search = &expansion->a[loc]; } } cvec_free_i(&valid_macros); }