Exemple #1
0
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);
}
Exemple #2
0
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");
    }
}
Exemple #3
0
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);
}
Exemple #4
0
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");
}
Exemple #5
0
void ScopeSetCurrent(const char *name)
{
    Scope *scope = ScopeGet(name);
    if (!scope)
    {
        scope = ScopeNew(name);
    }

    SCOPE_CURRENT = scope;
}
Exemple #6
0
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);
            }
        }
        
    }
    
}
Exemple #7
0
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);
    }
}
Exemple #8
0
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);
    }
}
Exemple #9
0
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);
    }
}
Exemple #10
0
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);
    }
}
Exemple #11
0
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);
    }
}
Exemple #12
0
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);
    }
}
Exemple #13
0
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);
    }
}
Exemple #14
0
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);
}
Exemple #15
0
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);
}
Exemple #16
0
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);
}
Exemple #17
0
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));
}
Exemple #18
0
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);
}
Exemple #19
0
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);
}
Exemple #20
0
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]);
            }
        }
    }
}
Exemple #21
0
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;
}
Exemple #22
0
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;
}
Exemple #23
0
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;
}
Exemple #24
0
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;
}
Exemple #25
0
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;
}
Exemple #26
0
bool ScopeExists(const char *name)
{
    return ScopeGet(name) != NULL;
}