Пример #1
0
/*!
 * \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;
}
Пример #2
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 = &params[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;
}