예제 #1
0
static int
process_directive(gmx_cpp_t *handlep, const char *dname, const char *dval)
{
    gmx_cpp_t    handle = (gmx_cpp_t)*handlep;
    int          i, i0, len, status;
    unsigned int i1;
    char        *inc_fn, *name;
    const char  *ptr;
    int          bIfdef, bIfndef;

    /* #ifdef or ifndef statement */
    bIfdef  = (strcmp(dname, "ifdef") == 0);
    bIfndef = (strcmp(dname, "ifndef") == 0);
    if (bIfdef || bIfndef)
    {
        if ((handle->nifdef > 0) && (handle->ifdefs[handle->nifdef-1] != eifTRUE))
        {
            handle->nifdef++;
            srenew(handle->ifdefs, handle->nifdef);
            handle->ifdefs[handle->nifdef-1] = eifIGNORE;
        }
        else
        {
            snew(name, strlen(dval)+1);
            sscanf(dval, "%s", name);
            for (i = 0; (i < ndef); i++)
            {
                if (strcmp(defs[i].name, name) == 0)
                {
                    break;
                }
            }
            handle->nifdef++;
            srenew(handle->ifdefs, handle->nifdef);
            if ((bIfdef && (i < ndef)) || (bIfndef && (i == ndef)))
            {
                handle->ifdefs[handle->nifdef-1] = eifTRUE;
            }
            else
            {
                handle->ifdefs[handle->nifdef-1] = eifFALSE;
            }
            sfree(name);
        }
        return eCPP_OK;
    }

    /* #else statement */
    if (strcmp(dname, "else") == 0)
    {
        if (handle->nifdef <= 0)
        {
            return eCPP_SYNTAX;
        }
        if (handle->ifdefs[handle->nifdef-1] == eifTRUE)
        {
            handle->ifdefs[handle->nifdef-1] = eifFALSE;
        }
        else if (handle->ifdefs[handle->nifdef-1] == eifFALSE)
        {
            handle->ifdefs[handle->nifdef-1] = eifTRUE;
        }
        return eCPP_OK;
    }

    /* #endif statement */
    if (strcmp(dname, "endif") == 0)
    {
        if (handle->nifdef <= 0)
        {
            return eCPP_SYNTAX;
        }
        handle->nifdef--;
        return eCPP_OK;
    }

    /* Check whether we're not ifdeffed out. The order of this statement
       is important. It has to come after #ifdef, #else and #endif, but
       anything else should be ignored. */
    if (is_ifdeffed_out(handle))
    {
        return eCPP_OK;
    }

    /* Check for include statements */
    if (strcmp(dname, "include") == 0)
    {
        len = -1;
        i0  = 0;
        for (i1 = 0; (i1 < strlen(dval)); i1++)
        {
            if ((dval[i1] == '"') || (dval[i1] == '<') || (dval[i1] == '>'))
            {
                if (len == -1)
                {
                    i0  = i1+1;
                    len = 0;
                }
                else
                {
                    break;
                }
            }
            else if (len >= 0)
            {
                len++;
            }
        }
        if (len == -1)
        {
            return eCPP_SYNTAX;
        }
        snew(inc_fn, len+1);
        strncpy(inc_fn, dval+i0, len);
        inc_fn[len] = '\0';

        if (debug)
        {
            fprintf(debug, "Going to open include file '%s' i0 = %d, strlen = %d\n",
                    inc_fn, i0, len);
        }
        /* Open include file and store it as a child in the handle structure */
        status = cpp_open_file(inc_fn, &(handle->child), NULL);
        sfree(inc_fn);
        if (status != eCPP_OK)
        {
            handle->child = NULL;
            return status;
        }
        /* Make a linked list of open files and move on to the include file */
        handle->child->parent = handle;
        *handlep              = handle->child;
        handle                = *handlep;
        return eCPP_OK;
    }

    /* #define statement */
    if (strcmp(dname, "define") == 0)
    {
        /* Split it into name and value. */
        ptr = dval;
        while ((*ptr != '\0') && !isspace(*ptr))
        {
            ptr++;
        }
        name = gmx_strndup(dval, ptr - dval);

        while ((*ptr != '\0') && isspace(*ptr))
        {
            ptr++;
        }

        add_define(name, ptr);
        sfree(name);
        return eCPP_OK;
    }

    /* #undef statement */
    if (strcmp(dname, "undef") == 0)
    {
        snew(name, strlen(dval)+1);
        sscanf(dval, "%s", name);
        for (i = 0; (i < ndef); i++)
        {
            if (strcmp(defs[i].name, name) == 0)
            {
                sfree(defs[i].name);
                sfree(defs[i].def);
                break;
            }
        }
        sfree(name);
        for (; (i < ndef-1); i++)
        {
            defs[i].name = defs[i+1].name;
            defs[i].def  = defs[i+1].def;
        }
        ndef--;

        return eCPP_OK;
    }

    /* If we haven't matched anything, this is an unknown directive */
    return eCPP_SYNTAX;
}
예제 #2
0
int
_gmx_sel_lexer_process_identifier(YYSTYPE *yylval, YYLTYPE *yylloc,
                                  char *yytext, size_t yyleng,
                                  gmx_sel_lexer_t *state)
{
    /* Check if the identifier matches with a parameter name */
    if (state->msp >= 0)
    {
        gmx_ana_selparam_t *param   = nullptr;
        bool                bBoolNo = false;
        int                 sp      = state->msp;
        while (!param && sp >= 0)
        {
            int             i;
            for (i = 0; i < state->mstack[sp]->nparams; ++i)
            {
                /* Skip NULL parameters and too long parameters */
                if (state->mstack[sp]->param[i].name == nullptr
                    || strlen(state->mstack[sp]->param[i].name) > yyleng)
                {
                    continue;
                }
                if (!strncmp(state->mstack[sp]->param[i].name, yytext, yyleng))
                {
                    param = &state->mstack[sp]->param[i];
                    break;
                }
                /* Check separately for a 'no' prefix on boolean parameters */
                if (state->mstack[sp]->param[i].val.type == NO_VALUE
                    && yyleng > 2 && yytext[0] == 'n' && yytext[1] == 'o'
                    && !strncmp(state->mstack[sp]->param[i].name, yytext+2, yyleng-2))
                {
                    param   = &state->mstack[sp]->param[i];
                    bBoolNo = true;
                    break;
                }
            }
            if (!param)
            {
                --sp;
            }
        }
        if (param)
        {
            if (param->val.type == NO_VALUE && !bBoolNo)
            {
                state->bMatchBool = true;
            }
            if (sp < state->msp)
            {
                state->neom      = state->msp - sp - 1;
                state->nextparam = param;
                state->bBoolNo   = bBoolNo;
                return END_OF_METHOD;
            }
            _gmx_sel_lexer_add_token(yylloc, param->name, -1, state);
            return init_param_token(yylval, param, bBoolNo);
        }
    }

    /* Check if the identifier matches with a symbol */
    const gmx::SelectionParserSymbol *symbol
        = state->sc->symtab->findSymbol(std::string(yytext, yyleng));
    /* If there is no match, return the token as a string */
    if (!symbol)
    {
        yylval->str = gmx_strndup(yytext, yyleng);
        _gmx_sel_lexer_add_token(yylloc, yytext, yyleng, state);
        return IDENTIFIER;
    }
    gmx::SelectionParserSymbol::SymbolType symtype = symbol->type();
    /* For method symbols, we need some extra processing. */
    if (symtype == gmx::SelectionParserSymbol::MethodSymbol)
    {
        return init_method_token(yylval, yylloc, symbol, state->prev_pos_kw > 0, state);
    }
    _gmx_sel_lexer_add_token(yylloc, symbol->name().c_str(), -1, state);
    /* Reserved symbols should have been caught earlier */
    if (symtype == gmx::SelectionParserSymbol::ReservedSymbol)
    {
        GMX_THROW(gmx::InternalError(gmx::formatString(
                                             "Mismatch between tokenizer and reserved symbol table (for '%s')",
                                             symbol->name().c_str())));
    }
    /* For variable symbols, return the type of the variable value */
    if (symtype == gmx::SelectionParserSymbol::VariableSymbol)
    {
        const gmx::SelectionTreeElementPointer &var = symbol->variableValue();
        /* Return simple tokens for constant variables */
        if (var->type == SEL_CONST)
        {
            switch (var->v.type)
            {
                case INT_VALUE:
                    yylval->i = var->v.u.i[0];
                    return TOK_INT;
                case REAL_VALUE:
                    yylval->r = var->v.u.r[0];
                    return TOK_REAL;
                case POS_VALUE:
                    break;
                default:
                    GMX_THROW(gmx::InternalError("Unsupported variable type"));
            }
        }
        yylval->sel = new gmx::SelectionTreeElementPointer(var);
        switch (var->v.type)
        {
            case INT_VALUE:   return VARIABLE_NUMERIC;
            case REAL_VALUE:  return VARIABLE_NUMERIC;
            case POS_VALUE:   return VARIABLE_POS;
            case GROUP_VALUE: return VARIABLE_GROUP;
            default:
                delete yylval->sel;
                GMX_THROW(gmx::InternalError("Unsupported variable type"));
        }
        /* This position should not be reached. */
    }
    /* For position symbols, we need to return KEYWORD_POS, but we also need
     * some additional handling. */
    if (symtype == gmx::SelectionParserSymbol::PositionSymbol)
    {
        state->bMatchOf    = true;
        yylval->str        = gmx_strdup(symbol->name().c_str());
        state->prev_pos_kw = 2;
        return KEYWORD_POS;
    }
    /* Should not be reached */
    return INVALID;
}
예제 #3
0
/* Open the file to be processed. The handle variable holds internal
   info for the cpp emulator. Return integer status */
int cpp_open_file(const char *filenm, gmx_cpp_t *handle, char **cppopts)
{
    gmx_cpp_t    cpp;
    char        *buf, *pdum;
    char        *ptr, *ptr2;
    int          i;
    unsigned int i1;

    /* First process options, they might be necessary for opening files
       (especially include statements). */
    i  = 0;
    if (cppopts)
    {
        while (cppopts[i])
        {
            if (strstr(cppopts[i], "-I") == cppopts[i])
            {
                add_include(cppopts[i]+2);
            }
            if (strstr(cppopts[i], "-D") == cppopts[i])
            {
                /* If the option contains a =, split it into name and value. */
                ptr = strchr(cppopts[i], '=');
                if (ptr)
                {
                    buf = gmx_strndup(cppopts[i] + 2, ptr - cppopts[i] - 2);
                    add_define(buf, ptr + 1);
                    sfree(buf);
                }
                else
                {
                    add_define(cppopts[i] + 2, NULL);
                }
            }
            i++;
        }
    }
    if (debug)
    {
        fprintf(debug, "GMXCPP: added %d command line arguments\n", i);
    }

    snew(cpp, 1);
    *handle      = cpp;
    cpp->fn      = NULL;
    /* Find the file. First check whether it is in the current directory. */
    if (gmx_fexist(filenm))
    {
        cpp->fn = gmx_strdup(filenm);
    }
    else
    {
        /* If not, check all the paths given with -I. */
        for (i = 0; i < nincl; ++i)
        {
            snew(buf, strlen(incl[i]) + strlen(filenm) + 2);
            sprintf(buf, "%s/%s", incl[i], filenm);
            if (gmx_fexist(buf))
            {
                cpp->fn = buf;
                break;
            }
            sfree(buf);
        }
        /* If still not found, check the Gromacs library search path. */
        if (!cpp->fn)
        {
            cpp->fn = low_gmxlibfn(filenm, FALSE, FALSE);
        }
    }
    if (!cpp->fn)
    {
        gmx_fatal(FARGS, "Topology include file \"%s\" not found", filenm);
    }
    if (NULL != debug)
    {
        fprintf(debug, "GMXCPP: cpp file open %s\n", cpp->fn);
    }
    /* If the file name has a path component, we need to change to that
     * directory. Note that we - just as C - always use UNIX path separators
     * internally in include file names.
     */
    ptr  = strrchr(cpp->fn, '/');
    ptr2 = strrchr(cpp->fn, DIR_SEPARATOR);

    if (ptr == NULL || (ptr2 != NULL && ptr2 > ptr))
    {
        ptr = ptr2;
    }
    if (ptr == NULL)
    {
        cpp->path = NULL;
        cpp->cwd  = NULL;
    }
    else
    {
        cpp->path = cpp->fn;
        *ptr      = '\0';
        cpp->fn   = gmx_strdup(ptr+1);
        snew(cpp->cwd, STRLEN);

        gmx_getcwd(cpp->cwd, STRLEN);
        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: cwd %s\n", cpp->cwd);
        }
        gmx_chdir(cpp->path);

        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: chdir to %s\n", cpp->path);
        }
    }
    cpp->line_len = 0;
    cpp->line     = NULL;
    cpp->line_nr  = 0;
    cpp->nifdef   = 0;
    cpp->ifdefs   = NULL;
    cpp->child    = NULL;
    cpp->parent   = NULL;
    if (cpp->fp == NULL)
    {
        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: opening file %s\n", cpp->fn);
        }
        cpp->fp = fopen(cpp->fn, "r");
    }
    if (cpp->fp == NULL)
    {
        switch (errno)
        {
            case EINVAL:
            default:
                return eCPP_UNKNOWN;
        }
    }
    return eCPP_OK;
}