Exemplo n.º 1
0
Arquivo: rlist.c Projeto: 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;
    }
}
Exemplo n.º 2
0
Rlist *RlistCopyRewriter(const Rlist *rp, JsonElement *map)
{
    Rlist *start = NULL;

    while (rp != NULL)
    {
        RlistAppendRval(&start, RvalCopyRewriter(rp->val, map));
        rp = rp->next;
    }

    return start;
}
Exemplo n.º 3
0
Rlist *RlistCopy(const Rlist *rp)
{
    Rlist *start = NULL;

    while (rp != NULL)
    {
        RlistAppendRval(&start, RvalCopy(rp->val));
        rp = rp->next;
    }

    return start;
}
Exemplo n.º 4
0
Rlist *RlistAppend(Rlist **start, const void *item, RvalType type)
{
    Rlist *lp = *start;

    switch (type)
    {
    case RVAL_TYPE_SCALAR:
        return RlistAppendScalar(start, item);

    case RVAL_TYPE_FNCALL:
        break;

    case RVAL_TYPE_LIST:
        for (const Rlist *rp = item; rp; rp = rp->next)
        {
            lp = RlistAppendRval(start, RvalCopy(rp->val));
        }

        return lp;

    default:
        Log(LOG_LEVEL_DEBUG, "Cannot append %c to rval-list '%s'", type, (char *) item);
        return NULL;
    }

    Rlist *rp = xmalloc(sizeof(Rlist));

    if (*start == NULL)
    {
        *start = rp;
    }
    else
    {
        for (lp = *start; lp->next != NULL; lp = lp->next)
        {
        }

        lp->next = rp;
    }

    rp->val = RvalCopy((Rval) {(void *) item, type});

    ThreadLock(cft_lock);

    rp->next = NULL;

    ThreadUnlock(cft_lock);

    return rp;
}
Exemplo n.º 5
0
Arquivo: rlist.c Projeto: cduclos/core
Rlist *RlistCopy(const Rlist *list)
{
    Rlist *start = NULL;

    if (list == NULL)
    {
        return NULL;
    }

    for (const Rlist *rp = list; rp != NULL; rp = rp->next)
    {
        RlistAppendRval(&start, RvalCopy(rp->val));
    }

    return start;
}
Exemplo n.º 6
0
static Rlist *NewExpArgs(EvalContext *ctx, const FnCall *fp)
{
    int len;
    Rval rval;
    Rlist *newargs = NULL;
    FnCall *subfp;
    const FnCallType *fn = FnCallTypeGet(fp->name);

    len = RlistLen(fp->args);

    if (!(fn->options & FNCALL_OPTION_VARARG))
    {
        if (len != FnNumArgs(fn))
        {
            Log(LOG_LEVEL_ERR, "Arguments to function '%s' do not tally. Expected %d not %d",
                  fp->name, FnNumArgs(fn), len);
            PromiseRef(LOG_LEVEL_ERR, fp->caller);
            exit(1);
        }
    }

    for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next)
    {
        switch (rp->val.type)
        {
        case RVAL_TYPE_FNCALL:
            subfp = RlistFnCallValue(rp);
            rval = FnCallEvaluate(ctx, subfp, fp->caller).rval;
            assert(rval.item);
            break;
        default:
            rval = ExpandPrivateRval(ctx, NULL, NULL, (Rval) { rp->val.item, rp->val.type});
            assert(rval.item);
            break;
        }

        RlistAppendRval(&newargs, rval);
    }

    return newargs;
}
Exemplo n.º 7
0
Rlist *RlistAppendScalar(Rlist **start, const char *scalar)
{
    return RlistAppendRval(start, RvalCopyScalar((Rval) { (char *)scalar, RVAL_TYPE_SCALAR }));
}
Exemplo n.º 8
0
Rlist *RlistAppendFnCall(Rlist **start, const FnCall *fn)
{
    return RlistAppendRval(start, RvalCopyFnCall((Rval) { (FnCall *)fn, RVAL_TYPE_FNCALL }));
}
Exemplo n.º 9
0
// See fncall.c for the usage of allow_all_types.
Rlist *RlistAppendAllTypes(Rlist **start, const void *item, RvalType type, bool allow_all_types)
{
    Rlist *lp = *start;

    switch (type)
    {
    case RVAL_TYPE_SCALAR:
        return RlistAppendScalar(start, item);

    case RVAL_TYPE_FNCALL:
        break;

    case RVAL_TYPE_LIST:
        if (allow_all_types)
        {
            JsonElement* store = JsonArrayCreate(RlistLen(item));
            for (const Rlist *rp = item; rp; rp = rp->next)
            {
                JsonArrayAppendElement(store, RvalToJson(rp->val));
            }

            return RlistAppendRval(start, (Rval) { store, RVAL_TYPE_CONTAINER });
        }

        for (const Rlist *rp = item; rp; rp = rp->next)
        {
            lp = RlistAppendRval(start, RvalCopy(rp->val));
        }

        return lp;

    case RVAL_TYPE_CONTAINER:
        if (allow_all_types)
        {
            return RlistAppendRval(start, (Rval) { JsonCopy((JsonElement*) item), RVAL_TYPE_CONTAINER });
        }

        // note falls through!

    default:
        Log(LOG_LEVEL_DEBUG, "Cannot append %c to rval-list '%s'", type, (char *) item);
        return NULL;
    }

    Rlist *rp = xmalloc(sizeof(Rlist));

    rp->val  = RvalNew(item, type);
    rp->next = NULL;

    if (*start == NULL)
    {
        *start = rp;
    }
    else
    {
        for (lp = *start; lp->next != NULL; lp = lp->next)
        {
        }

        lp->next = rp;
    }

    return rp;
}
Exemplo n.º 10
0
/* Inserts an Rlist node with value #rval, right after the rlist node #node. */
void RlistInsertAfter(Rlist *node, Rval rval)
{
    assert(node != NULL);

    Rlist new_node = { .val  = rval,
                       .next = node->next };

    node->next = xmemdup(&new_node, sizeof(new_node));
}

Rval RvalNewRewriter(const void *item, RvalType type, JsonElement *map)
{
    switch (type)
    {
    case RVAL_TYPE_SCALAR:
        if (map != NULL && JsonLength(map) > 0 &&       // do we have a rewrite map?
            (strstr(item, "$(") || strstr(item, "${"))) // are there unresolved variable references?
        {
            // TODO: replace with BufferSearchAndReplace when the
            // string_replace code is merged.
            // Sorry about the CF_BUFSIZE ugliness.
            int max_size = 10*CF_BUFSIZE+1;
            char *buffer_from = xmalloc(max_size);
            char *buffer_to = xmalloc(max_size);

            Buffer *format = BufferNew();
            StringCopy(item, buffer_from, max_size);

            for (int iteration = 0; iteration < 10; iteration++)
            {
                bool replacement_made = false;
                int var_start = -1;
                char closing_brace = 0;
                for (int c = 0; c < buffer_from[c]; c++)
                {
                    if (buffer_from[c] == '$')
                    {
                        if (buffer_from[c+1] == '(')
                        {
                            closing_brace = ')';
                        }
                        else if (buffer_from[c+1] == '{')
                        {
                            closing_brace = '}';
                        }

                        if (closing_brace)
                        {
                            c++;
                            var_start = c-1;
                        }
                    }
                    else if (var_start >= 0 && buffer_from[c] == closing_brace)
                    {
                        char saved = buffer_from[c];
                        buffer_from[c] = '\0';
                        const char *repl = JsonObjectGetAsString(map, buffer_from + var_start + 2);
                        buffer_from[c] = saved;

                        if (repl)
                        {
                            // Before the replacement.
                            memcpy(buffer_to, buffer_from, var_start);

                            // The actual replacement.
                            int repl_len = strlen(repl);
                            memcpy(buffer_to + var_start, repl, repl_len);

                            // The text after.
                            strlcpy(buffer_to + var_start + repl_len, buffer_from + c + 1, max_size - var_start - repl_len);

                            // Reset location to immediately after the replacement.
                            c = var_start + repl_len - 1;
                            var_start = -1;
                            StringCopy(buffer_to, buffer_from, max_size);
                            closing_brace = 0;
                            replacement_made = true;
                        }
                    }
                }

                if (!replacement_made)
                {
                    break;
                }
            }

            char *ret = xstrdup(buffer_to);

            BufferDestroy(format);
            free(buffer_to);
            free(buffer_from);

            return (Rval) { ret, RVAL_TYPE_SCALAR };
        }
        else
        {
            return (Rval) { xstrdup(item), RVAL_TYPE_SCALAR };
        }

    case RVAL_TYPE_FNCALL:
        return (Rval) { FnCallCopyRewriter(item, map), RVAL_TYPE_FNCALL };

    case RVAL_TYPE_LIST:
        return (Rval) { RlistCopyRewriter(item, map), RVAL_TYPE_LIST };

    case RVAL_TYPE_CONTAINER:
        return (Rval) { JsonCopy(item), RVAL_TYPE_CONTAINER };

    case RVAL_TYPE_NOPROMISEE:
        return ((Rval) {NULL, type});
    }

    assert(false);
    return ((Rval) { NULL, RVAL_TYPE_NOPROMISEE });
}

Rval RvalNew(const void *item, RvalType type)
{
    return RvalNewRewriter(item, type, NULL);
}

Rval RvalCopyRewriter(Rval rval, JsonElement *map)
{
    return RvalNewRewriter(rval.item, rval.type, map);
}

Rval RvalCopy(Rval rval)
{
    return RvalNew(rval.item, rval.type);
}

/*******************************************************************/

Rlist *RlistCopyRewriter(const Rlist *rp, JsonElement *map)
{
    Rlist *start = NULL;

    while (rp != NULL)
    {
        RlistAppendRval(&start, RvalCopyRewriter(rp->val, map));
        rp = rp->next;
    }

    return start;
}