diff --git a/Makefile b/Makefile index 0d1cee7..94b25e3 100644 --- a/Makefile +++ b/Makefile @@ -27,10 +27,10 @@ ifeq ($(track), no) CFLAGS += -DNOTRACK endif -OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o -OBJ_T = test.o util.o conout.o -OBJ_C = main.o lexer.o parser.o -OBJ_X = exec-standalone.o util.o conout.o +OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o file.o +OBJ_T = test.o util.o conout.o file.o +OBJ_C = main.o lexer.o parser.o file.o +OBJ_X = exec-standalone.o util.o conout.o file.o ifneq ("$(CYGWIN)", "") #nullify the common variables that diff --git a/code.c b/code.c index 42a5595..0ad8bec 100644 --- a/code.c +++ b/code.c @@ -154,41 +154,42 @@ bool code_write(const char *filename, const char *lnofile) { uint32_t lnotype = *(unsigned int*)"LNOF"; uint32_t version = 1; - fp = util_fopen(lnofile, "wb"); + fp = file_open(lnofile, "wb"); if (!fp) return false; util_endianswap(&version, 1, sizeof(version)); util_endianswap(code_linenums, vec_size(code_linenums), sizeof(code_linenums[0])); - if (fwrite(&lnotype, sizeof(lnotype), 1, fp) != 1 || - fwrite(&version, sizeof(version), 1, fp) != 1 || - fwrite(&code_header.defs.length, sizeof(code_header.defs.length), 1, fp) != 1 || - fwrite(&code_header.globals.length, sizeof(code_header.globals.length), 1, fp) != 1 || - fwrite(&code_header.fields.length, sizeof(code_header.fields.length), 1, fp) != 1 || - fwrite(&code_header.statements.length, sizeof(code_header.statements.length), 1, fp) != 1 || - fwrite(code_linenums, sizeof(code_linenums[0]), vec_size(code_linenums), fp) != vec_size(code_linenums)) + + if (file_write(&lnotype, sizeof(lnotype), 1, fp) != 1 || + file_write(&version, sizeof(version), 1, fp) != 1 || + file_write(&code_header.defs.length, sizeof(code_header.defs.length), 1, fp) != 1 || + file_write(&code_header.globals.length, sizeof(code_header.globals.length), 1, fp) != 1 || + file_write(&code_header.fields.length, sizeof(code_header.fields.length), 1, fp) != 1 || + file_write(&code_header.statements.length, sizeof(code_header.statements.length), 1, fp) != 1 || + file_write(code_linenums, sizeof(code_linenums[0]), vec_size(code_linenums), fp) != vec_size(code_linenums)) { con_err("failed to write lno file\n"); } - fclose(fp); + file_close(fp); fp = NULL; } - fp = util_fopen(filename, "wb"); + fp = file_open(filename, "wb"); if (!fp) return false; - if (1 != fwrite(&code_header, sizeof(prog_header) , 1 , fp) || - vec_size(code_statements) != fwrite(code_statements, sizeof(prog_section_statement), vec_size(code_statements), fp) || - vec_size(code_defs) != fwrite(code_defs, sizeof(prog_section_def) , vec_size(code_defs) , fp) || - vec_size(code_fields) != fwrite(code_fields, sizeof(prog_section_field) , vec_size(code_fields) , fp) || - vec_size(code_functions) != fwrite(code_functions, sizeof(prog_section_function) , vec_size(code_functions) , fp) || - vec_size(code_globals) != fwrite(code_globals, sizeof(int32_t) , vec_size(code_globals) , fp) || - vec_size(code_chars) != fwrite(code_chars, 1 , vec_size(code_chars) , fp)) + if (1 != file_write(&code_header, sizeof(prog_header) , 1 , fp) || + vec_size(code_statements) != file_write(code_statements, sizeof(prog_section_statement), vec_size(code_statements), fp) || + vec_size(code_defs) != file_write(code_defs, sizeof(prog_section_def) , vec_size(code_defs) , fp) || + vec_size(code_fields) != file_write(code_fields, sizeof(prog_section_field) , vec_size(code_fields) , fp) || + vec_size(code_functions) != file_write(code_functions, sizeof(prog_section_function) , vec_size(code_functions) , fp) || + vec_size(code_globals) != file_write(code_globals, sizeof(int32_t) , vec_size(code_globals) , fp) || + vec_size(code_chars) != file_write(code_chars, 1 , vec_size(code_chars) , fp)) { - fclose(fp); + file_close(fp); return false; } @@ -253,6 +254,6 @@ bool code_write(const char *filename, const char *lnofile) { vec_free(code_functions); vec_free(code_globals); vec_free(code_chars); - fclose(fp); + file_close(fp); return true; } diff --git a/conout.c b/conout.c index b8227e5..bf8b522 100644 --- a/conout.c +++ b/conout.c @@ -21,6 +21,7 @@ * SOFTWARE. */ #include "gmqcc.h" +#include /* * isatty/STDERR_FILENO/STDOUT_FILNO @@ -167,7 +168,7 @@ static int win_fputs(const char *str, FILE *h) { state = -1; } } else { - fputc(*str, h); + file_putc(*str, h); length ++; } str++; @@ -218,7 +219,7 @@ static int con_write(FILE *handle, const char *fmt, va_list va) { char data[4096]; memset(data, 0, sizeof(data)); vsnprintf(data, sizeof(data), fmt, va); - ln = (GMQCC_IS_DEFINE(handle)) ? win_fputs(data, handle) : fputs(data, handle); + ln = (GMQCC_IS_DEFINE(handle)) ? win_fputs(data, handle) : file_puts(data, handle); } #endif return ln; @@ -230,9 +231,9 @@ static int con_write(FILE *handle, const char *fmt, va_list va) { void con_close() { if (!GMQCC_IS_DEFINE(console.handle_err)) - fclose(console.handle_err); + file_close(console.handle_err); if (!GMQCC_IS_DEFINE(console.handle_out)) - fclose(console.handle_out); + file_close(console.handle_out); } void con_color(int state) { @@ -268,15 +269,18 @@ void con_reset() { int con_change(const char *out, const char *err) { con_close(); + if (!out) out = (const char *)((!console.handle_out) ? stdout : console.handle_out); + if (!err) err = (const char *)((!console.handle_err) ? stderr : console.handle_err); + if (GMQCC_IS_DEFINE(out)) { console.handle_out = GMQCC_IS_STDOUT(out) ? stdout : stderr; con_enablecolor(); - } else if (!(console.handle_out = fopen(out, "w"))) return 0; + } else if (!(console.handle_out = file_open(out, "w"))) return 0; if (GMQCC_IS_DEFINE(err)) { console.handle_err = GMQCC_IS_STDOUT(err) ? stdout : stderr; con_enablecolor(); - } else if (!(console.handle_err = fopen(err, "w"))) return 0; + } else if (!(console.handle_err = file_open(err, "w"))) return 0; /* no buffering */ setvbuf(console.handle_out, NULL, _IONBF, 0); diff --git a/exec.c b/exec.c index f4a986e..0b9b362 100644 --- a/exec.c +++ b/exec.c @@ -53,29 +53,28 @@ static void qcvmerror(qc_program *prog, const char *fmt, ...) qc_program* prog_load(const char *filename) { - qc_program *prog; - prog_header header; - FILE *file; + qc_program *prog; + prog_header header; + FILE *file = file_open(filename, "rb"); - file = util_fopen(filename, "rb"); if (!file) return NULL; - if (fread(&header, sizeof(header), 1, file) != 1) { + if (file_read(&header, sizeof(header), 1, file) != 1) { loaderror("failed to read header from '%s'", filename); - fclose(file); + file_close(file); return NULL; } if (header.version != 6) { loaderror("header says this is a version %i progs, we need version 6\n", header.version); - fclose(file); + file_close(file); return NULL; } prog = (qc_program*)mem_a(sizeof(qc_program)); if (!prog) { - fclose(file); + file_close(file); printf("failed to allocate program data\n"); return NULL; } @@ -91,15 +90,17 @@ qc_program* prog_load(const char *filename) } #define read_data(hdrvar, progvar, reserved) \ - if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) { \ + if (file_seek(file, header.hdrvar.offset, SEEK_SET) != 0) { \ loaderror("seek failed"); \ goto error; \ } \ - if (fread(vec_add(prog->progvar, header.hdrvar.length + reserved), \ - sizeof(*prog->progvar), \ - header.hdrvar.length, file) \ - != header.hdrvar.length) \ - { \ + if (file_read ( \ + vec_add(prog->progvar, header.hdrvar.length + reserved), \ + sizeof(*prog->progvar), \ + header.hdrvar.length, \ + file \ + )!= header.hdrvar.length \ + ) { \ loaderror("read failed"); \ goto error; \ } @@ -113,7 +114,7 @@ qc_program* prog_load(const char *filename) read_data1(strings); read_data2(globals, 2); /* reserve more in case a RETURN using with the global at "the end" exists */ - fclose(file); + file_close(file); /* profile counters */ memset(vec_add(prog->profile, vec_size(prog->code)), 0, sizeof(prog->profile[0]) * vec_size(prog->code)); diff --git a/file.c b/file.c new file mode 100644 index 0000000..2bbd81f --- /dev/null +++ b/file.c @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2012 + * Wolfgang Bumiller + * Dale Weiler + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "gmqcc.h" + +/* + * This is essentially a "wrapper" interface around standard C's IO + * library. There is two reason we implement this, 1) visual studio + * hearts for "secure" varations, as part of it's "Security Enhancements + * in the CRT" (http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx). + * 2) But one of the greater reasons is for the possibility of large file + * support in the future. I don't expect to reach the 2GB limit any + * time soon (mainly because that would be insane). But when it comes + * to adding support for some other larger IO tasks (in the test-suite, + * or even the QCVM we'll need it). There is also a third possibility of + * building .dat files directly from zip files (which would be very cool + * at least I think so). + */ +#ifdef _MSC_VER +/* {{{ */ + /* + * Visual Studio has security CRT features which I actually want to support + * if we ever port to Windows 8, and want GMQCC to be API safe. + * + * We handle them here, for all file-operations. + */ + + static void file_exception ( + const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t reserved + ) { + wprintf(L"Invalid parameter dectected %s:%d %s [%s]\n", file, line, function, expression); + wprintf(L"Aborting ...\n"); + abort(); + } + + static void file_init() { + static bool init = false; + + if (init) + return; + + _set_invalid_parameter_handler(&file_exception); + + /* + * Turnoff the message box for CRT asserations otherwise + * we don't get the error reported to the console as we should + * otherwise get. + */ + _CrtSetReportMode(_CRT_ASSERT, 0); + init = !init; + } + + + FILE *file_open(const char *filename, const char *mode) { + FILE *handle = NULL; + file_init(); + + return ((fopen_s(&handle, filename, mode) != 0) ? NULL : handle; + } + + size_t file_read(void *buffer, size_t size, size_t count, FILE *fp) { + file_init(); + return fread_s(buffer, size*count, size, count, fp); + } + + int file_printf(FILE *fp, const char *format, ...) { + int rt; + va_list va; + va_start(va, format); + + file_init(); + rt = vfprintf_s(fp, format, va); + va_end (va); + + return rt; + } + +/* }}} */ +#else +/* {{{ */ + /* + * All other compilers/platforms that don't restrict insane policies on + * IO for no aparent reason. + */ + FILE *file_open(const char *filename, const char *mode) { + return fopen(filename, mode); + } + + size_t file_read(void *buffer, size_t size, size_t count, FILE *fp) { + return fread(buffer, size, count, fp); + } + + int file_printf(FILE *fp, const char *format, ...) { + int rt; + va_list va; + va_start(va, format); + rt = vfprintf(fp, format, va); + va_end (va); + + return rt; + } + +/* }}} */ +#endif + +/* + * These are implemented as just generic wrappers to keep consistency in + * the API. Not as macros though + */ +void GMQCC_INLINE file_close(FILE *fp) { + /* Invokes file_exception on windows if fp is null */ + fclose (fp); +} + +size_t GMQCC_INLINE file_write ( + const void *buffer, + size_t size, + size_t count, + FILE *fp +) { + /* Invokes file_exception on windows if fp is null */ + return fwrite(buffer, size, count, fp); +} + +int GMQCC_INLINE file_error(FILE *fp) { + /* Invokes file_exception on windows if fp is null */ + return ferror(fp); +} + +int GMQCC_INLINE file_getc(FILE *fp) { + /* Invokes file_exception on windows if fp is null */ + return fgetc(fp); +} + +int GMQCC_INLINE file_puts(FILE *fp, const char *str) { + /* Invokes file_exception on windows if fp is null */ + return fputs(str, fp); +} + +int GMQCC_INLINE file_seek(FILE *fp, long int off, int whence) { + /* Invokes file_exception on windows if fp is null */ + return fseek(fp, off, whence); +} + +/* + * Implements libc getline for systems that don't have it, which is + * assmed all. This works the same as getline(). + */ +int file_getline(char **lineptr, size_t *n, FILE *stream) { + int chr; + int ret; + char *pos; + + if (!lineptr || !n || !stream) + return -1; + if (!*lineptr) { + if (!(*lineptr = (char*)mem_a((*n=64)))) + return -1; + } + + chr = *n; + pos = *lineptr; + + for (;;) { + int c = file_getc(stream); + + if (chr < 2) { + *n += (*n > 16) ? *n : 64; + chr = *n + *lineptr - pos; + if (!(*lineptr = (char*)mem_r(*lineptr,*n))) + return -1; + pos = *n - chr + *lineptr; + } + + if (ferror(stream)) + return -1; + if (c == EOF) { + if (pos == *lineptr) + return -1; + else + break; + } + + *pos++ = c; + chr--; + if (c == '\n') + break; + } + *pos = '\0'; + return (ret = pos - *lineptr); +} diff --git a/ftepp.c b/ftepp.c index 96c20bf..ed501a5 100644 --- a/ftepp.c +++ b/ftepp.c @@ -991,9 +991,9 @@ static char *ftepp_include_find_path(const char *file, const char *pathfile) memcpy(vec_add(filename, len+1), file, len); vec_last(filename) = 0; - fp = util_fopen(filename, "rb"); + fp = file_open(filename, "rb"); if (fp) { - fclose(fp); + file_close(fp); return filename; } vec_free(filename); diff --git a/gmqcc.h b/gmqcc.h index af98f3f..1e4fe3b 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -26,8 +26,8 @@ #include #include #include -#include #include +#include #include /* @@ -159,7 +159,6 @@ # define strtof(X, Y) (float)(strtod(X, Y)) #endif - /* * Very roboust way at determining endianess at compile time: this handles * almost every possible situation. Otherwise a runtime check has to be @@ -245,8 +244,6 @@ /*===================================================================*/ /*=========================== util.c ================================*/ /*===================================================================*/ -FILE *util_fopen(const char *filename, const char *mode); - void *util_memory_a (size_t, unsigned int, const char *); void util_memory_d (void *, unsigned int, const char *); void *util_memory_r (void *, size_t, unsigned int, const char *); @@ -257,7 +254,6 @@ bool util_strupper (const char *); bool util_strdigit (const char *); char *util_strdup (const char *); void util_debug (const char *, const char *, ...); -int util_getline (char **, size_t *, FILE *); void util_endianswap (void *, size_t, unsigned int); size_t util_strtocmd (const char *, char *, size_t); @@ -383,10 +379,31 @@ void util_htdel (hash_table_t *ht); size_t util_hthash(hash_table_t *ht, const char *key); void *util_htgeth(hash_table_t *ht, const char *key, size_t hash); void util_htseth(hash_table_t *ht, const char *key, size_t hash, void *value); + +/*===================================================================*/ +/*============================ file.c ===============================*/ +/*===================================================================*/ +void GMQCC_INLINE file_close (FILE *); + +int GMQCC_INLINE file_error (FILE *); +int GMQCC_INLINE file_getc (FILE *); +int GMQCC_INLINE file_printf (FILE *, const char *, ...); +int GMQCC_INLINE file_puts (FILE *, const char *); +int GMQCC_INLINE file_seek (FILE *, long int, int); + +size_t GMQCC_INLINE file_read (void *, size_t, size_t, FILE *); +size_t GMQCC_INLINE file_write (const void *, size_t, size_t, FILE *); + +FILE* GMQCC_INLINE file_open (const char *, const char *); + +int /*NO_INLINE*/ file_getline(char **, size_t *, FILE *); + + /*===================================================================*/ /*=========================== code.c ================================*/ /*===================================================================*/ +/* TODO: cleanup */ /* Note: if you change the order, fix type_sizeof in ir.c */ enum { TYPE_VOID , @@ -806,6 +823,7 @@ vector vec3_mulvf(vector, float); /*============================= exec.c ==============================*/ /*===================================================================*/ +/* TODO: cleanup */ /* * Darkplaces has (or will have) a 64 bit prog loader * where the 32 bit qc program is autoconverted on load. @@ -910,6 +928,8 @@ bool parser_compile_file (const char *filename); bool parser_compile_string(const char *name, const char *str); bool parser_finish (const char *output); void parser_cleanup (); + +/* TODO: make compile_string accept len and remove this */ /* There's really no need to strlen() preprocessed files */ bool parser_compile_string_len(const char *name, const char *str, size_t len); @@ -1015,6 +1035,7 @@ typedef enum { COMPILER_GMQCC /* this QuakeC */ } opts_std_t; +/* TODO: cleanup this */ typedef struct { uint32_t O; /* -Ox */ const char *output; /* -o file */ diff --git a/lexer.c b/lexer.c index 7fc606c..cf554fb 100644 --- a/lexer.c +++ b/lexer.c @@ -186,7 +186,7 @@ static void lex_token_new(lex_file *lex) lex_file* lex_open(const char *file) { lex_file *lex; - FILE *in = util_fopen(file, "rb"); + FILE *in = file_open(file, "rb"); if (!in) { lexerror(NULL, "open failed: '%s'\n", file); @@ -195,7 +195,7 @@ lex_file* lex_open(const char *file) lex = (lex_file*)mem_a(sizeof(*lex)); if (!lex) { - fclose(in); + file_close(in); lexerror(NULL, "out of memory\n"); return NULL; } @@ -260,7 +260,7 @@ void lex_close(lex_file *lex) vec_free(lex->modelname); if (lex->file) - fclose(lex->file); + file_close(lex->file); #if 0 if (lex->tok) token_delete(lex->tok); diff --git a/main.c b/main.c index d6edd5c..d732ef9 100644 --- a/main.c +++ b/main.c @@ -139,8 +139,8 @@ static bool options_parse(int argc, char **argv) { bool argend = false; size_t itr; char buffer[1024]; - char *redirout = (char*)stdout; - char *redirerr = (char*)stderr; + char *redirout = NULL; + char *redirerr = NULL; char *config = NULL; while (!argend && argc > 1) { @@ -474,7 +474,7 @@ static bool progs_nextline(char **out, size_t *alen,FILE *src) { char *end; line = *out; - len = util_getline(&line, alen, src); + len = file_getline(&line, alen, src); if (len == -1) return false; @@ -553,15 +553,16 @@ int main(int argc, char **argv) { if (opts.pp_only) { if (opts_output_wasset) { - outfile = util_fopen(opts.output, "wb"); + outfile = file_open(opts.output, "wb"); if (!outfile) { con_err("failed to open `%s` for writing\n", opts.output); retval = 1; goto cleanup; } } - else - outfile = stdout; + else { + /* TODO: stdout without stdout .. */ + } } if (!opts.pp_only) { @@ -604,7 +605,7 @@ int main(int argc, char **argv) { progs_src = true; - src = util_fopen("progs.src", "rb"); + src = file_open("progs.src", "rb"); if (!src) { con_err("failed to open `progs.src` for reading\n"); retval = 1; @@ -633,7 +634,7 @@ int main(int argc, char **argv) { } srcdone: - fclose(src); + file_close(src); mem_d(line); } @@ -663,7 +664,7 @@ srcdone: } out = ftepp_get(); if (out) - fprintf(outfile, "%s", out); + file_printf(outfile, "%s", out); ftepp_flush(); } else { diff --git a/opts.c b/opts.c index 6008fb1..69e93b4 100644 --- a/opts.c +++ b/opts.c @@ -169,7 +169,7 @@ static size_t opts_ini_parse ( char *read_name; char *read_value; - while (util_getline(&line, &linesize, filehandle) != EOF) { + while (file_getline(&line, &linesize, filehandle) != EOF) { parse_beg = line; /* handle BOM */ @@ -315,11 +315,11 @@ void opts_ini_init(const char *file) { if (!file) { /* try ini */ - if (!(ini = fopen((file = "gmqcc.ini"), "r"))) + if (!(ini = file_open((file = "gmqcc.ini"), "r"))) /* try cfg */ - if (!(ini = fopen((file = "gmqcc.cfg"), "r"))) + if (!(ini = file_open((file = "gmqcc.cfg"), "r"))) return; - } else if (!(ini = fopen(file, "r"))) + } else if (!(ini = file_open(file, "r"))) return; con_out("found ini file `%s`\n", file); @@ -330,5 +330,5 @@ void opts_ini_init(const char *file) { vec_free(error); } - fclose(ini); + file_close(ini); } diff --git a/test.c b/test.c index b29a3d4..495b547 100644 --- a/test.c +++ b/test.c @@ -451,7 +451,7 @@ bool task_template_parse(const char *file, task_template_t *template, FILE *fp) return false; /* top down parsing */ - while (util_getline(&back, &size, fp) != EOF) { + while (file_getline(&back, &size, fp) != EOF) { /* skip whitespace */ data = back; if (*data && (*data == ' ' || *data == '\t')) @@ -592,7 +592,7 @@ task_template_t *task_template_compile(const char *file, const char *dir) { memset (fullfile, 0, sizeof(fullfile)); snprintf(fullfile, sizeof(fullfile), "%s/%s", dir, file); - tempfile = fopen(fullfile, "r"); + tempfile = file_open(fullfile, "r"); template = mem_a(sizeof(task_template_t)); task_template_nullify(template); @@ -667,7 +667,7 @@ task_template_t *task_template_compile(const char *file, const char *dir) { } success: - fclose(tempfile); + file_close(tempfile); return template; failure: @@ -676,7 +676,7 @@ failure: * so the check to see if it's not null here is required. */ if (tempfile) - fclose(tempfile); + file_close(tempfile); mem_d (template); return NULL; @@ -812,7 +812,7 @@ bool task_propagate(const char *curdir) { memset (buf,0,sizeof(buf)); snprintf(buf, sizeof(buf), "%s.stdout", template->tempfilename); task.stdoutlogfile = util_strdup(buf); - if (!(task.stdoutlog = fopen(buf, "w"))) { + if (!(task.stdoutlog = file_open(buf, "w"))) { con_err("error opening %s for stdout\n", buf); continue; } @@ -820,7 +820,7 @@ bool task_propagate(const char *curdir) { memset (buf,0,sizeof(buf)); snprintf(buf, sizeof(buf), "%s.stderr", template->tempfilename); task.stderrlogfile = util_strdup(buf); - if (!(task.stderrlog = fopen(buf, "w"))) { + if (!(task.stderrlog = file_open(buf, "w"))) { con_err("error opening %s for stderr\n", buf); continue; } @@ -904,8 +904,8 @@ void task_destroy(const char *curdir) { * annoying to have to do all this cleanup work. */ if (task_tasks[i].runhandles) task_pclose(task_tasks[i].runhandles); - if (task_tasks[i].stdoutlog) fclose (task_tasks[i].stdoutlog); - if (task_tasks[i].stderrlog) fclose (task_tasks[i].stderrlog); + if (task_tasks[i].stdoutlog) file_close (task_tasks[i].stdoutlog); + if (task_tasks[i].stderrlog) file_close (task_tasks[i].stderrlog); /* * Only remove the log files if the test actually compiled otherwise @@ -983,7 +983,7 @@ bool task_execute(task_template_t *template, char ***line) { char *data = NULL; size_t size = 0; size_t compare = 0; - while (util_getline(&data, &size, execute) != EOF) { + while (file_getline(&data, &size, execute) != EOF) { if (!strcmp(data, "No main function found\n")) { con_err("test failure: `%s` [%s] (No main function found)\n", template->description, @@ -1059,8 +1059,8 @@ void task_schedualize() { * Read data from stdout first and pipe that stuff into a log file * then we do the same for stderr. */ - while (util_getline(&data, &size, task_tasks[i].runhandles[1]) != EOF) { - fputs(data, task_tasks[i].stdoutlog); + while (file_getline(&data, &size, task_tasks[i].runhandles[1]) != EOF) { + file_puts(task_tasks[i].stdoutlog, data); if (strstr(data, "failed to open file")) { task_tasks[i].compiled = false; @@ -1069,7 +1069,7 @@ void task_schedualize() { fflush(task_tasks[i].stdoutlog); } - while (util_getline(&data, &size, task_tasks[i].runhandles[2]) != EOF) { + while (file_getline(&data, &size, task_tasks[i].runhandles[2]) != EOF) { /* * If a string contains an error we just dissalow execution * of it in the vm. @@ -1083,7 +1083,7 @@ void task_schedualize() { task_tasks[i].compiled = false; } - fputs(data, task_tasks[i].stderrlog); + file_puts(task_tasks[i].stderrlog, data); fflush(task_tasks[i].stdoutlog); } diff --git a/util.c b/util.c index 2b2f1b0..c744b15 100644 --- a/util.c +++ b/util.c @@ -25,6 +25,7 @@ #include #include "gmqcc.h" +/* TODO: remove globals ... */ uint64_t mem_ab = 0; uint64_t mem_db = 0; uint64_t mem_at = 0; @@ -347,54 +348,6 @@ uint16_t util_crc16(const char *k, int len, const short clamp) { } #endif -/* - * Implements libc getline for systems that don't have it, which is - * assmed all. This works the same as getline(). - */ -int util_getline(char **lineptr, size_t *n, FILE *stream) { - int chr; - int ret; - char *pos; - - if (!lineptr || !n || !stream) - return -1; - if (!*lineptr) { - if (!(*lineptr = (char*)mem_a((*n=64)))) - return -1; - } - - chr = *n; - pos = *lineptr; - - for (;;) { - int c = getc(stream); - - if (chr < 2) { - *n += (*n > 16) ? *n : 64; - chr = *n + *lineptr - pos; - if (!(*lineptr = (char*)mem_r(*lineptr,*n))) - return -1; - pos = *n - chr + *lineptr; - } - - if (ferror(stream)) - return -1; - if (c == EOF) { - if (pos == *lineptr) - return -1; - else - break; - } - - *pos++ = c; - chr--; - if (c == '\n') - break; - } - *pos = '\0'; - return (ret = pos - *lineptr); -} - size_t util_strtocmd(const char *in, char *out, size_t outsz) { size_t sz = 1; for (; *in && sz < outsz; ++in, ++out, ++sz) @@ -411,19 +364,7 @@ size_t util_strtononcmd(const char *in, char *out, size_t outsz) { return sz-1; } - -FILE *util_fopen(const char *filename, const char *mode) -{ -#ifdef _MSC_VER - FILE *out; - if (fopen_s(&out, filename, mode) != 0) - return NULL; - return out; -#else - return fopen(filename, mode); -#endif -} - +/* TODO: rewrite ... when I redo the ve cleanup */ void _util_vec_grow(void **a, size_t i, size_t s) { size_t m = *a ? 2*_vec_beg(*a)+i : i+1; void *p = mem_r((*a ? _vec_raw(*a) : NULL), s * m + sizeof(size_t)*2);