Esempio n. 1
0
static string_ty *
sa_close(void)
{
    string_ty       *s;

    s = str_n_from_c(sa_data, sa_data_length);
    sa_data_length = 0;
    return s;
}
Esempio n. 2
0
string_ty *
sa_close(stracc *sap)
{
    string_ty       *val;

    trace(("sa_close()\n{\n"));
    assert(sap->sa_inuse);
    val = str_n_from_c(sap->sa_buf, sap->sa_len);
    sap->sa_inuse = 0;
    trace(("return %08lX;\n", val));
    trace(("}\n"));
    return val;
}
Esempio n. 3
0
static string_ty *
ends_with(string_ty *s1, const char *s2)
{
    size_t          len2;

    len2 = strlen(s2);
    if
    (
        s1->str_length > len2
    &&
        0 == memcmp(s1->str_text + s1->str_length - len2, s2, len2)
    )
        return str_n_from_c(s1->str_text, s1->str_length - len2);
    return 0;
}
Esempio n. 4
0
string_ty *
str_field(string_ty *s, int sep, int fldnum)
{
    char        *cp;
    char        *ep;

    cp = s->str_text;
    while (fldnum > 0)
    {
	ep = strchr(cp, sep);
	if (!ep)
    	    return 0;
	cp = ep + 1;
	--fldnum;
    }
    ep = strchr(cp, sep);
    if (ep)
	return str_n_from_c(cp, ep - cp);
    return str_from_c(cp);
}
Esempio n. 5
0
int
main(int argc, char **argv)
{
    int             retval;

    /*
     * Some versions of cron(8) and at(1) set SIGCHLD to SIG_IGN.
     * This is kinda dumb, because it breaks assumprions made in
     * libc (like pclose, for instance).  It also blows away most
     * of Cook's process handling.  We explicitly set the SIGCHLD
     * signal handling to SIG_DFL to make sure this signal does what
     * we expect no matter how we are invoked.
     */
#ifdef SIGCHLD
    signal(SIGCHLD, SIG_DFL);
#else
    signal(SIGCLD, SIG_DFL);
#endif

    /*
     * initialize things
     * (order is critical here)
     */
    progname_set(argv[0]);
    str_initialize();
    id_initialize();
    lex_initialize();

    /*
     * parse the COOK environment variable
     */
    arglex_init_from_env(argv[0], argtab);
    argparse(OPTION_LEVEL_ENVIRONMENT);

    /*
     * parse the command line
     */
    arglex_init(argc, argv, argtab);
    argparse(OPTION_LEVEL_COMMAND_LINE);

    option_tidy_up();

    log_open();

    /*
     * turn on progress stars if they asked for them
     */
    if (option_test(OPTION_STAR))
        star_enable();

    /*
     * If we were asked to update the fingerprints, do it here.
     * We don't actually ant to read in the cookbook.
     */
    if (option.fingerprint_update)
    {
        fp_tweak();
        quit(0);
    }

    /*
     * read in the cook book
     *
     * If there are #include-cooked directives,
     * we may need to do it more than once.
     */
    if (!option.o_book)
        fatal_intl(0, i18n("no book found"));
    for (;;)
    {
        int             status;
        size_t          j;

        builtin_initialize();

        /*
         * instanciate the command line variable assignments
         */
        for (j = 0; j < option.o_vardef.nstrings; ++j)
        {
            char            *s;
            char            *cp;
            string_ty       *name;
            string_ty       *value;
            string_list_ty  wl;
            opcode_context_ty *ocp;

            s = option.o_vardef.string[j]->str_text;
            cp = strchr(s, '=');
            assert(cp);
            if (!cp)
                continue;
            name = str_n_from_c(s, cp - s);
            value = str_from_c(cp + 1);
            str2wl(&wl, value, (char *)0, 0);
            str_free(value);
            ocp = opcode_context_new(0, 0);
            opcode_context_id_assign(ocp, name, id_variable_new(&wl), 0);
            opcode_context_delete(ocp);
            str_free(name);
            string_list_destructor(&wl);
        }

        set_command_line_goals();

        parse(option.o_book);
        status = cook_auto_required();
        if (status < 0)
            quit(1);
        if (!status)
            break;
        id_reset();
        cook_reset();
    }

    /*
     * work out what to cook.
     * If no targets have been given, use the first explicit recipe.
     */
    set_command_line_goals();
    if (!option.o_target.nstrings)
        cook_find_default(&option.o_target);
    assert(option.o_target.nstrings);

    /*
     * cook the target
     */
    if (option.pairs)
        retval = cook_pairs(&option.o_target);
    else if (option.script)
        retval = cook_script(&option.o_target);
    else if (option.web)
        retval = cook_web(&option.o_target);
    else
        retval = cook(&option.o_target);

#ifdef DEBUG
    fflush_slowly_report();
#endif

    quit(retval);
    /*NOTREACHED*/
    return 0;
}
Esempio n. 6
0
string_ty *
flatten(string_ty *filename)
{
    string_list_ty  sl;
    static string_ty *root;
    static string_ty *dot;
    static string_ty *dotdot;
    size_t          pos;
    size_t          start;
    size_t          j;
    string_ty       *s;

    /*
     * Create some things we are going to need.
     */
    if (!root)
    {
        root = str_from_c("");
        dot = str_from_c(".");
        dotdot = str_from_c("..");
    }

    /*
     * leading slash is special
     */
    pos = 0;
    string_list_constructor(&sl);
    if (filename->str_text[0] == '/')
    {
        ++pos;
        string_list_append(&sl, root);
    }

    /*
     * Break it into slash-separaed words.
     */
    for (;;)
    {
        while (pos < filename->str_length && filename->str_text[pos] == '/')
            ++pos;
        if (pos >= filename->str_length)
            break;
        start = pos;
        for (;;)
        {
            ++pos;
            if (pos >= filename->str_length || filename->str_text[pos] == '/')
                break;
        }

        /*
         * remember each word (except ".")
         */
        s = str_n_from_c(filename->str_text + start, pos - start);
        if (!str_equal(s, dot))
            string_list_append(&sl, s);
        str_free(s);
    }

    /*
     * Try as hard as possible to chuck out redundant stuff.
     */
    for (;;)
    {
        int             changed = 0;

        /*
         * "/.." -> "/"
         */
        if
        (
            sl.nstrings >= 2
        &&
            str_equal(sl.string[0], root)
        &&
            str_equal(sl.string[1], dotdot)
        )
        {
            string_list_remove_nth(&sl, 1);
            ++changed;
        }

        /*
         * "name/.." -> ""
         */
        for (j = 0; j + 1 < sl.nstrings; ++j)
        {
            if (str_equal(sl.string[j], root))
                continue;
            if (str_equal(sl.string[j], dotdot))
                continue;
            if (!str_equal(sl.string[j + 1], dotdot))
                continue;
            string_list_remove_nth(&sl, j);
            string_list_remove_nth(&sl, j);
            ++changed;
            --j;
        }

        /*
         * loop if anything changed,
         * bail if we can't find more to do
         */
        if (!changed)
            break;
    }

    /*
     * reassemble the "cleaned" path
     */
    s = wl2str_respect_empty(&sl, 0, sl.nstrings, "/", 1);
    string_list_destructor(&sl);
    return s;
}
Esempio n. 7
0
static int
reserved(string_ty *s)
{
    typedef struct table_ty table_ty;
    struct table_ty
    {
        char            *name;
        int             token;
    };

    static table_ty table[] =
    {
        { "override", OVERRIDE },
        { "include", INCLUDE2 },
        { "-include", INCLUDE3 },
        { ".include", INCLUDE },
        { "vpath", VPATH },
        { "VPATH", VPATH2 },
        { "ifdef", IF },
        { "ifndef", IF },
        { "ifeq", IF },
        { "ifneq", IF },
        { "else", ELSE },
        { "endif", ENDIF },
        { "endef", ENDDEF },
        { "define", DEFINE },
        { "export", EXPORT },
        { "unexport", UNEXPORT },
    };

    static symtab_ty *symtab;
    int             *data;
    string_ty       *name;
    char            *cp;

    if (!symtab)
    {
        table_ty        *tp;

        symtab = symtab_alloc(SIZEOF(table));
        for (tp = table; tp < ENDOF(table); ++tp)
        {
            name = str_from_c(tp->name);
            symtab_assign(symtab, name, &tp->token);
            str_free(name);
        }
    }

    cp = strchr(s->str_text, '(');
    if (cp)
    {
        name = str_n_from_c(s->str_text, cp - s->str_text);
        data = symtab_query(symtab, name);
        str_free(name);
    }
    else
        data = symtab_query(symtab, s);
    if (data)
        return *data;
    return 0;
}
Esempio n. 8
0
static blob_list_ty *
ifeq(blob_list_ty *blp, string_list_ty *ref)
{
    blob_ty         *arg;
    blob_ty         *bp;
    blob_list_ty    *result;
    string_ty       *s;
    string_ty       *s2;
    char            *cp;
    size_t          j;

    /*
     * allocate the result list
     */
    trace(("ifeq()\n{\n"));
    result = blob_list_alloc();

    /*
     * make sure we were given enough arguments
     */
    if (blp->length < 2)
    {
        arg = blp->list[0];
        blob_list_append
        (
            result,
            blob_alloc(str_from_c("0"), arg->file_name, arg->line_number)
        );
        trace(("}\n"));
        return result;
    }

    /*
     * turn the list of arguments into a single string
     */
    arg = blp->list[1];
    s = str_copy(blp->list[1]->text);
    for (j = 2; j < blp->length; ++j)
    {
        s2 = str_format("%s %s", s->str_text, blp->list[j]->text->str_text);
        str_free(s);
        s = s2;
    }
    bp = blob_alloc(s, arg->file_name, arg->line_number);

    /*
     * rename the variables
     * and reform to be a single string, again.
     */
    variable_rename(bp, result, ref, VAREN_NO_QUOQUO);
    blob_free(bp);
    s = result->length ? str_copy(result->list[0]->text) : str_from_c("0");
    for (j = 1; j < result->length; ++j)
    {
        s2 = str_format("%s %s", s->str_text, result->list[j]->text->str_text);
        str_free(s);
        s = s2;
    }
    blob_list_free(result);

    /*
     * construct the result
     */
    result = blob_list_alloc();
    switch (s->str_text[0])
    {
    case '(':
        /*
         * ifeq (xxx,yyy)
         */
        if (s->str_length < 3)
            goto useless;
        cp = strchr(s->str_text, ',');
        if (cp == 0 || s->str_text[s->str_length - 1] != ')')
            goto useless;

        blob_list_append
        (
            result,
            blob_alloc(str_from_c("[in"), arg->file_name, arg->line_number)
        );

        s2 = str_n_from_c(s->str_text + 1, cp - s->str_text - 1);
        if (s2->str_length == 0)
            s2 = str_from_c("\"\"");
        bp = blob_alloc(s2, arg->file_name, arg->line_number);
        blob_list_append(result, bp);

        s2 = str_n_from_c(cp + 1, s->str_text + s->str_length - cp - 2);
        if (s2->str_length == 0)
            s2 = str_from_c("\"\"");
        bp = blob_alloc(s2, arg->file_name, arg->line_number);
        blob_list_append(result, bp);

        blob_list_append
        (
            result,
            blob_alloc(str_from_c("]"), arg->file_name, arg->line_number)
        );
        break;

    case '\'':
    case '"':
        /*
         * ifeq "xxx" "yyy"
         */
        if (s->str_length < 5)
            goto useless;
        cp = strchr(s->str_text + 1, s->str_text[0]);
        if
        (
            !cp
        ||
            cp[1] != ' '
        ||
            cp[2] != s->str_text[0]
        ||
            s->str_text[s->str_length - 1] != s->str_text[0]
        )
            goto useless;

        blob_list_append
        (
            result,
            blob_alloc(str_from_c("[in"), arg->file_name, arg->line_number)
        );

        s2 = str_n_from_c(s->str_text + 1, cp - s->str_text - 1);
        if (s2->str_length == 0)
            s2 = str_from_c("\"\"");
        bp = blob_alloc(s2, arg->file_name, arg->line_number);
        blob_list_append(result, bp);

        s2 = str_n_from_c(cp + 3, s->str_text + s->str_length - cp - 4);
        if (s2->str_length == 0)
            s2 = str_from_c("\"\"");
        bp = blob_alloc(s2, arg->file_name, arg->line_number);
        blob_list_append(result, bp);

        blob_list_append
        (
            result,
            blob_alloc(str_from_c("]"), arg->file_name, arg->line_number)
        );
        break;

    default:
        /*
         * We were given some useless thing, just rename the
         * variables and copy it through.
         */
        useless:
        bp = blob_alloc(str_copy(s), arg->file_name, arg->line_number);
        blob_list_append(result, bp);
        break;
    }
    str_free(s);
    trace(("}\n"));
    return result;
}
Esempio n. 9
0
string_ty *
str_from_c(const char *s)
{
    return str_n_from_c(s, strlen(s));
}
Esempio n. 10
0
static int
interpret(string_list_ty *result, const string_list_ty *arg,
    const expr_position_ty *pp, const struct opcode_context_ty *ocp)
{
    long            start;
    long            length;
    long            end;
    size_t          j;

    trace(("builtin::substr()\n{\n"));
    (void)ocp;
    if (arg->nstrings < 3)
    {
        sub_context_ty *scp;

        scp = sub_context_new();
        sub_var_set_string(scp, "Name", arg->string[0]);
        error_with_position
        (
            pp,
            scp,
            i18n("$name: requires two or more arguments")
        );
        sub_context_delete(scp);
        trace(("return -1;\n"));
        trace(("}\n"));
        return -1;
    }

    if (!number(arg->string[1]->str_text, &start))
    {
        sub_context_ty  *scp;

        scp = sub_context_new();
        sub_var_set_string(scp, "Name", arg->string[0]);
        sub_var_set(scp, "Number", "1");
        error_with_position
        (
            pp,
            scp,
            i18n("$name: argument $number: must be a positive decimal number")
        );
        sub_context_delete(scp);
        trace(("return -1;\n"));
        trace(("}\n"));
        return -1;
    }
    --start;
    trace(("start = %ld;\n", start));

    if (!number(arg->string[2]->str_text, &length))
    {
        sub_context_ty  *scp;

        scp = sub_context_new();
        sub_var_set_string(scp, "Name", arg->string[0]);
        sub_var_set(scp, "Number", "2");
        error_with_position
        (
            pp,
            scp,
            i18n("$name: argument $number: must be a positive decimal number")
        );
        sub_context_delete(scp);
        trace(("return -1;\n"));
        trace(("}\n"));
        return -1;
    }
    trace(("length = %ld;\n", length));
    if (start < 0)
    {
        length += start;
        start = 0;
        trace(("length = %ld;\n", length));
    }
    if (length < 0)
    {
        start = 0;
        length = 0;
    }
    end = start + length;

    for (j = 3; j < arg->nstrings; ++j)
    {
        string_ty       *s;
        string_ty       *s2;

        s = arg->string[j];
        trace(("s = \"%s\";\n", s->str_text));
        if (start >= (int)(s->str_length))
            s2 = str_from_c("");
        else if (end > (int)(s->str_length))
        {
            s2 = str_n_from_c(s->str_text + start, s->str_length - start);
        }
        else
            s2 = str_n_from_c(s->str_text + start, length);
        trace(("s2 = \"%s\";\n", s2->str_text));
        string_list_append(result, s2);
        str_free(s2);
    }
    trace(("return 0;\n"));
    trace(("}\n"));
    return 0;
}