FnCallResult EvaluateFunctionCall(FnCall *fp, const Promise *pp) { Rlist *expargs; const FnCallType *this = FindFunction(fp->name); if (this) { if (DEBUG) { printf("EVALUATE FN CALL %s\n", fp->name); ShowFnCall(stdout, fp); printf("\n"); } } else { if (pp) { CfOut(cf_error, "", "No such FnCall \"%s()\" in promise @ %s near line %zd\n", fp->name, pp->audit->filename, pp->offset.line); } else { CfOut(cf_error, "", "No such FnCall \"%s()\" - context info unavailable\n", fp->name); } return (FnCallResult) { FNCALL_FAILURE, { CopyFnCall(fp), CF_FNCALL } }; } /* If the container classes seem not to be defined at this stage, then don't try to expand the function */ if ((pp != NULL) && !IsDefinedClass(pp->classes)) { return (FnCallResult) { FNCALL_FAILURE, { CopyFnCall(fp), CF_FNCALL } }; } expargs = NewExpArgs(fp, pp); if (UnresolvedArgs(expargs)) { DeleteExpArgs(expargs); return (FnCallResult) { FNCALL_FAILURE, { CopyFnCall(fp), CF_FNCALL } }; } FnCallResult result = CallFunction(this, fp, expargs); if (result.status == FNCALL_FAILURE) { /* We do not assign variables to failed function calls */ DeleteExpArgs(expargs); return (FnCallResult) { FNCALL_FAILURE, { CopyFnCall(fp), CF_FNCALL } }; } DeleteExpArgs(expargs); return result; }
FnCall *NewFnCall(const char *name, Rlist *args) { FnCall *fp; CfDebug("Installing Function Call %s\n", name); fp = xmalloc(sizeof(FnCall)); fp->name = xstrdup(name); fp->args = args; CfDebug("Installed "); if (DEBUG) { ShowFnCall(stdout, fp); } CfDebug("\n\n"); return fp; }
void ShowFnCall(FILE *fout, FnCall *fp) { Rlist *rp; if (XML) { fprintf(fout, "%s(", fp->name); } else { fprintf(fout, "%s(", fp->name); } for (rp = fp->args; rp != NULL; rp = rp->next) { switch (rp->type) { case CF_SCALAR: fprintf(fout, "%s,", (char *) rp->item); break; case CF_FNCALL: ShowFnCall(fout, (FnCall *) rp->item); break; default: fprintf(fout, "(** Unknown argument **)\n"); break; } } if (XML) { fprintf(fout, ")"); } else { fprintf(fout, ")"); } }
int MapBodyArgs(const char *scopeid, Rlist *give, const Rlist *take) { Rlist *rpg = NULL; const Rlist *rpt = NULL; FnCall *fp; enum cfdatatype dtg = cf_notype, dtt = cf_notype; char *lval; void *rval; int len1, len2; CfDebug("MapBodyArgs(begin)\n"); len1 = RlistLen(give); len2 = RlistLen(take); if (len1 != len2) { CfOut(cf_error, "", " !! Argument mismatch in body template give[+args] = %d, take[-args] = %d", len1, len2); return false; } for (rpg = give, rpt = take; rpg != NULL && rpt != NULL; rpg = rpg->next, rpt = rpt->next) { dtg = StringDataType(scopeid, (char *) rpg->item); dtt = StringDataType(scopeid, (char *) rpt->item); if (dtg != dtt) { CfOut(cf_error, "", "Type mismatch between logical/formal parameters %s/%s\n", (char *) rpg->item, (char *) rpt->item); CfOut(cf_error, "", "%s is %s whereas %s is %s\n", (char *) rpg->item, CF_DATATYPES[dtg], (char *) rpt->item, CF_DATATYPES[dtt]); } switch (rpg->type) { case CF_SCALAR: lval = (char *) rpt->item; rval = rpg->item; CfDebug("MapBodyArgs(SCALAR,%s,%s)\n", lval, (char *) rval); AddVariableHash(scopeid, lval, (Rval) {rval, CF_SCALAR}, dtg, NULL, 0); break; case CF_LIST: lval = (char *) rpt->item; rval = rpg->item; AddVariableHash(scopeid, lval, (Rval) {rval, CF_LIST}, dtg, NULL, 0); break; case CF_FNCALL: fp = (FnCall *) rpg->item; dtg = FunctionReturnType(fp->name); FnCallResult res = EvaluateFunctionCall(fp, NULL); if (res.status == FNCALL_FAILURE && THIS_AGENT_TYPE != cf_common) { // Unresolved variables if (VERBOSE) { printf (" !! Embedded function argument does not resolve to a name - probably too many evaluation levels for "); ShowFnCall(stdout, fp); printf(" (try simplifying)\n"); } } else { DeleteFnCall(fp); rpg->item = res.rval.item; rpg->type = res.rval.rtype; lval = (char *) rpt->item; rval = rpg->item; AddVariableHash(scopeid, lval, (Rval) {rval, CF_SCALAR}, dtg, NULL, 0); } break; default: /* Nothing else should happen */ FatalError("Software error: something not a scalar/function in argument literal"); } } CfDebug("MapBodyArgs(end)\n"); return true; }