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; }
static int EvalClassExpression(struct Constraint *cp,struct Promise *pp) { int result_and = true; int result_or = false; int result_xor = 0; int result = 0,total = 0; char buffer[CF_MAXVARSIZE]; struct Rlist *rp; double prob,cum = 0,fluct; struct Rval newret; struct FnCall *fp; if (cp == NULL) { CfOut(cf_error,""," !! EvalClassExpression internal diagnostic discovered an ill-formed condition"); } if (!IsDefinedClass(pp->classes)) { return false; } if (pp->done) { return false; } if (IsDefinedClass(pp->promiser)) { return false; } switch (cp->type) { case CF_FNCALL: fp = (struct FnCall *)cp->rval; /* Special expansion of functions for control, best effort only */ newret = EvaluateFunctionCall(fp,pp); DeleteFnCall(fp); cp->rval = newret.item; cp->type = newret.rtype; break; case CF_LIST: for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next) { newret = EvaluateFinalRval("this",rp->item,rp->type,true,pp); DeleteRvalItem(rp->item,rp->type); rp->item = newret.item; rp->type = newret.rtype; } break; default: newret = ExpandPrivateRval("this",cp->rval,cp->type); DeleteRvalItem(cp->rval,cp->type); cp->rval = newret.item; cp->type = newret.rtype; break; } if (strcmp(cp->lval,"expression") == 0) { if (cp->type != CF_SCALAR) { return false; } if (IsDefinedClass((char *)cp->rval)) { return true; } else { return false; } } if (strcmp(cp->lval,"not") == 0) { if (cp->type != CF_SCALAR) { return false; } if (IsDefinedClass((char *)cp->rval)) { return false; } else { return true; } } // Class selection if (strcmp(cp->lval,"select_class") == 0) { char splay[CF_MAXVARSIZE]; int i,n; double hash; total = 0; for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next) { total++; } if (total == 0) { CfOut(cf_error,""," !! No classes to select on RHS"); PromiseRef(cf_error,pp); return false; } snprintf(splay,CF_MAXVARSIZE,"%s+%s+%d",VFQNAME,VIPADDRESS,getuid()); hash = (double)GetHash(splay); n = (int)(total*hash/(double)CF_HASHTABLESIZE); for (rp = (struct Rlist *)cp->rval,i = 0; rp != NULL; rp = rp->next,i++) { if (i == n) { NewClass(rp->item); return true; } } } // Class distributions if (strcmp(cp->lval,"dist") == 0) { for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next) { result = Str2Int(rp->item); if (result < 0) { CfOut(cf_error,""," !! Non-positive integer in class distribution"); PromiseRef(cf_error,pp); return false; } total += result; } if (total == 0) { CfOut(cf_error,""," !! An empty distribution was specified on RHS"); PromiseRef(cf_error,pp); return false; } } fluct = drand48(); /* Get random number 0-1 */ cum = 0.0; /* If we get here, anything remaining on the RHS must be a clist */ if (cp->type != CF_LIST) { CfOut(cf_error,""," !! RHS of promise body attribute \"%s\" is not a list\n",cp->lval); PromiseRef(cf_error,pp); return true; } for (rp = (struct Rlist *)cp->rval; rp != NULL; rp = rp->next) { if (rp->type != CF_SCALAR) { return false; } result = IsDefinedClass((char *)(rp->item)); result_and = result_and && result; result_or = result_or || result; result_xor ^= result; if (total > 0) // dist class { prob = ((double)Str2Int(rp->item))/((double)total); cum += prob; if ((fluct < cum) || rp->next == NULL) { snprintf(buffer,CF_MAXVARSIZE-1,"%s_%s",pp->promiser,rp->item); *(pp->donep) = true; if (strcmp(pp->bundletype,"common") == 0) { NewClass(buffer); } else { NewBundleClass(buffer,pp->bundle); } Debug(" ?? \'Strategy\' distribution class interval -> %s\n",buffer); return true; } } } // Class combinations if (strcmp(cp->lval,"or") == 0) { return result_or; } if (strcmp(cp->lval,"xor") == 0) { return (result_xor == 1) ? true : false; } if (strcmp(cp->lval,"and") == 0) { return result_and; } return false; }