CfAssoc *NewAssoc(const char *lval, Rval rval, enum cfdatatype dt) { CfAssoc *ap; ap = xmalloc(sizeof(CfAssoc)); /* Make a private copy because promises are ephemeral in expansion phase */ ap->lval = xstrdup(lval); ap->rval = CopyRvalItem(rval); ap->dtype = dt; return ap; }
int AddVariableHash(const char *scope, const char *lval, Rval rval, enum cfdatatype dtype, const char *fname, int lineno) { Scope *ptr; const Rlist *rp; CfAssoc *assoc; if (rval.rtype == CF_SCALAR) { CfDebug("AddVariableHash(%s.%s=%s (%s) rtype=%c)\n", scope, lval, (const char *) rval.item, CF_DATATYPES[dtype], rval.rtype); } else { CfDebug("AddVariableHash(%s.%s=(list) (%s) rtype=%c)\n", scope, lval, CF_DATATYPES[dtype], rval.rtype); } if (lval == NULL || scope == NULL) { CfOut(cf_error, "", "scope.value = %s.%s", scope, lval); ReportError("Bad variable or scope in a variable assignment"); FatalError("Should not happen - forgotten to register a function call in fncall.c?"); } if (rval.item == NULL) { CfDebug("No value to assignment - probably a parameter in an unused bundle/body\n"); return false; } if (strlen(lval) > CF_MAXVARSIZE) { ReportError("variable lval too long"); return false; } /* If we are not expanding a body template, check for recursive singularities */ if (strcmp(scope, "body") != 0) { switch (rval.rtype) { case CF_SCALAR: if (StringContainsVar((char *) rval.item, lval)) { CfOut(cf_error, "", "Scalar variable %s.%s contains itself (non-convergent): %s", scope, lval, (char *) rval.item); return false; } break; case CF_LIST: for (rp = rval.item; rp != NULL; rp = rp->next) { if (StringContainsVar((char *) rp->item, lval)) { CfOut(cf_error, "", "List variable %s contains itself (non-convergent)", lval); return false; } } break; } } ptr = GetScope(scope); if (ptr == NULL) { return false; } // Look for outstanding lists in variable rvals if (THIS_AGENT_TYPE == cf_common) { Rlist *listvars = NULL, *scalarvars = NULL; if (strcmp(CONTEXTID, "this") != 0) { MapIteratorsFromRval(CONTEXTID, &scalarvars, &listvars, rval, NULL); if (listvars != NULL) { CfOut(cf_error, "", " !! Redefinition of variable \"%s\" (embedded list in RHS) in context \"%s\"", lval, CONTEXTID); } DeleteRlist(scalarvars); DeleteRlist(listvars); } } assoc = HashLookupElement(ptr->hashtable, lval); if (assoc) { if (CompareVariableValue(rval, assoc) == 0) { /* Identical value, keep as is */ } else { /* Different value, bark and replace */ if (!UnresolvedVariables(assoc, rval.rtype)) { CfOut(cf_inform, "", " !! Duplicate selection of value for variable \"%s\" in scope %s", lval, ptr->scope); if (fname) { CfOut(cf_inform, "", " !! Rule from %s at/before line %d\n", fname, lineno); } else { CfOut(cf_inform, "", " !! in bundle parameterization\n"); } } DeleteRvalItem(assoc->rval); assoc->rval = CopyRvalItem(rval); assoc->dtype = dtype; CfDebug("Stored \"%s\" in context %s\n", lval, scope); } } else { if (!HashInsertElement(ptr->hashtable, lval, rval, dtype)) { FatalError("Hash table is full"); } } CfDebug("Added Variable %s in scope %s with value (omitted)\n", lval, scope); return true; }