示例#1
0
static JsonElement *FnCallToJson(const FnCall *fp)
{
    assert(fp);

    JsonElement *object = JsonObjectCreate(3);

    JsonObjectAppendString(object, "name", fp->name);
    JsonObjectAppendString(object, "type", "function-call");

    JsonElement *argsArray = JsonArrayCreate(5);

    for (Rlist *rp = fp->args; rp != NULL; rp = rp->next)
    {
        switch (rp->val.type)
        {
        case RVAL_TYPE_SCALAR:
            JsonArrayAppendString(argsArray, RlistScalarValue(rp));
            break;

        case RVAL_TYPE_FNCALL:
            JsonArrayAppendObject(argsArray, FnCallToJson(RlistFnCallValue(rp)));
            break;

        default:
            assert(false && "Unknown argument type");
            break;
        }
    }
    JsonObjectAppendArray(object, "arguments", argsArray);

    return object;
}
示例#2
0
static JsonElement *RlistToJson(Rlist *list)
{
    JsonElement *array = JsonArrayCreate(RlistLen(list));

    for (Rlist *rp = list; rp; rp = rp->next)
    {
        switch (rp->val.type)
        {
        case RVAL_TYPE_SCALAR:
            JsonArrayAppendString(array, RlistScalarValue(rp));
            break;

        case RVAL_TYPE_LIST:
            JsonArrayAppendArray(array, RlistToJson(RlistRlistValue(rp)));
            break;

        case RVAL_TYPE_FNCALL:
            JsonArrayAppendObject(array, FnCallToJson(RlistFnCallValue(rp)));
            break;

        default:
            assert(false && "Unsupported item type in rlist");
            break;
        }
    }

    return array;
}
示例#3
0
文件: fncall.c 项目: dstam/core
void FnCallWrite(Writer *writer, const FnCall *call)
{
    WriterWrite(writer, call->name);
    WriterWriteChar(writer, '(');

    for (const Rlist *rp = call->args; rp != NULL; rp = rp->next)
    {
        switch (rp->val.type)
        {
        case RVAL_TYPE_SCALAR:
            ScalarWrite(writer, RlistScalarValue(rp), true);
            break;

        case RVAL_TYPE_FNCALL:
            FnCallWrite(writer, RlistFnCallValue(rp));
            break;

        default:
            WriterWrite(writer, "(** Unknown argument **)\n");
            break;
        }

        if (rp->next != NULL)
        {
            WriterWriteChar(writer, ',');
        }
    }

    WriterWriteChar(writer, ')');
}
示例#4
0
文件: loading.c 项目: ddurieux/core
static bool VerifyBundleSequence(EvalContext *ctx, const Policy *policy, const GenericAgentConfig *config)
{
    Rlist *fallback = NULL;
    const Rlist *bundlesequence = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BUNDLESEQUENCE);
    if (!bundlesequence)
    {
        RlistAppendScalar(&fallback, "main");
        bundlesequence = fallback;
    }

    const char *name;
    int ok = true;
    for (const Rlist *rp = bundlesequence; rp != NULL; rp = rp->next)
    {
        switch (rp->val.type)
        {
        case RVAL_TYPE_SCALAR:
            name = RlistScalarValue(rp);
            break;

        case RVAL_TYPE_FNCALL:
            name = RlistFnCallValue(rp)->name;
            break;

        default:
            name = NULL;
            ok = false;
            {
                Writer *w = StringWriter();
                WriterWrite(w, "Illegal item found in bundlesequence '");
                RvalWrite(w, rp->val);
                WriterWrite(w, "'");
                Log(LOG_LEVEL_ERR, "%s", StringWriterData(w));
                WriterClose(w);
            }
            continue;
        }

        if (strcmp(name, CF_NULL_VALUE) == 0)
        {
            continue;
        }

        if (!config->ignore_missing_bundles && !PolicyGetBundle(policy, NULL, NULL, name))
        {
            Log(LOG_LEVEL_ERR, "Bundle '%s' listed in the bundlesequence is not a defined bundle", name);
            ok = false;
        }
    }

    RlistDestroy(fallback);
    return ok;
}
示例#5
0
static Rlist *NewExpArgs(EvalContext *ctx, const Policy *policy, const FnCall *fp)
{
    {
        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;
                assert(rval.item);
            }
            break;
        default:
            rval = ExpandPrivateRval(ctx, NULL, NULL, rp->val.item, rp->val.type);
            assert(rval.item);
            break;
        }

        RlistAppend(&expanded_args, rval.item, rval.type);
        RvalDestroy(rval);
    }

    return expanded_args;
}
示例#6
0
文件: fncall.c 项目: cduclos/core
static Rlist *NewExpArgs(EvalContext *ctx, const FnCall *fp)
{
    int len;
    Rval rval;
    Rlist *newargs = NULL;
    FnCall *subfp;
    const FnCallType *fn = FnCallTypeGet(fp->name);

    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(1);
        }
    }

    for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next)
    {
        switch (rp->val.type)
        {
        case RVAL_TYPE_FNCALL:
            subfp = RlistFnCallValue(rp);
            rval = FnCallEvaluate(ctx, subfp, fp->caller).rval;
            assert(rval.item);
            break;
        default:
            rval = ExpandPrivateRval(ctx, NULL, NULL, (Rval) { rp->val.item, rp->val.type});
            assert(rval.item);
            break;
        }

        RlistAppendRval(&newargs, rval);
    }

    return newargs;
}
示例#7
0
文件: fncall.c 项目: cduclos/core
void FnCallShow(FILE *fout, const char *prefix, const FnCall *fp, const Rlist *args)
{
    fprintf(fout, "%s %s(", prefix, fp->name);

    for (const Rlist *rp = args; rp != NULL; rp = rp->next)
    {
        switch (rp->val.type)
        {
        case RVAL_TYPE_SCALAR:
            fprintf(fout, "%s,", RlistScalarValue(rp));
            break;

        case RVAL_TYPE_FNCALL:
            FnCallShow(fout, prefix, RlistFnCallValue(rp), NULL);
            break;

        default:
            fprintf(fout, "(** Unknown argument **)\n");
            break;
        }
    }

    fprintf(fout, ") from %s\n", fp->caller->promiser);
}
示例#8
0
文件: fncall.c 项目: dstam/core
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;
}
示例#9
0
void ScopeMapBodyArgs(EvalContext *ctx, const Body *body, const Rlist *args)
{
    const Rlist *arg = NULL;
    const Rlist *param = NULL;

    for (arg = args, param = body->args; arg != NULL && param != NULL; arg = arg->next, param = param->next)
    {
        DataType arg_type = CF_DATA_TYPE_NONE;
        switch (arg->val.type)
        {
        case RVAL_TYPE_SCALAR:
            arg_type = StringDataType(ctx, RlistScalarValue(arg));
            break;

        case RVAL_TYPE_FNCALL:
            {
                const FnCallType *fn = FnCallTypeGet(RlistFnCallValue(arg)->name);
                if (!fn)
                {
                    FatalError(ctx, "Argument '%s' given to body '%s' is not a valid function",
                               RlistFnCallValue(arg)->name, body->name);
                }
                arg_type = fn->dtype;
            }
            break;

        default:
            FatalError(ctx, "Cannot derive data type from Rval type %c", arg->val.type);
        }

        switch (arg->val.type)
        {
        case RVAL_TYPE_SCALAR:
            {
                const char *lval = RlistScalarValue(param);
                VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.');
                EvalContextVariablePut(ctx, ref, RvalScalarValue(arg->val), arg_type, "source=body");
                VarRefDestroy(ref);
            }
            break;

        case RVAL_TYPE_LIST:
            {
                const char *lval = RlistScalarValue(param);
                VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.');
                EvalContextVariablePut(ctx, ref, RvalRlistValue(arg->val), arg_type, "source=body");
                VarRefDestroy(ref);
            }
            break;

        case RVAL_TYPE_FNCALL:
            {
                FnCall *fp = RlistFnCallValue(arg);
                arg_type = CF_DATA_TYPE_NONE;
                {
                    const FnCallType *fncall_type = FnCallTypeGet(fp->name);
                    if (fncall_type)
                    {
                        arg_type = fncall_type->dtype;
                    }
                }

                FnCallResult res = FnCallEvaluate(ctx, body->parent_policy, fp, NULL);

                if (res.status == FNCALL_FAILURE && THIS_AGENT_TYPE != AGENT_TYPE_COMMON)
                {
                    Log(LOG_LEVEL_VERBOSE, "Embedded function argument does not resolve to a name - probably too many evaluation levels for '%s'",
                        fp->name);
                }
                else
                {
                    const char *lval = RlistScalarValue(param);
                    void *rval = res.rval.item;

                    VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.');
                    EvalContextVariablePut(ctx, ref, rval, arg_type, "source=body");
                    VarRefDestroy(ref);
                }

                RvalDestroy(res.rval);
            }

            break;

        default:
            /* Nothing else should happen */
            ProgrammingError("Software error: something not a scalar/function in argument literal");
        }
    }
}
示例#10
0
void ScopeAugment(EvalContext *ctx, const Bundle *bp, const Promise *pp, const Rlist *arguments)
{
    if (RlistLen(bp->args) != RlistLen(arguments))
    {
        Log(LOG_LEVEL_ERR, "While constructing scope '%s'", bp->name);
        fprintf(stderr, "Formal = ");
        RlistShow(stderr, bp->args);
        fprintf(stderr, ", Actual = ");
        RlistShow(stderr, arguments);
        fprintf(stderr, "\n");
        FatalError(ctx, "Augment scope, formal and actual parameter mismatch is fatal");
    }

    const Bundle *pbp = NULL;
    if (pp != NULL)
    {
        pbp = PromiseGetBundle(pp);
    }

    for (const Rlist *rpl = bp->args, *rpr = arguments; rpl != NULL; rpl = rpl->next, rpr = rpr->next)
    {
        const char *lval = RlistScalarValue(rpl);

        Log(LOG_LEVEL_VERBOSE, "Augment scope '%s' with variable '%s' (type: %c)", bp->name, lval, rpr->val.type);

        // CheckBundleParameters() already checked that there is no namespace collision
        // By this stage all functions should have been expanded, so we only have scalars left

        if (rpr->val.type == RVAL_TYPE_SCALAR && IsNakedVar(RlistScalarValue(rpr), '@'))
        {

            char naked[CF_BUFSIZE];
            
            GetNaked(naked, RlistScalarValue(rpr));

            DataType value_type = CF_DATA_TYPE_NONE;
            const void *value = NULL;
            if (pbp != NULL)
            {
                VarRef *ref = VarRefParseFromBundle(naked, pbp);
                value = EvalContextVariableGet(ctx, ref, &value_type);
                VarRefDestroy(ref);
            }
            else
            {
                VarRef *ref = VarRefParseFromBundle(naked, bp);
                value = EvalContextVariableGet(ctx, ref, &value_type);
                VarRefDestroy(ref);
            }

            switch (value_type)
            {
            case CF_DATA_TYPE_STRING_LIST:
            case CF_DATA_TYPE_INT_LIST:
            case CF_DATA_TYPE_REAL_LIST:
                {
                    VarRef *ref = VarRefParseFromBundle(lval, bp);
                    EvalContextVariablePut(ctx, ref, value, CF_DATA_TYPE_STRING_LIST, "source=promise");
                    VarRefDestroy(ref);
                }
                break;
            case CF_DATA_TYPE_CONTAINER:
                {
                    VarRef *ref = VarRefParseFromBundle(lval, bp);
                    EvalContextVariablePut(ctx, ref, value, CF_DATA_TYPE_CONTAINER, "source=promise");
                    VarRefDestroy(ref);
                }
                break;
            default:
                {
                    Log(LOG_LEVEL_ERR, "List or container parameter '%s' not found while constructing scope '%s' - use @(scope.variable) in calling reference", naked, bp->name);
                    VarRef *ref = VarRefParseFromBundle(lval, bp);
                    EvalContextVariablePut(ctx, ref, RlistScalarValue(rpr), CF_DATA_TYPE_STRING, "source=promise");
                    VarRefDestroy(ref);
                }
                break;
            }
        }
        else
        {
            switch(rpr->val.type)
            {
            case RVAL_TYPE_SCALAR:
                {
                    VarRef *ref = VarRefParseFromBundle(lval, bp);
                    EvalContextVariablePut(ctx, ref, RvalScalarValue(rpr->val), CF_DATA_TYPE_STRING, "source=promise");
                    VarRefDestroy(ref);
                }
                break;

            case RVAL_TYPE_FNCALL:
                {
                    FnCall *subfp = RlistFnCallValue(rpr);
                    Rval rval = FnCallEvaluate(ctx, PromiseGetPolicy(pp), subfp, pp).rval;
                    if (rval.type == RVAL_TYPE_SCALAR)
                    {
                        VarRef *ref = VarRefParseFromBundle(lval, bp);
                        EvalContextVariablePut(ctx, ref, RvalScalarValue(rval), CF_DATA_TYPE_STRING, "source=promise");
                        VarRefDestroy(ref);
                    }
                    else
                    {
                        Log(LOG_LEVEL_ERR, "Only functions returning scalars can be used as arguments");
                    }
                    RvalDestroy(rval);
                }
                break;
            default:
                ProgrammingError("An argument neither a scalar nor a list seemed to appear. Impossible");
            }
        }
    }

/* Check that there are no danglers left to evaluate in the hash table itself */

    return;
}
示例#11
0
文件: expand.c 项目: tzz/core
Rval EvaluateFinalRval(EvalContext *ctx, const Policy *policy, const char *ns, const char *scope,
                       Rval rval, bool forcelist, const Promise *pp)
{
    assert(ctx);
    assert(policy);

    Rval returnval, newret;
    if ((rval.type == RVAL_TYPE_SCALAR) && IsNakedVar(rval.item, '@'))        /* Treat lists specially here */
    {
        char naked[CF_MAXVARSIZE];
        GetNaked(naked, rval.item);

        if (!IsExpandable(naked))
        {
            VarRef *ref = VarRefParseFromScope(naked, scope);
            DataType value_type = DATA_TYPE_NONE;
            const void *value = EvalContextVariableGet(ctx, ref, &value_type);

            if (!value || DataTypeToRvalType(value_type) != RVAL_TYPE_LIST)
            {
                returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
            }
            else
            {
                returnval.item = ExpandList(ctx, ns, scope, value, true);
                returnval.type = RVAL_TYPE_LIST;
            }

            VarRefDestroy(ref);
        }
        else
        {
            returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
        }
    }
    else
    {
        if (forcelist)          /* We are replacing scalar @(name) with list */
        {
            returnval = ExpandPrivateRval(ctx, ns, scope, rval.item, rval.type);
        }
        else
        {
            if (FnCallIsBuiltIn(rval))
            {
                returnval = RvalCopy(rval);
            }
            else
            {
                returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
            }
        }
    }

    switch (returnval.type)
    {
    case RVAL_TYPE_SCALAR:
    case RVAL_TYPE_CONTAINER:
        break;

    case RVAL_TYPE_LIST:
        for (Rlist *rp = RvalRlistValue(returnval); rp; rp = rp->next)
        {
            if (rp->val.type == RVAL_TYPE_FNCALL)
            {
                FnCall *fp = RlistFnCallValue(rp);
                FnCallResult res = FnCallEvaluate(ctx, policy, fp, pp);

                FnCallDestroy(fp);
                rp->val = res.rval;
            }
            else
            {
                if (EvalContextStackCurrentPromise(ctx))
                {
                    if (IsCf3VarString(RlistScalarValue(rp)))
                    {
                        newret = ExpandPrivateRval(ctx, NULL, "this", rp->val.item, rp->val.type);
                        free(rp->val.item);
                        rp->val.item = newret.item;
                    }
                }
            }

            /* returnval unchanged */
        }
        break;

    case RVAL_TYPE_FNCALL:
        if (FnCallIsBuiltIn(returnval))
        {
            FnCall *fp = RvalFnCallValue(returnval);
            returnval = FnCallEvaluate(ctx, policy, fp, pp).rval;
            FnCallDestroy(fp);
        }
        break;

    default:
        returnval.item = NULL;
        returnval.type = RVAL_TYPE_NOPROMISEE;
        break;
    }

    return returnval;
}
示例#12
0
文件: expand.c 项目: kkaempf/core
Rval EvaluateFinalRval(EvalContext *ctx, const Policy *policy,
                       const char *ns, const char *scope,
                       Rval rval, bool forcelist, const Promise *pp)
{
    assert(ctx);
    assert(policy);
    Rval returnval;

    /* Treat lists specially. */
    if (rval.type == RVAL_TYPE_SCALAR && IsNakedVar(rval.item, '@'))
    {
        char naked[CF_MAXVARSIZE];
        GetNaked(naked, rval.item);

        if (IsExpandable(naked))                /* example: @(blah_$(blue)) */
        {
            returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
        }
        else
        {
            VarRef *ref = VarRefParseFromScope(naked, scope);
            DataType value_type;
            const void *value = EvalContextVariableGet(ctx, ref, &value_type);
            VarRefDestroy(ref);

            if (DataTypeToRvalType(value_type) == RVAL_TYPE_LIST)
            {
                returnval.item = ExpandList(ctx, ns, scope, value, true);
                returnval.type = RVAL_TYPE_LIST;
            }
            else
            {
                returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
            }
        }
    }
    else if (forcelist) /* We are replacing scalar @(name) with list */
    {
        returnval = ExpandPrivateRval(ctx, ns, scope, rval.item, rval.type);
    }
    else if (FnCallIsBuiltIn(rval))
    {
        returnval = RvalCopy(rval);
    }
    else
    {
        returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
    }

    switch (returnval.type)
    {
    case RVAL_TYPE_SCALAR:
    case RVAL_TYPE_CONTAINER:
        break;

    case RVAL_TYPE_LIST:
        for (Rlist *rp = RvalRlistValue(returnval); rp; rp = rp->next)
        {
            switch (rp->val.type)
            {
            case RVAL_TYPE_FNCALL:
            {
                FnCall *fp = RlistFnCallValue(rp);
                rp->val = FnCallEvaluate(ctx, policy, fp, pp).rval;
                FnCallDestroy(fp);
                break;
            }
            case RVAL_TYPE_SCALAR:
                if (EvalContextStackCurrentPromise(ctx) &&
                    IsCf3VarString(RlistScalarValue(rp)))
                {
                    void *prior = rp->val.item;
                    rp->val = ExpandPrivateRval(ctx, NULL, "this",
                                                prior, RVAL_TYPE_SCALAR);
                    free(prior);
                }
                /* else: returnval unchanged. */
                break;
            default:
                assert(!"Bad type for entry in Rlist");
            }
        }
        break;

    case RVAL_TYPE_FNCALL:
        if (FnCallIsBuiltIn(returnval))
        {
            FnCall *fp = RvalFnCallValue(returnval);
            returnval = FnCallEvaluate(ctx, policy, fp, pp).rval;
            FnCallDestroy(fp);
        }
        break;

    default:
        assert(returnval.item == NULL); /* else we're leaking it */
        returnval.item = NULL;
        returnval.type = RVAL_TYPE_NOPROMISEE;
        break;
    }

    return returnval;
}
示例#13
0
void ScopeMapBodyArgs(EvalContext *ctx, const Body *body, const Rlist *args)
{
    const Rlist *arg = NULL;
    const Rlist *param = NULL;

    for (arg = args, param = body->args; arg != NULL && param != NULL; arg = arg->next, param = param->next)
    {
        DataType arg_type = StringDataType(ctx, RlistScalarValue(arg));
        DataType param_type = StringDataType(ctx, RlistScalarValue(param));

        if (arg_type != param_type)
        {
            Log(LOG_LEVEL_ERR, "Type mismatch between logical/formal parameters %s/%s", RlistScalarValue(arg), RlistScalarValue(param));
            Log(LOG_LEVEL_ERR, "%s is %s whereas %s is %s", RlistScalarValue(arg), DataTypeToString(arg_type), RlistScalarValue(param), DataTypeToString(param_type));
        }

        switch (arg->val.type)
        {
        case RVAL_TYPE_SCALAR:
            {
                const char *lval = RlistScalarValue(param);
                VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.');
                EvalContextVariablePut(ctx, ref, RvalScalarValue(arg->val), arg_type, "source=body");
            }
            break;

        case RVAL_TYPE_LIST:
            {
                const char *lval = RlistScalarValue(param);
                VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.');
                EvalContextVariablePut(ctx, ref, RvalRlistValue(arg->val), arg_type, "source=body");
                VarRefDestroy(ref);
            }
            break;

        case RVAL_TYPE_FNCALL:
            {
                FnCall *fp = RlistFnCallValue(arg);
                arg_type = DATA_TYPE_NONE;
                {
                    const FnCallType *fncall_type = FnCallTypeGet(fp->name);
                    if (fncall_type)
                    {
                        arg_type = fncall_type->dtype;
                    }
                }

                FnCallResult res = FnCallEvaluate(ctx, fp, NULL);

                if (res.status == FNCALL_FAILURE && THIS_AGENT_TYPE != AGENT_TYPE_COMMON)
                {
                    Log(LOG_LEVEL_VERBOSE, "Embedded function argument does not resolve to a name - probably too many evaluation levels for '%s'",
                        fp->name);
                }
                else
                {
                    FnCallDestroy(fp);

                    const char *lval = RlistScalarValue(param);
                    void *rval = res.rval.item;

                    VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.');
                    EvalContextVariablePut(ctx, ref, rval, arg_type, "source=body");
                    VarRefDestroy(ref);
                }
            }

            break;

        default:
            /* Nothing else should happen */
            ProgrammingError("Software error: something not a scalar/function in argument literal");
        }
    }
}