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; }
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; }
/* 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; }