Ejemplo n.º 1
0
static Rval ExpandListEntry(EvalContext *ctx,
                            const char *ns, const char *scope,
                            int expandnaked, Rval entry)
{
    if (entry.type == RVAL_TYPE_SCALAR &&
        IsNakedVar(entry.item, '@'))
    {
        if (expandnaked)
        {
            char naked[CF_MAXVARSIZE];
            GetNaked(naked, entry.item);

            if (!IsExpandable(naked))
            {
                VarRef *ref = VarRefParseFromScope(naked, scope);

                DataType value_type = CF_DATA_TYPE_NONE;
                const void *value = EvalContextVariableGet(ctx, ref, &value_type);
                VarRefDestroy(ref);

                if (value)
                {
                    return ExpandPrivateRval(ctx, ns, scope, value,
                                             DataTypeToRvalType(value_type));
                }
            }
        }
        else
        {
            return RvalNew(entry.item, RVAL_TYPE_SCALAR);
        }
    }

    return ExpandPrivateRval(ctx, ns, scope, entry.item, entry.type);
}
Ejemplo n.º 2
0
Archivo: expand.c Proyecto: tzz/core
Rlist *ExpandList(EvalContext *ctx, const char *ns, const char *scope, const Rlist *list, int expandnaked)
{
    Rlist *start = NULL;
    Rval returnval;

    for (const Rlist *rp = list; rp != NULL; rp = rp->next)
    {
        if (!expandnaked && (rp->val.type == RVAL_TYPE_SCALAR) && IsNakedVar(RlistScalarValue(rp), '@'))
        {
            returnval = RvalNew(RlistScalarValue(rp), RVAL_TYPE_SCALAR);
        }
        else if ((rp->val.type == RVAL_TYPE_SCALAR) && IsNakedVar(RlistScalarValue(rp), '@'))
        {
            char naked[CF_MAXVARSIZE];
            GetNaked(naked, RlistScalarValue(rp));

            if (!IsExpandable(naked))
            {
                VarRef *ref = VarRefParseFromScope(naked, scope);

                DataType value_type = DATA_TYPE_NONE;
                const void *value = EvalContextVariableGet(ctx, ref, &value_type);
                if (value)
                {
                    returnval = ExpandPrivateRval(ctx, ns, scope, value, DataTypeToRvalType(value_type));
                }
                else
                {
                    returnval = ExpandPrivateRval(ctx, ns, scope, rp->val.item, rp->val.type);
                }

                VarRefDestroy(ref);
            }
            else
            {
                returnval = ExpandPrivateRval(ctx, ns, scope, rp->val.item, rp->val.type);
            }
        }
        else
        {
            returnval = ExpandPrivateRval(ctx, ns, scope, rp->val.item, rp->val.type);
        }

        RlistAppend(&start, returnval.item, returnval.type);
        RvalDestroy(returnval);
    }

    return start;
}
Ejemplo n.º 3
0
Archivo: rlist.c Proyecto: cduclos/core
void RlistFlatten(EvalContext *ctx, Rlist **list)
{
    for (Rlist *rp = *list; rp != NULL;)
    {
        if (rp->val.type != RVAL_TYPE_SCALAR)
        {
            rp = rp->next;
            continue;
        }

        char naked[CF_BUFSIZE] = "";
        if (IsNakedVar(RlistScalarValue(rp), '@'))
        {
            GetNaked(naked, RlistScalarValue(rp));

            if (!IsExpandable(naked))
            {
                Rval rv;
                VarRef *ref = VarRefParse(naked);

                bool var_found = EvalContextVariableGet(ctx, ref, &rv, NULL);

                VarRefDestroy(ref);

                if (var_found)
                {
                    switch (rv.type)
                    {
                    case RVAL_TYPE_LIST:
                        for (const Rlist *srp = rv.item; srp != NULL; srp = srp->next)
                        {
                            RlistAppendRval(list, RvalCopy(srp->val));
                        }
                        Rlist *next = rp->next;
                        RlistDestroyEntry(list, rp);
                        rp = next;
                        continue;

                    default:
                        ProgrammingError("List variable does not resolve to a list");
                        RlistAppendRval(list, RvalCopy(rp->val));
                        break;
                    }
                }
            }
        }
        rp = rp->next;
    }
}
Ejemplo n.º 4
0
static Rval ExpandListEntry(EvalContext *ctx,
                            const char *ns, const char *scope,
                            int expandnaked, Rval entry)
{
    if (entry.type == RVAL_TYPE_SCALAR &&
        IsNakedVar(entry.item, '@'))
    {
        if (expandnaked)
        {
            char naked[CF_MAXVARSIZE];
            GetNaked(naked, entry.item);

            if (IsExpandable(naked))
            {
                char *exp = ExpandScalar(ctx, ns, scope, naked, NULL);
                strlcpy(naked, exp, sizeof(naked));             /* TODO err */
                free(exp);
            }

            /* Check again, it might have changed. */
            if (!IsExpandable(naked))
            {
                VarRef *ref = VarRefParseFromScope(naked, scope);

                DataType value_type;
                const void *value = EvalContextVariableGet(ctx, ref, &value_type);
                VarRefDestroy(ref);

                if (value_type != CF_DATA_TYPE_NONE)     /* variable found? */
                {
                    return ExpandPrivateRval(ctx, ns, scope, value,
                                             DataTypeToRvalType(value_type));
                }
            }
        }
        else
        {
            return RvalNew(entry.item, RVAL_TYPE_SCALAR);
        }
    }

    return ExpandPrivateRval(ctx, ns, scope, entry.item, entry.type);
}
Ejemplo n.º 5
0
void RlistFlatten(EvalContext *ctx, Rlist **list)
{
    for (Rlist *rp = *list; rp != NULL;)
    {
        if (rp->type != RVAL_TYPE_SCALAR)
        {
            rp = rp->next;
            continue;
        }

        char naked[CF_BUFSIZE] = "";
        if (IsNakedVar(rp->item, '@'))
        {
            GetNaked(naked, rp->item);

            Rval rv;
            if (EvalContextVariableGet(ctx, (VarRef) { NULL, ScopeGetCurrent()->scope, naked }, &rv, NULL))
            {
                switch (rv.type)
                {
                case RVAL_TYPE_LIST:
                    for (const Rlist *srp = rv.item; srp != NULL; srp = srp->next)
                    {
                        RlistAppend(list, srp->item, srp->type);
                    }
                    Rlist *next = rp->next;
                    RlistDestroyEntry(list, rp);
                    rp = next;
                    continue;

                default:
                    ProgrammingError("List variable does not resolve to a list");
                    RlistAppend(list, rp->item, rp->type);
                    break;
                }
            }
        }
        rp = rp->next;
    }
}
Ejemplo n.º 6
0
void RlistFlatten(EvalContext *ctx, Rlist **list)
{
    Rlist *prev = NULL, *next;
    for (Rlist *rp = *list; rp != NULL; rp = next)
    {
        next = rp->next;
        if (rp->val.type != RVAL_TYPE_SCALAR)
        {
            prev = rp;
            continue;
        }

        char naked[CF_BUFSIZE] = "";
        if (IsNakedVar(RlistScalarValue(rp), '@'))
        {
            GetNaked(naked, RlistScalarValue(rp));

            if (!IsExpandable(naked))
            {
                VarRef *ref = VarRefParse(naked);
                DataType value_type = CF_DATA_TYPE_NONE;
                const void *value = EvalContextVariableGet(ctx, ref, &value_type);
                VarRefDestroy(ref);

                if (value)
                {
                    switch (DataTypeToRvalType(value_type))
                    {
                    case RVAL_TYPE_LIST:
                        {
                            RlistDestroyEntry(list, rp);

                            for (const Rlist *srp = value; srp != NULL; srp = srp->next)
                            {
                                Rlist *nrp = xmalloc(sizeof(Rlist));
                                nrp->val = RvalCopy(srp->val);
                                nrp->next = next;

                                if (prev)
                                {
                                    prev->next = nrp;
                                }
                                else
                                {
                                    *list = nrp;
                                }

                                prev = nrp;
                            }
                        }
                        continue;

                    default:
                        Log(LOG_LEVEL_WARNING, "Attempted to dereference variable '%s' using @ but variable did not resolve to a list",
                            RlistScalarValue(rp));
                        break;
                    }
                }
            }
        }

        prev = rp;
    }
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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)
            {
                VarRef *ref = VarRefParseFromBundle(naked, pbp);
                EvalContextVariableGet(ctx, ref, &retval, &vtype);
                VarRefDestroy(ref);
            }
            else
            {
                VarRef *ref = VarRefParseFromBundle(naked, bp);
                EvalContextVariableGet(ctx, ref, &retval, &vtype);
                VarRefDestroy(ref);
            }

            switch (vtype)
            {
            case DATA_TYPE_STRING_LIST:
            case DATA_TYPE_INT_LIST:
            case DATA_TYPE_REAL_LIST:
                {
                    VarRef *ref = VarRefParseFromBundle(lval, bp);
                    EvalContextVariablePut(ctx, ref, (Rval) { retval.item, RVAL_TYPE_LIST}, DATA_TYPE_STRING_LIST);
                    VarRefDestroy(ref);
                }
                break;
            default:
                {
                    Log(LOG_LEVEL_ERR, "List parameter '%s' not found while constructing scope '%s' - use @(scope.variable) in calling reference", naked, bp->name);
                    VarRef *ref = VarRefParseFromBundle(lval, bp);
                    EvalContextVariablePut(ctx, ref, (Rval) { rpr->item, RVAL_TYPE_SCALAR }, DATA_TYPE_STRING);
                    VarRefDestroy(ref);
                }
                break;
            }
        }
        else
        {
            switch(rpr->type)
            {
            case RVAL_TYPE_SCALAR:
                {
                    VarRef *ref = VarRefParseFromBundle(lval, bp);
                    EvalContextVariablePut(ctx, ref, (Rval) { rpr->item, RVAL_TYPE_SCALAR }, DATA_TYPE_STRING);
                    VarRefDestroy(ref);
                }
                break;

            case RVAL_TYPE_FNCALL:
                {
                    FnCall *subfp = rpr->item;
                    Rval rval = FnCallEvaluate(ctx, subfp, pp).rval;
                    if (rval.type == RVAL_TYPE_SCALAR)
                    {
                        VarRef *ref = VarRefParseFromBundle(lval, bp);
                        EvalContextVariablePut(ctx, ref, (Rval) { rval.item, RVAL_TYPE_SCALAR }, DATA_TYPE_STRING);
                        VarRefDestroy(ref);
                    }
                    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 */

    return;
}
Ejemplo n.º 9
0
Archivo: expand.c Proyecto: tzz/core
Rval EvaluateFinalRval(EvalContext *ctx, const Policy *policy, const char *ns, const char *scope,
                       Rval rval, bool forcelist, const Promise *pp)
{
    assert(ctx);
    assert(policy);

    Rval returnval, newret;
    if ((rval.type == RVAL_TYPE_SCALAR) && IsNakedVar(rval.item, '@'))        /* Treat lists specially here */
    {
        char naked[CF_MAXVARSIZE];
        GetNaked(naked, rval.item);

        if (!IsExpandable(naked))
        {
            VarRef *ref = VarRefParseFromScope(naked, scope);
            DataType value_type = DATA_TYPE_NONE;
            const void *value = EvalContextVariableGet(ctx, ref, &value_type);

            if (!value || DataTypeToRvalType(value_type) != RVAL_TYPE_LIST)
            {
                returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
            }
            else
            {
                returnval.item = ExpandList(ctx, ns, scope, value, true);
                returnval.type = RVAL_TYPE_LIST;
            }

            VarRefDestroy(ref);
        }
        else
        {
            returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
        }
    }
    else
    {
        if (forcelist)          /* We are replacing scalar @(name) with list */
        {
            returnval = ExpandPrivateRval(ctx, ns, scope, rval.item, rval.type);
        }
        else
        {
            if (FnCallIsBuiltIn(rval))
            {
                returnval = RvalCopy(rval);
            }
            else
            {
                returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
            }
        }
    }

    switch (returnval.type)
    {
    case RVAL_TYPE_SCALAR:
    case RVAL_TYPE_CONTAINER:
        break;

    case RVAL_TYPE_LIST:
        for (Rlist *rp = RvalRlistValue(returnval); rp; rp = rp->next)
        {
            if (rp->val.type == RVAL_TYPE_FNCALL)
            {
                FnCall *fp = RlistFnCallValue(rp);
                FnCallResult res = FnCallEvaluate(ctx, policy, fp, pp);

                FnCallDestroy(fp);
                rp->val = res.rval;
            }
            else
            {
                if (EvalContextStackCurrentPromise(ctx))
                {
                    if (IsCf3VarString(RlistScalarValue(rp)))
                    {
                        newret = ExpandPrivateRval(ctx, NULL, "this", rp->val.item, rp->val.type);
                        free(rp->val.item);
                        rp->val.item = newret.item;
                    }
                }
            }

            /* returnval unchanged */
        }
        break;

    case RVAL_TYPE_FNCALL:
        if (FnCallIsBuiltIn(returnval))
        {
            FnCall *fp = RvalFnCallValue(returnval);
            returnval = FnCallEvaluate(ctx, policy, fp, pp).rval;
            FnCallDestroy(fp);
        }
        break;

    default:
        returnval.item = NULL;
        returnval.type = RVAL_TYPE_NOPROMISEE;
        break;
    }

    return returnval;
}
Ejemplo n.º 10
0
Rval EvaluateFinalRval(EvalContext *ctx, const Policy *policy,
                       const char *ns, const char *scope,
                       Rval rval, bool forcelist, const Promise *pp)
{
    assert(ctx);
    assert(policy);
    Rval returnval;

    /* Treat lists specially. */
    if (rval.type == RVAL_TYPE_SCALAR && IsNakedVar(rval.item, '@'))
    {
        char naked[CF_MAXVARSIZE];
        GetNaked(naked, rval.item);

        if (IsExpandable(naked))                /* example: @(blah_$(blue)) */
        {
            returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
        }
        else
        {
            VarRef *ref = VarRefParseFromScope(naked, scope);
            DataType value_type;
            const void *value = EvalContextVariableGet(ctx, ref, &value_type);
            VarRefDestroy(ref);

            if (DataTypeToRvalType(value_type) == RVAL_TYPE_LIST)
            {
                returnval.item = ExpandList(ctx, ns, scope, value, true);
                returnval.type = RVAL_TYPE_LIST;
            }
            else
            {
                returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
            }
        }
    }
    else if (forcelist) /* We are replacing scalar @(name) with list */
    {
        returnval = ExpandPrivateRval(ctx, ns, scope, rval.item, rval.type);
    }
    else if (FnCallIsBuiltIn(rval))
    {
        returnval = RvalCopy(rval);
    }
    else
    {
        returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type);
    }

    switch (returnval.type)
    {
    case RVAL_TYPE_SCALAR:
    case RVAL_TYPE_CONTAINER:
        break;

    case RVAL_TYPE_LIST:
        for (Rlist *rp = RvalRlistValue(returnval); rp; rp = rp->next)
        {
            switch (rp->val.type)
            {
            case RVAL_TYPE_FNCALL:
            {
                FnCall *fp = RlistFnCallValue(rp);
                rp->val = FnCallEvaluate(ctx, policy, fp, pp).rval;
                FnCallDestroy(fp);
                break;
            }
            case RVAL_TYPE_SCALAR:
                if (EvalContextStackCurrentPromise(ctx) &&
                    IsCf3VarString(RlistScalarValue(rp)))
                {
                    void *prior = rp->val.item;
                    rp->val = ExpandPrivateRval(ctx, NULL, "this",
                                                prior, RVAL_TYPE_SCALAR);
                    free(prior);
                }
                /* else: returnval unchanged. */
                break;
            default:
                assert(!"Bad type for entry in Rlist");
            }
        }
        break;

    case RVAL_TYPE_FNCALL:
        if (FnCallIsBuiltIn(returnval))
        {
            FnCall *fp = RvalFnCallValue(returnval);
            returnval = FnCallEvaluate(ctx, policy, fp, pp).rval;
            FnCallDestroy(fp);
        }
        break;

    default:
        assert(returnval.item == NULL); /* else we're leaking it */
        returnval.item = NULL;
        returnval.type = RVAL_TYPE_NOPROMISEE;
        break;
    }

    return returnval;
}
Ejemplo n.º 11
0
/**
 * @brief Flattens an Rlist by expanding naked scalar list-variable
 *        members. Flattening is only one-level deep.
 */
void RlistFlatten(EvalContext *ctx, Rlist **list)
{
    Rlist *next;
    for (Rlist *rp = *list; rp != NULL; rp = next)
    {
        next = rp->next;

        if (rp->val.type == RVAL_TYPE_SCALAR      &&
            IsNakedVar(RlistScalarValue(rp), '@'))
        {
            char naked[CF_MAXVARSIZE];
            GetNaked(naked, RlistScalarValue(rp));

            /* Make sure there are no inner expansions to take place, like if
             * rp was "@{blah_$(blue)}".  */
            if (!IsExpandable(naked))
            {
                Log(LOG_LEVEL_DEBUG,
                    "Flattening slist: %s", RlistScalarValue(rp));

                VarRef *ref = VarRefParse(naked);
                DataType value_type;
                const void *value = EvalContextVariableGet(ctx, ref, &value_type);
                VarRefDestroy(ref);

                if (value_type == CF_DATA_TYPE_NONE)
                {
                    assert(value == NULL);
                    continue;                         /* undefined variable */
                }

                if (DataTypeToRvalType(value_type) != RVAL_TYPE_LIST)
                {
                    Log(LOG_LEVEL_WARNING,
                        "'%s' failed - variable is not list but %s",
                        RlistScalarValue(rp), DataTypeToString(value_type));
                    continue;
                }

                /* NOTE: Remember that value can be NULL as an empty Rlist. */

                /* at_node: just a mnemonic name for the
                            list node with @{blah}. */
                Rlist *at_node      = rp;
                Rlist *insert_after = at_node;
                for (const Rlist *rp2 = value; rp2 != NULL; rp2 = rp2->next)
                {
                    assert(insert_after != NULL);

                    RlistInsertAfter(insert_after, RvalCopy(rp2->val));
                    insert_after = insert_after->next;
                }

                /* Make sure we won't miss any element. */
                assert(insert_after->next == next);
                RlistDestroyEntry(list, at_node);   /* Delete @{blah} entry */

                char *list_s = RlistToString(*list);
                Log(LOG_LEVEL_DEBUG, "Flattened slist: %s", list_s);
                free(list_s);
            }
        }
    }
}