Пример #1
0
vector(char*) initVectorFromPATH (void) {
    vector(char*) paths = vectorInit(16, malloc);

    //TODO: secure_getenv ??
    const char* PATH = getenv("PATH");

    /*Iterate through each colon-separated segment of the PATH,
      add the paths to the vector*/
    for (const char *path = PATH,
                    *nextcolon = /*not-null, for the entry condition*/ PATH;
         nextcolon;
         path = nextcolon+1) {
        /*Note: strchr can be used on UTF8 strings as long as searching for a Latin char*/
        nextcolon = strchr(path, ':');

        char* dupe;

        /*Not the last path, followed by a colon*/
        if (nextcolon) {
            size_t pathlength = nextcolon-path;
            /*Copy up to the colon, add a null*/
            dupe = strncpy(malloc(pathlength+1), path, pathlength);
            dupe[pathlength] = 0;

        } else
            dupe = strdup(path);

        vectorPush(&paths, dupe);
    }

    return paths;
}
Пример #2
0
/**
 * FnApp = { Atom | ( "`" Atom "`" ) }
 *
 * A series of at least one expr-atom. If multiple, then the last is a
 * function to which the others are applied. Instead, one of them may
 * be explicitly marked in backticks as the function.
 */
static ast* parseFnApp (parserCtx* ctx) {
    /*Filled iff there is a backtick function*/
    ast* fn = 0;

    vector(ast*) nodes = vectorInit(3, malloc);

    /*Require at least one expr*/
    if (!see(ctx, "!"))
        vectorPush(&nodes, parseAtom(ctx));

    while (waiting_for_delim(ctx)) {
        if (try_match(ctx, "!")) {
            if (fn) {
                error(ctx)("Multiple explicit functions: '%s'\n", ctx->current.buffer);
                vectorPush(&nodes, fn);
            }

            fn = parseAtom(ctx);

        } else
            vectorPush(&nodes, parseAtom(ctx));
    }

    if (fn)
        return astCreateFnApp(nodes, fn);

    else if (nodes.length == 0) {
        /*Shouldn't happen due to the way it parses*/
        errprintf("FnApp took no AST nodes");
        return astCreateInvalid();

    } else if (nodes.length == 1) {
        /*No application*/
        ast* node = vectorPop(&nodes);
        vectorFree(&nodes);
        return node;

    } else {
    	/*The last node is the fn*/
        fn = vectorPop(&nodes);
        return astCreateFnApp(nodes, fn);
    }
}
Пример #3
0
/**
 * Name = <UnqualifiedIdent>
 *
 * If inDecl, creates a symbol, adding it to the list of declarations
 * if already created.
 */
static ast* parserName (parserCtx* ctx, bool inDecl, symTag tag) {
    debugEnter("Name");

    ast* Node;

    if (tokenIsIdent(ctx)) {
        tokenLocation loc = ctx->location;
        Node = astCreateLiteralIdent(loc, tokenDupMatch(ctx));

        /*Check for a collision only in this scope, will shadow any
          other declarations elsewhere.*/
        sym* Symbol = symFind(ctx->scope, (char*) Node->literal);

        if (Symbol) {
            Node->symbol = Symbol;
            symChangeParent(Symbol, ctx->scope);

            if (Node->symbol->tag != tag && !isTypedefException(Node->symbol, tag))
                errorRedeclaredSymAs(ctx, Node->symbol, tag);

        } else if (inDecl)
            Node->symbol = symCreateNamed(tag, ctx->scope, (char*) Node->literal);

        if (Node->symbol) {
            /*Can't tell whether this is a duplicate declaration
              or a (matching) redefinition*/
            vectorPush(&Node->symbol->decls, Node);
        }

    } else {
        errorExpected(ctx, "name");
        Node = astCreateInvalid(ctx->location);
        Node->literal = strdup("");
        Node->symbol = symCreateNamed(tag, ctx->scope, "");
    }

    debugLeave();

    return Node;
}
Пример #4
0
/**
 * FnLit = "\" [{ Pattern }] "->" Expr
 */
static ast* parseFnLit (parserCtx* ctx) {
    match(ctx, "\\");

    /*Enter a new scope*/
    sym* oldscope = push_scope(ctx, symAddScope(ctx->scope));

    /*Arg patterns*/

    vector(ast*) args = vectorInit(2, malloc);

    while (!see(ctx, "->"))
        vectorPush(&args, parserPattern(ctx));

    /*Body*/

    match(ctx, "->");
    ast* expr = parseExpr(ctx);

    /*Pop scope*/
    ctx->scope = oldscope;

    return astCreateFnLit(args, expr);
}
Пример #5
0
static type* typeNonUnitary (typeSys* ts, typeKind kind, type init) {
    type* dt = typeCreate(kind, init);
    vectorPush(&ts->others, dt);
    return dt;
}
Пример #6
0
/**
 * Atom =   ( "(" [ Expr [{ "," Expr }] ] ")" )
 *        | ( "[" [{ Expr }] "]" )
 *        | FnLit | Path | <Str> | <Symbol>
 */
static ast* parseAtom (parserCtx* ctx) {
    ast* node;

    if (try_match(ctx, "(")) {
        /*Empty brackets => unit literal*/
        if (see(ctx, ")"))
            node = astCreateUnitLit();

        else {
            node = parseExpr(ctx);

            /*Tuple literal*/
            if (see(ctx, ",")) {
                vector(ast*) nodes = vectorInit(3, malloc);
                vectorPush(&nodes, node);

                while (try_match(ctx, ","))
                    vectorPush(&nodes, parseExpr(ctx));

                node = astCreateTupleLit(nodes);
            }
        }

        match(ctx, ")");

    /*List literal*/
    } else if (try_match(ctx, "[")) {
        vector(ast*) nodes = vectorInit(4, malloc);

        if (waiting_for(ctx, "]")) do {
            vectorPush(&nodes, parseExpr(ctx));
        } while (try_match(ctx, ","));

        node = astCreateListLit(nodes);

        match(ctx, "]");

    } else if (see(ctx, "\\")) {
        node = parseFnLit(ctx);

    } else if (see(ctx, "true") || see(ctx, "false")) {
        node = astCreateBoolLit(see(ctx, "true"));
        accept(ctx);

    } else if (see_kind(ctx, tokenIntLit)) {
        node = astCreateIntLit(atoi(ctx->current.buffer));
        accept(ctx);

    } else if (see_kind(ctx, tokenStrLit)) {
        node = astCreateStrLit(ctx->current.buffer);
        accept(ctx);

    } else if (see_kind(ctx, tokenNormal)) {
        sym* symbol;

        if (isPathToken(ctx->current.buffer))
            node = parsePath(ctx);

        else if ((symbol = symLookup(ctx->scope, ctx->current.buffer)))
            node = astCreateSymbol(symbol);

        else
            node = astCreateFileLit(ctx->current.buffer);

        accept(ctx);

    } else {
        expected(ctx, "expression");
        node = astCreateInvalid();
    }

    return node;
}
Пример #7
0
Файл: type.c Проект: Pastor/fcc
char* typeToStrEmbed (const type* DT, const char* embedded) {
    /*TODO: Jump through typedefs and offer akas
            Three modes: print as normal, print jumping through typedefs,
                         print both forms with akas at the correct positions
            Even when directed to, it is to the discretion of this function
            as to whether it is sensible to reprint types*/

    /*Basic type or invalid*/
    if (DT->tag == typeInvalid || DT->tag == typeBasic) {
        char* basicStr = typeIsInvalid(DT)
                            ? "<invalid>"
                            : (DT->basic->ident && DT->basic->ident[0])
                                ? DT->basic->ident
                                : DT->basic->tag == symStruct ? "<unnamed struct>" :
                                  DT->basic->tag == symUnion ? "<unnamed union>" :
                                  DT->basic->tag == symEnum ? "<unnamed enum>" : "<unnamed type>";

        char* qualified = typeQualifiersToStr(DT->qual, basicStr);

        if (embedded[0] == (char) 0)
            return qualified;

        else {
            char* ret = malloc(  strlen(embedded)
                   + strlen(basicStr)
                   + 2 + (DT->qual.isConst ? 6 : 0));
            sprintf(ret, "%s %s", qualified, embedded);
            free(qualified);
            return ret;
        }

    /*Function*/
    } else if (DT->tag == typeFunction) {
        /*Get the param string that goes inside the parens*/

        char* params = 0;

        if (DT->params == 0)
            params = strdup("void");

        else {
            vector/*<char*>*/ paramStrs;
            vectorInit(&paramStrs, DT->params+1);
            vectorPushFromArray(&paramStrs, (void**) DT->paramTypes, DT->params, sizeof(type*));
            vectorMap(&paramStrs, (vectorMapper) typeToStr, &paramStrs);

            if (DT->variadic)
                vectorPush(&paramStrs, "...");

            params = strjoinwith((char**) paramStrs.buffer, paramStrs.length, ", ", malloc);

            if (DT->variadic)
                paramStrs.length--;

            vectorFreeObjs(&paramStrs, free);
        }

        /* */

        char* format = malloc(  strlen(embedded) + 2
                              + strlen(params) + 3);

        if (!embedded[0])
            sprintf(format, "()(%s)", params);

        else
            sprintf(format, "%s(%s)", embedded, params);

        free(params);
        char* ret = typeToStrEmbed(DT->returnType, format);
        free(format);
        return ret;

    /*Array or Ptr*/
    } else {
        char* format;

        if (typeIsPtr(DT)) {
            format = malloc(strlen(embedded) + 4 + (DT->qual.isConst ? 7 : 0));

            char* qualified = typeQualifiersToStr(DT->qual, embedded);

            if (DT->base->tag == typeFunction)
                sprintf(format, "(*%s)", qualified);

            else
                sprintf(format, "*%s", qualified);

            free(qualified);

        } else {
            assert(typeIsArray(DT));

            format = malloc(  strlen(embedded)
                            + (DT->array < 0 ? 0 : logi(DT->array, 10)) + 4);

            if (DT->array < 0)
                sprintf(format, "%s[]", embedded);

            else
                sprintf(format, "%s[%d]", embedded, DT->array);
        }

        char* ret = typeToStrEmbed(DT->base, format);
        free(format);
        return ret;
    }
}