#include #include #include #include #include #include #include #include #include #include #include #include /** * Read whole file into a buffer and return pointer to buffer. * Possibly kind of silly to have both \p file and \p f. * Apparently there's no standardized way to get the file name of a * file pointer. * * @param fname Name of file to read. * @param f File pointer. * @return Pointer to buffer with file contents. */ static char *read_file(const char *fname, FILE *f) { fseek(f, 0, SEEK_END); long s = ftell(f); if (s == LONG_MAX) { /** @todo should probably do this via fstat or something */ error("%s might be a directory", fname); return NULL; } fseek(f, 0, SEEK_SET); char *buf = malloc(s + 1); if (!buf) return NULL; fread(buf, s + 1, 1, f); /* remember terminating null */ buf[s] = 0; return buf; } int run(const char *fname) { int ret = 0; const char *buf = NULL; struct scope *scope = NULL; struct parser *p = NULL; FILE *f = fopen(fname, "rb"); if (!f) { error("failed opening %s: %s\n", fname, strerror(errno)); return -1; } buf = read_file(fname, f); fclose(f); if (!buf) { ret = -1; goto out; } p = create_parser(); if (!p) { ret = -1; goto out; } parse(p, fname, buf); if (p->failed) { ret = -1; goto out; } scope = create_scope(); if (!scope) { ret = -1; goto out; } scope_set_file(scope, fname, buf); struct ast *ast = p->tree; if (check(scope, ast)) { ret = -1; goto out; } if (lower_ast(ast)) { ret = -1; goto out; } execute(); out: free((void *)buf); destroy_lowering(); destroy_scopes(); destroy_ast_nodes(); destroy_parser(p); return ret; }