void ScopePutMatch(int index, const char *value) { if (!SCOPE_MATCH) { SCOPE_MATCH = ScopeNew("match"); } Scope *ptr = SCOPE_MATCH; char lval[4] = { 0 }; snprintf(lval, 3, "%d", index); Rval rval = (Rval) { value, RVAL_TYPE_SCALAR }; CfAssoc *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_TYPE_SCALAR)) { CfOut(OUTPUT_LEVEL_INFORM, "", " !! Duplicate selection of value for variable \"%s\" in scope %s", lval, ptr->scope); } RvalDestroy(assoc->rval); assoc->rval = RvalCopy(rval); assoc->dtype = DATA_TYPE_STRING; CfDebug("Stored \"%s\" in context %s\n", lval, "match"); } } else { if (!HashInsertElement(ptr->hashtable, lval, rval, DATA_TYPE_STRING)) { ProgrammingError("Hash table is full"); } } }
bool EvalContextVariablePut(EvalContext *ctx, VarRef lval, Rval rval, DataType type) { Scope *ptr; const Rlist *rp; CfAssoc *assoc; if (rval.type == RVAL_TYPE_SCALAR) { CfDebug("AddVariableHash(%s.%s=%s (%s) rtype=%c)\n", lval.scope, lval.lval, (const char *) rval.item, CF_DATATYPES[type], rval.type); } else { CfDebug("AddVariableHash(%s.%s=(list) (%s) rtype=%c)\n", lval.scope, lval.lval, CF_DATATYPES[type], rval.type); } if (lval.lval == NULL || lval.scope == NULL) { CfOut(OUTPUT_LEVEL_ERROR, "", "scope.value = %s.%s", lval.scope, lval.lval); ProgrammingError("Bad variable or scope in a variable assignment, 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.lval) > CF_MAXVARSIZE) { char *lval_str = VarRefToString(lval); CfOut(OUTPUT_LEVEL_ERROR, "", "Variable %s cannot be added because its length exceeds the maximum length allowed: %d", lval_str, CF_MAXVARSIZE); free(lval_str); return false; } /* If we are not expanding a body template, check for recursive singularities */ if (strcmp(lval.scope, "body") != 0) { switch (rval.type) { case RVAL_TYPE_SCALAR: if (StringContainsVar((char *) rval.item, lval.lval)) { CfOut(OUTPUT_LEVEL_ERROR, "", "Scalar variable %s.%s contains itself (non-convergent): %s", lval.scope, lval.lval, (char *) rval.item); return false; } break; case RVAL_TYPE_LIST: for (rp = rval.item; rp != NULL; rp = rp->next) { if (StringContainsVar((char *) rp->item, lval.lval)) { CfOut(OUTPUT_LEVEL_ERROR, "", "List variable %s contains itself (non-convergent)", lval.lval); return false; } } break; default: break; } } ptr = ScopeGet(lval.scope); if (!ptr) { ptr = ScopeNew(lval.scope); if (!ptr) { return false; } } // Look for outstanding lists in variable rvals if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON) { Rlist *listvars = NULL; if (ScopeGetCurrent() && strcmp(ScopeGetCurrent()->scope, "this") != 0) { MapIteratorsFromRval(ScopeGetCurrent()->scope, &listvars, rval); if (listvars != NULL) { CfOut(OUTPUT_LEVEL_ERROR, "", " !! Redefinition of variable \"%s\" (embedded list in RHS) in context \"%s\"", lval.lval, ScopeGetCurrent()->scope); } RlistDestroy(listvars); } } assoc = HashLookupElement(ptr->hashtable, lval.lval); if (assoc) { if (CompareVariableValue(rval, assoc) == 0) { /* Identical value, keep as is */ } else { /* Different value, bark and replace */ if (!UnresolvedVariables(assoc, rval.type)) { CfOut(OUTPUT_LEVEL_INFORM, "", " !! Duplicate selection of value for variable \"%s\" in scope %s", lval.lval, ptr->scope); } RvalDestroy(assoc->rval); assoc->rval = RvalCopy(rval); assoc->dtype = type; CfDebug("Stored \"%s\" in context %s\n", lval.lval, lval.scope); } } else { if (!HashInsertElement(ptr->hashtable, lval.lval, rval, type)) { ProgrammingError("Hash table is full"); } } CfDebug("Added Variable %s in scope %s with value (omitted)\n", lval.lval, lval.scope); return true; }
bool EvalContextVariableGet(const EvalContext *ctx, VarRef lval, Rval *rval_out, DataType *type_out) { if (lval.lval == NULL) { if (rval_out) { *rval_out = (Rval) {NULL, RVAL_TYPE_SCALAR }; } if (type_out) { *type_out = DATA_TYPE_NONE; } return false; } char expanded_lval[CF_MAXVARSIZE] = ""; if (!IsExpandable(lval.lval)) { strncpy(expanded_lval, lval.lval, CF_MAXVARSIZE - 1); } else { char buffer[CF_EXPANDSIZE] = ""; if (ExpandScalar(ctx, lval.scope, lval.lval, buffer)) { strncpy(expanded_lval, buffer, CF_MAXVARSIZE - 1); } else { if (rval_out) { *rval_out = (Rval) {(char *) lval.lval, RVAL_TYPE_SCALAR }; } if (type_out) { *type_out = DATA_TYPE_NONE; } return false; } } Scope *get_scope = NULL; char lookup_key[CF_MAXVARSIZE] = ""; { char scopeid[CF_MAXVARSIZE] = ""; if (IsQualifiedVariable(expanded_lval)) { scopeid[0] = '\0'; sscanf(expanded_lval, "%[^.].", scopeid); strlcpy(lookup_key, expanded_lval + strlen(scopeid) + 1, sizeof(lookup_key)); } else { strlcpy(lookup_key, expanded_lval, sizeof(lookup_key)); strlcpy(scopeid, lval.scope, sizeof(scopeid)); } if (lval.ns != NULL && strchr(scopeid, CF_NS) == NULL && strcmp(lval.ns, "default") != 0) { char buffer[CF_EXPANDSIZE] = ""; sprintf(buffer, "%s%c%s", lval.ns, CF_NS, scopeid); strlcpy(scopeid, buffer, sizeof(scopeid)); } get_scope = ScopeGet(scopeid); } if (!get_scope) { if (rval_out) { *rval_out = (Rval) {(char *) lval.lval, RVAL_TYPE_SCALAR }; } if (type_out) { *type_out = DATA_TYPE_NONE; } return false; } CfAssoc *assoc = HashLookupElement(get_scope->hashtable, lookup_key); if (!assoc) { if (rval_out) { *rval_out = (Rval) {(char *) lval.lval, RVAL_TYPE_SCALAR }; } if (type_out) { *type_out = DATA_TYPE_NONE; } return false; } if (rval_out) { *rval_out = assoc->rval; } if (type_out) { *type_out = assoc->dtype; assert(*type_out != DATA_TYPE_NONE); } return true; }
bool EvalContextVariablePut(EvalContext *ctx, VarRef lval, Rval rval, DataType type) { assert(type != DATA_TYPE_NONE); if (lval.lval == NULL || lval.scope == NULL) { ProgrammingError("Bad variable or scope in a variable assignment. scope.value = %s.%s", lval.scope, lval.lval); } if (rval.item == NULL) { return false; } if (strlen(lval.lval) > CF_MAXVARSIZE) { char *lval_str = VarRefToString(lval, true); Log(LOG_LEVEL_ERR, "Variable '%s'' cannot be added because its length exceeds the maximum length allowed '%d' characters", lval_str, CF_MAXVARSIZE); free(lval_str); return false; } // If we are not expanding a body template, check for recursive singularities if (strcmp(lval.scope, "body") != 0) { switch (rval.type) { case RVAL_TYPE_SCALAR: if (StringContainsVar((char *) rval.item, lval.lval)) { Log(LOG_LEVEL_ERR, "Scalar variable '%s.%s' contains itself (non-convergent), value '%s'", lval.scope, lval.lval, (char *) rval.item); return false; } break; case RVAL_TYPE_LIST: for (const Rlist *rp = rval.item; rp != NULL; rp = rp->next) { if (StringContainsVar(rp->item, lval.lval)) { Log(LOG_LEVEL_ERR, "List variable '%s' contains itself (non-convergent)", lval.lval); return false; } } break; default: break; } } else { assert(STACK_FRAME_TYPE_BODY == LastStackFrame(ctx, 0)->type); } Scope *put_scope = ScopeGet(lval.scope); if (!put_scope) { put_scope = ScopeNew(lval.scope); if (!put_scope) { return false; } } // Look for outstanding lists in variable rvals if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON) { Rlist *listvars = NULL; Rlist *scalars = NULL; // TODO what do we do with scalars? if (ScopeGetCurrent() && strcmp(ScopeGetCurrent()->scope, "this") != 0) { MapIteratorsFromRval(ctx, ScopeGetCurrent()->scope, &listvars, &scalars, rval); if (listvars != NULL) { Log(LOG_LEVEL_ERR, "Redefinition of variable '%s' (embedded list in RHS) in context '%s'", lval.lval, ScopeGetCurrent()->scope); } RlistDestroy(listvars); RlistDestroy(scalars); } } // FIX: lval is stored with array params as part of the lval for legacy reasons. char *final_lval = VarRefToString(lval, false); CfAssoc *assoc = HashLookupElement(put_scope->hashtable, final_lval); if (assoc) { if (CompareVariableValue(rval, assoc) != 0) { /* Different value, bark and replace */ if (!UnresolvedVariables(assoc, rval.type)) { Log(LOG_LEVEL_INFO, "Replaced value of variable '%s' in scope '%s'", lval.lval, put_scope->scope); } RvalDestroy(assoc->rval); assoc->rval = RvalCopy(rval); assoc->dtype = type; } } else { if (!HashInsertElement(put_scope->hashtable, final_lval, rval, type)) { ProgrammingError("Hash table is full"); } } free(final_lval); return true; }
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; }
enum cfdatatype GetVariable(const char *scope, const char *lval, Rval *returnv) { Scope *ptr = NULL; char scopeid[CF_MAXVARSIZE], vlval[CF_MAXVARSIZE], sval[CF_MAXVARSIZE]; char expbuf[CF_EXPANDSIZE]; CfAssoc *assoc; CfDebug("\nGetVariable(%s,%s) type=(to be determined)\n", scope, lval); if (lval == NULL) { *returnv = (Rval) {NULL, CF_SCALAR}; return cf_notype; } if (!IsExpandable(lval)) { strncpy(sval, lval, CF_MAXVARSIZE - 1); } else { if (ExpandScalar(lval, expbuf)) { strncpy(sval, expbuf, CF_MAXVARSIZE - 1); } else { /* C type system does not allow us to express the fact that returned value may contain immutable string. */ *returnv = (Rval) {(char *) lval, CF_SCALAR}; CfDebug("Couldn't expand array-like variable (%s) due to undefined dependencies\n", lval); return cf_notype; } } if (IsQualifiedVariable(sval)) { scopeid[0] = '\0'; sscanf(sval, "%[^.].%s", scopeid, vlval); CfDebug("Variable identifier %s is prefixed with scope id %s\n", vlval, scopeid); ptr = GetScope(scopeid); } else { strlcpy(vlval, sval, sizeof(vlval)); strlcpy(scopeid, scope, sizeof(scopeid)); } CfDebug("Looking for %s.%s\n", scopeid, vlval); if (ptr == NULL) { /* Assume current scope */ strcpy(vlval, lval); ptr = GetScope(scopeid); } if (ptr == NULL) { CfDebug("Scope for variable \"%s.%s\" does not seem to exist\n", scope, lval); /* C type system does not allow us to express the fact that returned value may contain immutable string. */ *returnv = (Rval) {(char *) lval, CF_SCALAR}; return cf_notype; } CfDebug("GetVariable(%s,%s): using scope '%s' for variable '%s'\n", scopeid, vlval, ptr->scope, vlval); assoc = HashLookupElement(ptr->hashtable, vlval); if (assoc == NULL) { CfDebug("No such variable found %s.%s\n\n", scopeid, lval); /* C type system does not allow us to express the fact that returned value may contain immutable string. */ *returnv = (Rval) {(char *) lval, CF_SCALAR}; return cf_notype; } CfDebug("return final variable type=%s, value={\n", CF_DATATYPES[assoc->dtype]); if (DEBUG) { ShowRval(stdout, assoc->rval); } CfDebug("}\n"); *returnv = assoc->rval; return assoc->dtype; }