Пример #1
0
Rlist *NewExpArgs(EvalContext *ctx, const Policy *policy, const FnCall *fp, const FnCallType *fp_type)
{
    // Functions with delayed evaluation will call this themselves later
    if (fp_type && fp_type->options & FNCALL_OPTION_DELAYED_EVALUATION)
    {
        return RlistCopy(fp->args);
    }

    const FnCallType *fn = FnCallTypeGet(fp->name);
    {
        int len = RlistLen(fp->args);

        if (!(fn->options & FNCALL_OPTION_VARARG))
        {
            if (len != FnNumArgs(fn))
            {
                Log(LOG_LEVEL_ERR, "Arguments to function '%s' do not tally. Expected %d not %d",
                      fp->name, FnNumArgs(fn), len);
                PromiseRef(LOG_LEVEL_ERR, fp->caller);
                exit(EXIT_FAILURE);
            }
        }
    }

    Rlist *expanded_args = NULL;
    for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next)
    {
        Rval rval;

        switch (rp->val.type)
        {
        case RVAL_TYPE_FNCALL:
            {
                FnCall *subfp = RlistFnCallValue(rp);
                rval = FnCallEvaluate(ctx, policy, subfp, fp->caller).rval;
            }
            break;
        default:
            rval = ExpandPrivateRval(ctx, NULL, NULL, rp->val.item, rp->val.type);
            assert(rval.item);
            break;
        }

        /*

          Collect compound values into containers only if the function
          supports it.

          Functions without FNCALL_OPTION_COLLECTING don't collect
          Rlist elements. So in the policy, you call
          and(splitstring("a b")) and it ends up as and("a", "b").
          This expansion happens once per FnCall, not for all
          arguments.

          Functions with FNCALL_OPTION_COLLECTING instead collect all
          the results of a FnCall into a single JSON array object. It
          requires functions to expect it, but it's the only
          reasonable way to preserve backwards compatibility for
          functions like and() and allow nesting of calls to functions
          that take and return compound data types.

        */
        RlistAppendAllTypes(&expanded_args, rval.item, rval.type,
                            (fn->options & FNCALL_OPTION_COLLECTING));
        RvalDestroy(rval);
    }

    return expanded_args;
}
Пример #2
0
// NOTE: Copies item, does NOT take ownership
Rlist *RlistAppend(Rlist **start, const void *item, RvalType type)
{
    return RlistAppendAllTypes(start, item, type, false);
}