Exemplo n.º 1
0
///
/// 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);
}
Exemplo n.º 2
0
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(&parameters);
    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(&parameters, 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(&parameters))
        dhalt(ERR_PP_TOO_MANY_PARAMETERS, start_loc);
    else if (list_size(&arguments) < list_size(&parameters))
        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(&parameters); i++)
    {
        new_info = malloc(sizeof(struct replace_info));
        new_info->full = list_get_at(&parameters, 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(&parameters, 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);
}