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; }
Rlist *NewExpArgs(const FnCall *fp, const Promise *pp) { int len; Rval rval; Rlist *newargs = NULL; FnCall *subfp; const FnCallType *fn = FindFunction(fp->name); len = RlistLen(fp->args); if (!fn->varargs) { if (len != FnNumArgs(fn)) { CfOut(cf_error, "", "Arguments to function %s(.) do not tally. Expect %d not %d", fp->name, FnNumArgs(fn), len); PromiseRef(cf_error, pp); exit(1); } } for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next) { switch (rp->type) { case CF_FNCALL: subfp = (FnCall *) rp->item; rval = EvaluateFunctionCall(subfp, pp).rval; break; default: rval = ExpandPrivateRval(CONTEXTID, (Rval) {rp->item, rp->type}); break; } CfDebug("EXPARG: %s.%s\n", CONTEXTID, (char *) rval.item); AppendRlist(&newargs, rval.item, rval.rtype); DeleteRvalItem(rval); } return newargs; }
Rlist *NewExpArgs(EvalContext *ctx, const FnCall *fp, const Promise *pp) { int len; Rval rval; Rlist *newargs = NULL; FnCall *subfp; const FnCallType *fn = FnCallTypeGet(fp->name); len = RlistLen(fp->args); if (!fn->varargs) { if (len != FnNumArgs(fn)) { CfOut(OUTPUT_LEVEL_ERROR, "", "Arguments to function %s(.) do not tally. Expect %d not %d", fp->name, FnNumArgs(fn), len); PromiseRef(OUTPUT_LEVEL_ERROR, pp); exit(1); } } for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next) { switch (rp->type) { case RVAL_TYPE_FNCALL: subfp = (FnCall *) rp->item; rval = FnCallEvaluate(ctx, subfp, pp).rval; break; default: rval = ExpandPrivateRval(ScopeGetCurrent()->scope, (Rval) {rp->item, rp->type}); break; } CfDebug("EXPARG: %s.%s\n", ScopeGetCurrent()->scope, (char *) rval.item); RlistAppend(&newargs, rval.item, rval.type); RvalDestroy(rval); } return newargs; }
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; }
static void ShowBuiltinFunctions() { int i; printf("<h1>builtin functions</h1>\n"); printf("<center><table id=functionshow>\n"); printf("<tr><th>Return type</th><th>Function name</th><th>Arguments</th><th>Description</th></tr>\n"); for (i = 0; CF_FNCALL_TYPES[i].name != NULL; i++) { printf("<tr><td>%s</td><td>%s()</td><td>%d args expected</td><td>%s</td></tr>\n", CF_DATATYPES[CF_FNCALL_TYPES[i].dtype], CF_FNCALL_TYPES[i].name, FnNumArgs(&CF_FNCALL_TYPES[i]), CF_FNCALL_TYPES[i].description); } printf("</table></center>\n"); }
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; }