void ScopePushThis() { Scope *op; char name[CF_MAXVARSIZE]; op = ScopeGet("this"); if (op == NULL) { return; } int frame_index = RlistLen(CF_STCK) - 1; { Rlist *rp = xmalloc(sizeof(Rlist)); rp->next = CF_STCK; rp->item = op; rp->type = CF_STACK; CF_STCK = rp; } snprintf(name, CF_MAXVARSIZE, "this_%d", frame_index); free(op->scope); op->scope = xstrdup(name); }
void ScopePopThis() { if (RlistLen(CF_STCK) > 0) { Scope *current_this = ScopeGet(NULL, "this"); if (current_this) { ScopeDelete(current_this); } Rlist *rp = CF_STCK; CF_STCK = CF_STCK->next; Scope *new_this = rp->item; free(new_this->scope); new_this->scope = xstrdup("this"); new_this->ns = xstrdup("default"); free(rp); } else { ProgrammingError("Attempt to pop from empty stack"); } }
void ScopeClear(const char *ns, const char *name) { assert(name); assert(!ScopeIsReserved(name)); if (!ns) { ns = "default"; } if (!ThreadLock(cft_vscope)) { Log(LOG_LEVEL_ERR, "Could not lock VSCOPE"); return; } Scope *scope = ScopeGet(ns, name); if (!scope) { Log(LOG_LEVEL_DEBUG, "No scope '%s' to clear", name); ThreadUnlock(cft_vscope); return; } HashFree(scope->hashtable); scope->hashtable = HashInit(); Log(LOG_LEVEL_DEBUG, "Scope '%s' cleared", name); ThreadUnlock(cft_vscope); }
void ScopePushThis() { static const char RVAL_TYPE_STACK = 'k'; Scope *op = ScopeGet(NULL, "this"); if (!op) { return; } int frame_index = RlistLen(CF_STCK); char name[CF_MAXVARSIZE]; snprintf(name, CF_MAXVARSIZE, "this_%d", frame_index + 1); free(op->scope); free(op->ns); op->scope = xstrdup(name); Rlist *rp = xmalloc(sizeof(Rlist)); rp->next = CF_STCK; rp->item = op; rp->type = RVAL_TYPE_STACK; CF_STCK = rp; ScopeNew(NULL, "this"); }
void ScopeSetCurrent(const char *name) { Scope *scope = ScopeGet(name); if (!scope) { scope = ScopeNew(name); } SCOPE_CURRENT = scope; }
static void GetReturnValue(EvalContext *ctx, char *scope, Promise *pp) { char *result = ConstraintGetRvalValue(ctx, "useresult", pp, RVAL_TYPE_SCALAR); if (result) { AssocHashTableIterator i; CfAssoc *assoc; char newname[CF_BUFSIZE]; Scope *ptr; char index[CF_MAXVARSIZE], match[CF_MAXVARSIZE]; if ((ptr = ScopeGet(scope)) == NULL) { Log(LOG_LEVEL_INFO, "useresult was specified but the method returned no data"); return; } i = HashIteratorInit(ptr->hashtable); while ((assoc = HashIteratorNext(&i))) { snprintf(match, CF_MAXVARSIZE - 1, "last-result["); if (strncmp(match, assoc->lval, strlen(match)) == 0) { char *sp; index[0] = '\0'; sscanf(assoc->lval + strlen(match), "%127[^\n]", index); if ((sp = strchr(index, ']'))) { *sp = '\0'; } else { index[strlen(index) - 1] = '\0'; } if (strlen(index) > 0) { snprintf(newname, CF_BUFSIZE, "%s[%s]", result, index); } else { snprintf(newname, CF_BUFSIZE, "%s", result); } EvalContextVariablePut(ctx, (VarRef) { NULL, PromiseGetBundle(pp)->name, newname }, assoc->rval, DATA_TYPE_STRING); } } } }
void ScopeDeleteVariable(const char *ns, const char *scope, const char *id) { Scope *ptr = ScopeGet(ns, scope); if (ptr == NULL) { return; } if (HashDeleteElement(ptr->hashtable, id) == false) { Log(LOG_LEVEL_DEBUG, "No variable matched '%s' for removal", id); } }
void ScopeDeleteVariable(const char *scope, const char *id) { Scope *ptr = ScopeGet(scope); if (ptr == NULL) { return; } if (HashDeleteElement(ptr->hashtable, id) == false) { CfDebug("No variable matched %s\n", id); } }
void ScopeDeleteScalar(const VarRef *ref) { assert(!ScopeIsReserved(ref->scope)); Scope *scope = ScopeGet(ref->ns, ref->scope); if (scope == NULL) { return; } if (HashDeleteElement(scope->hashtable, ref->lval) == false) { Log(LOG_LEVEL_DEBUG, "Attempt to delete non-existent variable '%s' in scope '%s'", ref->lval, ref->scope); } }
void ScopeDeleteSpecialScalar(const char *scope, const char *lval) { assert(ScopeIsReserved(scope)); Scope *scope_ptr = ScopeGet(scope); if (scope_ptr == NULL) { return; } if (HashDeleteElement(scope_ptr->hashtable, lval) == false) { CfDebug("Attempt to delete non-existent variable %s in scope %s\n", lval, scope); } }
void ScopeDeleteSpecial(const char *scope, const char *lval) { assert(ScopeIsReserved(scope)); Scope *scope_ptr = ScopeGet(scope); if (scope_ptr == NULL) { return; } if (HashDeleteElement(scope_ptr->hashtable, lval) == false) { Log(LOG_LEVEL_DEBUG, "Attempt to delete non-existent variable '%s' in scope '%s'", lval, scope); } }
void ScopeDeleteScalar(VarRef lval) { assert(!ScopeIsReserved(lval.scope)); if (ScopeIsReserved(lval.scope)) { ScopeDeleteSpecialScalar(lval.scope, lval.lval); } Scope *scope = ScopeGet(lval.scope); if (scope == NULL) { return; } if (HashDeleteElement(scope->hashtable, lval.lval) == false) { CfDebug("Attempt to delete non-existent variable %s in scope %s\n", lval.lval, lval.scope); } }
void ScopeDeleteScalar(VarRef lval) { assert(!ScopeIsReserved(lval.scope)); if (ScopeIsReserved(lval.scope)) { ScopeDeleteSpecial(lval.scope, lval.lval); } Scope *scope = ScopeGet(lval.scope); if (scope == NULL) { return; } if (HashDeleteElement(scope->hashtable, lval.lval) == false) { Log(LOG_LEVEL_DEBUG, "Attempt to delete non-existent variable '%s' in scope '%s'", lval.lval, lval.scope); } }
void ScopeCopy(const char *new_ns, const char *new_scopename, const Scope *old_scope) /* * Thread safe */ { ScopeNew(new_ns, new_scopename); if (!ThreadLock(cft_vscope)) { Log(LOG_LEVEL_ERR, "Could not lock VSCOPE"); return; } if (old_scope) { Scope *np = ScopeGet(new_ns, new_scopename); HashCopy(np->hashtable, old_scope->hashtable); } ThreadUnlock(cft_vscope); }
void ScopeClear(const char *name) { if (!ThreadLock(cft_vscope)) { Log(LOG_LEVEL_ERR, "Could not lock VSCOPE"); return; } Scope *scope = ScopeGet(name); if (!scope) { Log(LOG_LEVEL_DEBUG, "No such scope to clear"); ThreadUnlock(cft_vscope); return; } HashFree(scope->hashtable); scope->hashtable = HashInit(); ThreadUnlock(cft_vscope); }
void ScopeClearSpecial(SpecialScope scope) { if (!ThreadLock(cft_vscope)) { Log(LOG_LEVEL_ERR, "Could not lock VSCOPE"); return; } Scope *ptr = ScopeGet(NULL, SpecialScopeToString(scope)); if (!ptr) { Log(LOG_LEVEL_DEBUG, "No special scope '%s' to clear", SpecialScopeToString(scope)); ThreadUnlock(cft_vscope); return; } HashFree(ptr->hashtable); ptr->hashtable = HashInit(); Log(LOG_LEVEL_DEBUG, "Special scope '%s' cleared", SpecialScopeToString(scope)); ThreadUnlock(cft_vscope); }
void ScopeDeleteSpecial(SpecialScope scope, const char *lval) { Scope *scope_ptr = ScopeGet(NULL, SpecialScopeToString(scope)); if (scope_ptr == NULL) { Log(LOG_LEVEL_WARNING, "Attempt to delete variable '%s' in non-existent scope '%s'", lval, SpecialScopeToString(scope)); return; } if (HashDeleteElement(scope_ptr->hashtable, lval) == false) { Log(LOG_LEVEL_WARNING, "Attempt to delete non-existent variable '%s' in scope '%s'", lval, SpecialScopeToString(scope)); return; } Log(LOG_LEVEL_DEBUG, "Deleted existent variable '%s' in scope '%s'", lval, SpecialScopeToString(scope)); }
void ScopeCopy(const char *new_scopename, const Scope *old_scope) /* * Thread safe */ { CfDebug("\n*\nCopying scope data %s to %s\n*\n", old_scope->scope, new_scopename); ScopeNew(new_scopename); if (!ThreadLock(cft_vscope)) { CfOut(OUTPUT_LEVEL_ERROR, "", "!! Could not lock VSCOPE"); return; } if (old_scope) { Scope *np = ScopeGet(new_scopename); HashCopy(np->hashtable, old_scope->hashtable); } ThreadUnlock(cft_vscope); }
void ScopeClear(const char *name) { CfDebug("Clearing scope %s\n", name); if (!ThreadLock(cft_vscope)) { CfOut(OUTPUT_LEVEL_ERROR, "", "!! Could not lock VSCOPE"); return; } Scope *scope = ScopeGet(name); if (!scope) { CfDebug("No such scope to clear\n"); ThreadUnlock(cft_vscope); return; } HashFree(scope->hashtable); scope->hashtable = HashInit(); ThreadUnlock(cft_vscope); }
void ScopeDeRefListsInHashtable(char *scope, Rlist *namelist, Rlist *dereflist) // Go through scope and for each variable in name-list, replace with a // value from the deref "lol" (list of lists) clock { int len; Scope *ptr; Rlist *rp; CfAssoc *cplist; AssocHashTableIterator i; CfAssoc *assoc; if ((len = RlistLen(namelist)) != RlistLen(dereflist)) { CfOut(OUTPUT_LEVEL_ERROR, "", " !! Name list %d, dereflist %d\n", len, RlistLen(dereflist)); ProgrammingError("Software Error DeRefLists... correlated lists not same length"); } if (len == 0) { return; } ptr = ScopeGet(scope); i = HashIteratorInit(ptr->hashtable); while ((assoc = HashIteratorNext(&i))) { for (rp = dereflist; rp != NULL; rp = rp->next) { cplist = (CfAssoc *) rp->item; if (strcmp(cplist->lval, assoc->lval) == 0) { /* Link up temp hash to variable lol */ if (rp->state_ptr == NULL || rp->state_ptr->type == RVAL_TYPE_FNCALL) { /* Unexpanded function, or blank variable must be skipped. */ return; } if (rp->state_ptr) { CfDebug("Rewriting expanded type for %s from %s to %s\n", assoc->lval, CF_DATATYPES[assoc->dtype], (char *) rp->state_ptr->item); // must first free existing rval in scope, then allocate new (should always be string) RvalDestroy(assoc->rval); // avoids double free - borrowing value from lol (freed in DeleteScope()) assoc->rval.item = xstrdup(rp->state_ptr->item); } switch (assoc->dtype) { case DATA_TYPE_STRING_LIST: assoc->dtype = DATA_TYPE_STRING; assoc->rval.type = RVAL_TYPE_SCALAR; break; case DATA_TYPE_INT_LIST: assoc->dtype = DATA_TYPE_INT; assoc->rval.type = RVAL_TYPE_SCALAR; break; case DATA_TYPE_REAL_LIST: assoc->dtype = DATA_TYPE_REAL; assoc->rval.type = RVAL_TYPE_SCALAR; break; default: /* Only lists need to be converted */ break; } CfDebug(" to %s\n", CF_DATATYPES[assoc->dtype]); } } } }
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; }
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; }
void ScopeAugment(EvalContext *ctx, const Bundle *bp, const Promise *pp, const Rlist *arguments) { if (RlistLen(bp->args) != RlistLen(arguments)) { Log(LOG_LEVEL_ERR, "While constructing scope '%s'", bp->name); fprintf(stderr, "Formal = "); RlistShow(stderr, bp->args); fprintf(stderr, ", Actual = "); RlistShow(stderr, arguments); fprintf(stderr, "\n"); FatalError(ctx, "Augment scope, formal and actual parameter mismatch is fatal"); } const Bundle *pbp = NULL; if (pp != NULL) { pbp = PromiseGetBundle(pp); } for (const Rlist *rpl = bp->args, *rpr = arguments; rpl != NULL; rpl = rpl->next, rpr = rpr->next) { const char *lval = rpl->item; Log(LOG_LEVEL_VERBOSE, "Augment scope '%s' with variable '%s' (type: %c)", bp->name, lval, rpr->type); // CheckBundleParameters() already checked that there is no namespace collision // By this stage all functions should have been expanded, so we only have scalars left if (IsNakedVar(rpr->item, '@')) { DataType vtype; char naked[CF_BUFSIZE]; GetNaked(naked, rpr->item); Rval retval; if (pbp != NULL) { EvalContextVariableGet(ctx, (VarRef) { pbp->ns, pbp->name, naked }, &retval, &vtype); } else { EvalContextVariableGet(ctx, (VarRef) { NULL, bp->name, naked }, &retval, &vtype); } switch (vtype) { case DATA_TYPE_STRING_LIST: case DATA_TYPE_INT_LIST: case DATA_TYPE_REAL_LIST: EvalContextVariablePut(ctx, (VarRef) { NULL, bp->name, lval }, (Rval) { retval.item, RVAL_TYPE_LIST}, DATA_TYPE_STRING_LIST); break; default: Log(LOG_LEVEL_ERR, "List parameter '%s' not found while constructing scope '%s' - use @(scope.variable) in calling reference", naked, bp->name); EvalContextVariablePut(ctx, (VarRef) { NULL, bp->name, lval }, (Rval) { rpr->item, RVAL_TYPE_SCALAR }, DATA_TYPE_STRING); break; } } else { switch(rpr->type) { case RVAL_TYPE_SCALAR: EvalContextVariablePut(ctx, (VarRef) { NULL, bp->name, lval }, (Rval) { rpr->item, RVAL_TYPE_SCALAR }, DATA_TYPE_STRING); break; case RVAL_TYPE_FNCALL: { FnCall *subfp = rpr->item; Rval rval = FnCallEvaluate(ctx, subfp, pp).rval; if (rval.type == RVAL_TYPE_SCALAR) { EvalContextVariablePut(ctx, (VarRef) { NULL, bp->name, lval }, (Rval) { rval.item, RVAL_TYPE_SCALAR }, DATA_TYPE_STRING); } else { Log(LOG_LEVEL_ERR, "Only functions returning scalars can be used as arguments"); } } break; default: ProgrammingError("An argument neither a scalar nor a list seemed to appear. Impossible"); } } } /* Check that there are no danglers left to evaluate in the hash table itself */ { Scope *ptr = ScopeGet(bp->name); AssocHashTableIterator i = HashIteratorInit(ptr->hashtable); CfAssoc *assoc = NULL; while ((assoc = HashIteratorNext(&i))) { Rval retval = ExpandPrivateRval(ctx, bp->name, assoc->rval); // Retain the assoc, just replace rval RvalDestroy(assoc->rval); assoc->rval = retval; } } return; }
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; }
void ScopeAugment(EvalContext *ctx, const Bundle *bp, const Rlist *arguments) { if (RlistLen(bp->args) != RlistLen(arguments)) { CfOut(OUTPUT_LEVEL_ERROR, "", "While constructing scope \"%s\"\n", bp->name); fprintf(stderr, "Formal = "); RlistShow(stderr, bp->args); fprintf(stderr, ", Actual = "); RlistShow(stderr, arguments); fprintf(stderr, "\n"); FatalError(ctx, "Augment scope, formal and actual parameter mismatch is fatal"); } for (const Rlist *rpl = bp->args, *rpr = arguments; rpl != NULL; rpl = rpl->next, rpr = rpr->next) { const char *lval = rpl->item; CfOut(OUTPUT_LEVEL_VERBOSE, "", " ? Augment scope %s with %s (%c)\n", bp->name, lval, rpr->type); // CheckBundleParameters() already checked that there is no namespace collision // By this stage all functions should have been expanded, so we only have scalars left if (IsNakedVar(rpr->item, '@')) { DataType vtype; char qnaked[CF_MAXVARSIZE]; char naked[CF_BUFSIZE]; GetNaked(naked, rpr->item); if (IsQualifiedVariable(naked) && strchr(naked, CF_NS) == NULL) { snprintf(qnaked, CF_MAXVARSIZE, "%s%c%s", bp->ns, CF_NS, naked); } Rval retval; EvalContextVariableGet(ctx, (VarRef) { NULL, bp->name, qnaked }, &retval, &vtype); switch (vtype) { case DATA_TYPE_STRING_LIST: case DATA_TYPE_INT_LIST: case DATA_TYPE_REAL_LIST: ScopeNewList(ctx, (VarRef) { NULL, bp->name, lval }, RvalCopy((Rval) { retval.item, RVAL_TYPE_LIST}).item, DATA_TYPE_STRING_LIST); break; default: CfOut(OUTPUT_LEVEL_ERROR, "", " !! List parameter \"%s\" not found while constructing scope \"%s\" - use @(scope.variable) in calling reference", qnaked, bp->name); ScopeNewScalar(ctx, (VarRef) { NULL, bp->name, lval }, rpr->item, DATA_TYPE_STRING); break; } } else { switch(rpr->type) { case RVAL_TYPE_SCALAR: ScopeNewScalar(ctx, (VarRef) { NULL, bp->name, lval }, rpr->item, DATA_TYPE_STRING); break; case RVAL_TYPE_FNCALL: { FnCall *subfp = rpr->item; Promise *pp = NULL; // This argument should really get passed down. Rval rval = FnCallEvaluate(ctx, subfp, pp).rval; if (rval.type == RVAL_TYPE_SCALAR) { ScopeNewScalar(ctx, (VarRef) { NULL, bp->name, lval }, rval.item, DATA_TYPE_STRING); } else { CfOut(OUTPUT_LEVEL_ERROR, "", "Only functions returning scalars can be used as arguments"); } } break; default: ProgrammingError("An argument neither a scalar nor a list seemed to appear. Impossible"); } } } /* Check that there are no danglers left to evaluate in the hash table itself */ { Scope *ptr = ScopeGet(bp->name); AssocHashTableIterator i = HashIteratorInit(ptr->hashtable); CfAssoc *assoc = NULL; while ((assoc = HashIteratorNext(&i))) { Rval retval = ExpandPrivateRval(ctx, bp->name, assoc->rval); // Retain the assoc, just replace rval RvalDestroy(assoc->rval); assoc->rval = retval; } } return; }
bool ScopeExists(const char *name) { return ScopeGet(name) != NULL; }