/*! * \param[out] selp Pointer to receive a pointer to the created selection * element (set to NULL on error). * \param[in] method Keyword selection method to evaluate. * \param[in] param Parameter that gives the group to evaluate \p method in. * \param[in] scanner Scanner data structure. * \returns 0 on success, non-zero error code on error. * * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp) * that evaluates the keyword method given by \p method in the group given by * \p param. */ int _gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method, t_selexpr_param *param, void *scanner) { t_selelem *sel; t_methoddata_kweval *data; gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner); char buf[1024]; sprintf(buf, "In evaluation of '%s'", method->name); gmx::MessageStringContext context(errors, buf); if ((method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL)) || method->outinit || method->pupdate) { _gmx_selexpr_free_params(param); GMX_ERROR(gmx::eeInternalError, "Unsupported keyword method for arbitrary group evaluation"); } *selp = NULL; sel = _gmx_selelem_create(SEL_EXPRESSION); _gmx_selelem_set_method(sel, method, scanner); snew(data, 1); data->kwmethod = sel->u.expr.method; data->kwmdata = sel->u.expr.mdata; gmx_ana_index_clear(&data->g); snew(sel->u.expr.method, 1); memcpy(sel->u.expr.method, data->kwmethod, sizeof(gmx_ana_selmethod_t)); sel->u.expr.method->flags |= SMETH_VARNUMVAL; sel->u.expr.method->init_data = NULL; sel->u.expr.method->set_poscoll = NULL; sel->u.expr.method->init = method->init ? &init_kweval : NULL; sel->u.expr.method->outinit = &init_output_kweval; sel->u.expr.method->free = &free_data_kweval; sel->u.expr.method->init_frame = method->init_frame ? &init_frame_kweval : NULL; sel->u.expr.method->update = &evaluate_kweval; sel->u.expr.method->pupdate = NULL; sel->u.expr.method->nparams = asize(smparams_kweval); sel->u.expr.method->param = smparams_kweval; _gmx_selelem_init_method_params(sel, scanner); sel->u.expr.mdata = data; sel->u.expr.method->param[0].val.u.g = &data->g; sfree(param->name); param->name = NULL; if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams, sel->u.expr.method->param, sel, scanner)) { _gmx_selelem_free(sel); return -1; } *selp = sel; return 0; }
/*! * \param pparams List of parameters from the selection parser. * \param[in] nparam Number of parameters in \p params. * \param params Array of parameters to parse. * \param root Selection element to which child expressions are added. * \param[in] scanner Scanner data structure. * \returns TRUE if the parameters were parsed successfully, FALSE otherwise. * * Initializes the \p params array based on the parameters in \p pparams. * See the documentation of \c gmx_ana_selparam_t for different options * available for parsing. * * The list \p pparams and any associated values are freed after the parameters * have been processed, no matter is there was an error or not. */ gmx_bool _gmx_sel_parse_params(t_selexpr_param *pparams, int nparam, gmx_ana_selparam_t *params, t_selelem *root, void *scanner) { t_selexpr_param *pparam; gmx_ana_selparam_t *oparam; gmx_bool bOk, rc; int i; /* Check that the value pointers of SPAR_VARNUM parameters are NULL and * that they are not NULL for other parameters */ bOk = TRUE; for (i = 0; i < nparam; ++i) { if (params[i].val.type != POS_VALUE && (params[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL))) { if (params[i].val.u.ptr != NULL) { _gmx_selparser_error("warning: value pointer of parameter '%s' is not NULL\n" " although it should be for SPAR_VARNUM and SPAR_ATOMVAL parameters\n", params[i].name); } if ((params[i].flags & SPAR_VARNUM) && (params[i].flags & SPAR_DYNAMIC) && !params[i].nvalptr) { _gmx_selparser_error("error: nvalptr of parameter '%s' is NULL\n" " but both SPAR_VARNUM and SPAR_DYNAMIC are specified\n", params[i].name); bOk = FALSE; } } else { if (params[i].val.u.ptr == NULL) { _gmx_selparser_error("error: value pointer of parameter '%s' is NULL\n", params[i].name); bOk = FALSE; } } } if (!bOk) { _gmx_selexpr_free_params(pparams); return FALSE; } /* Parse the parameters */ pparam = pparams; i = 0; while (pparam) { /* Find the parameter and make some checks */ if (pparam->name != NULL) { i = -1; oparam = gmx_ana_selparam_find(pparam->name, nparam, params); } else if (i >= 0) { oparam = ¶ms[i]; if (oparam->name != NULL) { oparam = NULL; _gmx_selparser_error("too many NULL parameters provided"); bOk = FALSE; goto next_param; } ++i; } else { _gmx_selparser_error("all NULL parameters should appear in the beginning of the list"); bOk = FALSE; pparam = pparam->next; continue; } if (!oparam) { _gmx_selparser_error("unknown parameter '%s' skipped", pparam->name); bOk = FALSE; goto next_param; } if (oparam->flags & SPAR_SET) { _gmx_selparser_error("parameter '%s' set multiple times, extra values skipped", pparam->name); bOk = FALSE; goto next_param; } oparam->flags |= SPAR_SET; /* Process the values for the parameter */ convert_const_values(pparam->value); if (convert_values(pparam->value, oparam->val.type, scanner) != 0) { _gmx_selparser_error("invalid value for parameter '%s'", pparam->name); bOk = FALSE; goto next_param; } if (oparam->val.type == NO_VALUE) { rc = parse_values_gmx_bool(pparam->name, pparam->nval, pparam->value, oparam); } else if (oparam->flags & SPAR_RANGES) { rc = parse_values_range(pparam->nval, pparam->value, oparam); } else if (oparam->flags & SPAR_VARNUM) { if (pparam->nval == 1 && pparam->value->bExpr) { rc = parse_values_varnum_expr(pparam->nval, pparam->value, oparam, root); } else { rc = parse_values_varnum(pparam->nval, pparam->value, oparam, root); } } else if (oparam->flags & SPAR_ENUMVAL) { rc = parse_values_enum(pparam->nval, pparam->value, oparam); } else { rc = parse_values_std(pparam->nval, pparam->value, oparam, root); } if (!rc) { bOk = FALSE; } /* Advance to the next parameter */ next_param: pparam = pparam->next; } /* Check that all required parameters are present */ for (i = 0; i < nparam; ++i) { if (!(params[i].flags & SPAR_OPTIONAL) && !(params[i].flags & SPAR_SET)) { _gmx_selparser_error("required parameter '%s' not specified", params[i].name); bOk = FALSE; } } _gmx_selexpr_free_params(pparams); return bOk; }