/// /// Flips the current scope on the stack. /// void ppimpl_flip_scope(state_t* state) { scope_t* scope = list_get_at(&state->scopes, list_size(&state->scopes) - 1); bool active = scope->active; ppimpl_pop_scope(state); ppimpl_push_scope(state, !active); }
static void macro_handle(state_t* state, match_t* match, bool* reprocess) { bstring name; bstring temp; list_t parameters; list_t arguments; bool getting_name = true; bool getting_parameters = false; bool getting_arguments = false; struct replace_info* info = match->userdata; int i = 0; int argument_brackets = 0; char c; char* start_loc; match_t* new_match; struct replace_info* new_info; // Parse the parameters out of the name. list_init(¶meters); temp = bfromcstr(""); for (i = 0; i < blength(info->full); i++) { c = info->full->data[i]; if (getting_name) { if (c == '(') { getting_name = false; getting_parameters = true; name = bstrcpy(temp); bassigncstr(temp, ""); } else bconchar(temp, c); } else if (getting_parameters) { if (c == ',' || c == ')') { btrimws(temp); list_append(¶meters, bstrcpy(temp)); bassigncstr(temp, ""); if (c == ')') { getting_parameters = false; break; } } else bconchar(temp, c); } } // Attempt to accept an open bracket. c = ppimpl_get_input(state); while (c == '\1') { // Consume macro termination. i = 0; while (i < strlen("\1MACROTERMINATE\1")) { if (c != "\1MACROTERMINATE\1"[i++]) dhalt(ERR_PP_EXPECTED_OPEN_BRACKET, ppimpl_get_location(state)); c = ppimpl_get_input(state); } ppimpl_pop_scope(state); } if (c != '(') dhalt(ERR_PP_EXPECTED_OPEN_BRACKET, ppimpl_get_location(state)); // Read arguments. getting_arguments = true; list_init(&arguments); start_loc = ppimpl_get_location(state); bassigncstr(temp, ""); while (ppimpl_has_input(state) && getting_arguments) { c = ppimpl_get_input(state); if (c == '(') { argument_brackets++; bconchar(temp, c); } else if (c == ')' && argument_brackets != 0) { argument_brackets--; bconchar(temp, c); } else if (c == ')' && argument_brackets == 0) { list_append(&arguments, bstrcpy(temp)); bassigncstr(temp, ""); getting_arguments = false; break; } else if (c == ',' && argument_brackets == 0) { list_append(&arguments, bstrcpy(temp)); bassigncstr(temp, ""); } else bconchar(temp, c); } if (getting_arguments) dhalt(ERR_PP_NO_TERMINATING_BRACKET, start_loc); // Check to see if the argument count is correct. if (list_size(&arguments) > list_size(¶meters)) dhalt(ERR_PP_TOO_MANY_PARAMETERS, start_loc); else if (list_size(&arguments) < list_size(¶meters)) dhalt(ERR_PP_NOT_ENOUGH_PARAMETERS, start_loc); free(start_loc); // Create a new scope for macro evaluation. ppimpl_push_scope(state, true); // Define the new handlers. for (i = 0; i < list_size(¶meters); i++) { new_info = malloc(sizeof(struct replace_info)); new_info->full = list_get_at(¶meters, i); new_info->replacement = list_get_at(&arguments, i); if (biseq(new_info->full, new_info->replacement)) { free(new_info); continue; } new_match = malloc(sizeof(match_t)); new_match->text = bautofree(list_get_at(¶meters, i)); new_match->handler = replace_handle; new_match->line_start_only = false; new_match->identifier_only = true; new_match->userdata = new_info; new_match->case_insensitive = false; ppimpl_register(state, new_match); } // Print out the macro evaluation and terminator. ppimpl_printf(state, "%s\1MACROTERMINATE\1", info->replacement->data); }