From: Dale Weiler Date: Fri, 11 Oct 2013 06:39:30 +0000 (-0400) Subject: Initial platform / compiler specific code refactoring. X-Git-Tag: 0.3.5~35^2~2^2~12 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=151606e25558ec8f8f211db5aba4c4fa66948731;p=xonotic%2Fgmqcc.git Initial platform / compiler specific code refactoring. --- diff --git a/Makefile b/Makefile index a89d8c2..f7255d4 100644 --- a/Makefile +++ b/Makefile @@ -148,12 +148,13 @@ install-doc: # DO NOT DELETE +pak.o: gmqcc.h opts.def +ansi.o: gmqcc.h opts.def util.o: gmqcc.h opts.def +stat.o: gmqcc.h opts.def fs.o: gmqcc.h opts.def conout.o: gmqcc.h opts.def opts.o: gmqcc.h opts.def -pak.o: gmqcc.h opts.def -stat.o: gmqcc.h opts.def test.o: gmqcc.h opts.def main.o: gmqcc.h opts.def lexer.h lexer.o: gmqcc.h opts.def lexer.h diff --git a/ansi.c b/ansi.c new file mode 100644 index 0000000..adc7907 --- /dev/null +++ b/ansi.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012, 2013 + * 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 +#include + +#include "gmqcc.h" + +int platform_vsnprintf(char *buffer, size_t bytes, const char *format, va_list arg) { + return vsnprintf(buffer, bytes, format, arg); +} + +int platform_sscanf(const char *str, const char *format, ...) { + int rt; + va_list va; + + va_start(va, format); + rt = vsscanf(str, format, va); + va_end (va); + + return rt; +} + +const struct tm *platform_localtime(const time_t *timer) { + return localtime(timer); +} + +const char *platform_ctime(const time_t *timer) { + return ctime(timer); +} + +char *platform_strncat(char *dest, const char *src, size_t num) { + return strncat(dest, src, num); +} + +const char *platform_tmpnam(char *str) { + return tmpnam(str); +} + +const char *platform_getenv(char *var) { + return getenv(var); +} + +int platform_snprintf(char *src, size_t bytes, const char *format, ...) { + int rt; + va_list va; + + va_start(va, format); + rt = vsnprintf(src, bytes, format, va); + va_end(va); + + return rt; +} + +char *platform_strcat(char *dest, const char *src) { + return strcat(dest, src); +} + +char *platform_strncpy(char *dest, const char *src, size_t num) { + return strncpy(dest, src, num); +} + +const char *platform_strerror(int err) { + return strerror(err); +} diff --git a/ast.c b/ast.c index 362a06f..56dc1e5 100644 --- a/ast.c +++ b/ast.c @@ -259,7 +259,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi if (!e) { if (pos + 6 >= bufsize) goto full; - util_strncpy(buf + pos, "(null)", 6); + platform_strncpy(buf + pos, "(null)", 6); return pos + 6; } @@ -268,7 +268,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi switch (e->vtype) { case TYPE_VARIANT: - util_strncpy(buf + pos, "(variant)", 9); + platform_strncpy(buf + pos, "(variant)", 9); return pos + 9; case TYPE_FIELD: @@ -314,7 +314,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi if (pos + 1 >= bufsize) goto full; buf[pos++] = '['; - pos += util_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count); + pos += platform_snprintf(buf + pos, bufsize - pos - 1, "%i", (int)e->count); if (pos + 1 >= bufsize) goto full; buf[pos++] = ']'; @@ -325,7 +325,7 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi typelen = strlen(typestr); if (pos + typelen >= bufsize) goto full; - util_strncpy(buf + pos, typestr, typelen); + platform_strncpy(buf + pos, typestr, typelen); return pos + typelen; } @@ -1463,12 +1463,12 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) namelen = strlen(self->name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + platform_strncpy(name, self->name, namelen); array->ir_values = (ir_value**)mem_a(sizeof(array->ir_values[0]) * array->expression.count); array->ir_values[0] = v; for (ai = 1; ai < array->expression.count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); + platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); array->ir_values[ai] = ir_builder_create_field(ir, name, vtype); if (!array->ir_values[ai]) { mem_d(name); @@ -1532,12 +1532,12 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) namelen = strlen(self->name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + platform_strncpy(name, self->name, namelen); self->ir_values = (ir_value**)mem_a(sizeof(self->ir_values[0]) * self->expression.count); self->ir_values[0] = v; for (ai = 1; ai < self->expression.count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); + platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); self->ir_values[ai] = ir_builder_create_global(ir, name, vtype); if (!self->ir_values[ai]) { mem_d(name); @@ -1677,11 +1677,11 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param) namelen = strlen(self->name); name = (char*)mem_a(namelen + 16); - util_strncpy(name, self->name, namelen); + platform_strncpy(name, self->name, namelen); self->ir_values[0] = v; for (ai = 1; ai < self->expression.count; ++ai) { - util_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); + platform_snprintf(name + namelen, 16, "[%u]", (unsigned int)ai); self->ir_values[ai] = ir_function_create_local(func, name, vtype, param); if (!self->ir_values[ai]) { compile_error(ast_ctx(self), "internal_error: ir_builder_create_global failed on `%s`", name); diff --git a/conout.c b/conout.c index 63391d6..f89d68c 100644 --- a/conout.c +++ b/conout.c @@ -216,11 +216,7 @@ static int con_write(FILE *handle, const char *fmt, va_list va) { { char data[4096]; memset(data, 0, sizeof(data)); -#ifdef _MSC_VER - vsnprintf_s(data, sizeof(data), sizeof(data), fmt, va); -#else - vsnprintf(data, sizeof(data), fmt, va); -#endif + platform_vsnprintf(data, sizeof(data), fmt, va); ln = (GMQCC_IS_DEFINE(handle)) ? win_fputs(handle, data) : fs_file_puts(handle, data); } #endif diff --git a/exec.c b/exec.c index c4de8ad..d614ebf 100644 --- a/exec.c +++ b/exec.c @@ -37,7 +37,7 @@ static void loaderror(const char *fmt, ...) va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); - printf(": %s\n", util_strerror(err)); + printf(": %s\n", platform_strerror(err)); } static void qcvmerror(qc_program_t *prog, const char *fmt, ...) @@ -91,11 +91,11 @@ qc_program_t* prog_load(const char *filename, bool skipversion) } #define read_data(hdrvar, progvar, reserved) \ - if (fs_file_seek(file, header.hdrvar.offset, SEEK_SET) != 0) { \ + if (fs_file_seek(file, header.hdrvar.offset, SEEK_SET) != 0) { \ loaderror("seek failed"); \ goto error; \ } \ - if (fs_file_read ( \ + if (fs_file_read ( \ vec_add(prog->progvar, header.hdrvar.length + reserved), \ sizeof(*prog->progvar), \ header.hdrvar.length, \ @@ -661,7 +661,7 @@ static int qc_ftos(qc_program_t *prog) { qcany_t str; CheckArgs(1); num = GetArg(0); - util_snprintf(buffer, sizeof(buffer), "%g", num->_float); + platform_snprintf(buffer, sizeof(buffer), "%g", num->_float); str.string = prog_tempstring(prog, buffer); Return(str); return 0; @@ -683,7 +683,7 @@ static int qc_vtos(qc_program_t *prog) { qcany_t str; CheckArgs(1); num = GetArg(0); - util_snprintf(buffer, sizeof(buffer), "'%g %g %g'", num->vector[0], num->vector[1], num->vector[2]); + platform_snprintf(buffer, sizeof(buffer), "'%g %g %g'", num->vector[0], num->vector[1], num->vector[2]); str.string = prog_tempstring(prog, buffer); Return(str); return 0; @@ -695,7 +695,7 @@ static int qc_etos(qc_program_t *prog) { qcany_t str; CheckArgs(1); num = GetArg(0); - util_snprintf(buffer, sizeof(buffer), "%i", num->_int); + platform_snprintf(buffer, sizeof(buffer), "%i", num->_int); str.string = prog_tempstring(prog, buffer); Return(str); return 0; @@ -877,17 +877,10 @@ static void prog_main_setparams(qc_program_t *prog) { arg->vector[2] = 0; switch (main_params[i].vtype) { case TYPE_VECTOR: -#ifdef _MSC_VER - (void)sscanf_s(main_params[i].value, " %f %f %f ", - &arg->vector[0], - &arg->vector[1], - &arg->vector[2]); -#else - (void)sscanf(main_params[i].value, " %f %f %f ", - &arg->vector[0], - &arg->vector[1], - &arg->vector[2]); -#endif + (void)platform_sscanf(main_params[i].value, " %f %f %f ", + &arg->vector[0], + &arg->vector[1], + &arg->vector[2]); break; case TYPE_FLOAT: arg->_float = atof(main_params[i].value); diff --git a/fold.c b/fold.c index ffa0f65..d485ed2 100644 --- a/fold.c +++ b/fold.c @@ -338,7 +338,7 @@ ast_expression *fold_constgen_string(fold_t *fold, const char *str, bool transla if (translate) { char name[32]; - util_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(fold->parser->translated++)); + platform_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(fold->parser->translated++)); out = ast_value_new(parser_ctx(fold->parser), name, TYPE_STRING); out->expression.flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */ } else diff --git a/fs.c b/fs.c index 501041f..7844703 100644 --- a/fs.c +++ b/fs.c @@ -229,7 +229,7 @@ int fs_file_getline(char **lineptr, size_t *n, FILE *stream) { if (!dir) return NULL; - util_strncpy(dir->dd_name, name, strlen(name)); + platform_strncpy(dir->dd_name, name, strlen(name)); return dir; } @@ -249,8 +249,8 @@ int fs_file_getline(char **lineptr, size_t *n, FILE *stream) { if (*dir->dd_name) { size_t n = strlen(dir->dd_name); if ((dirname = (char*)mem_a(n + 5) /* 4 + 1 */)) { - util_strncpy(dirname, dir->dd_name, n); - util_strncpy(dirname + n, "\\*.*", 4); /* 4 + 1 */ + platform_strncpy(dirname, dir->dd_name, n); + platform_strncpy(dirname + n, "\\*.*", 4); /* 4 + 1 */ } } else { if (!(dirname = util_strdup("\\*.*"))) @@ -270,7 +270,7 @@ int fs_file_getline(char **lineptr, size_t *n, FILE *stream) { return NULL; if ((data = (struct dirent*)mem_a(sizeof(struct dirent)))) { - util_strncpy(data->d_name, info.cFileName, FILENAME_MAX - 1); + platform_strncpy(data->d_name, info.cFileName, FILENAME_MAX - 1); data->d_name[FILENAME_MAX - 1] = '\0'; /* terminate */ data->d_namlen = strlen(data->d_name); } diff --git a/ftepp.c b/ftepp.c index 050d6d8..f6c850c 100644 --- a/ftepp.c +++ b/ftepp.c @@ -85,22 +85,14 @@ static uint32_t ftepp_predef_randval = 0; /* __DATE__ */ static char *ftepp_predef_date(lex_file *context) { - struct tm *itime = NULL; - time_t rtime; - char *value = (char*)mem_a(82); - /* 82 is enough for strftime but we also have " " in our string */ + const struct tm *itime = NULL; + char *value = (char*)mem_a(82); + time_t rtime; (void)context; - /* get time */ time (&rtime); - -#ifdef _MSC_VER - localtime_s(itime, &rtime); -#else - itime = localtime(&rtime); -#endif - + itime = platform_localtime(&rtime); strftime(value, 82, "\"%b %d %Y\"", itime); return value; @@ -108,22 +100,14 @@ static char *ftepp_predef_date(lex_file *context) { /* __TIME__ */ static char *ftepp_predef_time(lex_file *context) { - struct tm *itime = NULL; - time_t rtime; - char *value = (char*)mem_a(82); - /* 82 is enough for strftime but we also have " " in our string */ + const struct tm *itime = NULL; + char *value = (char*)mem_a(82); + time_t rtime; (void)context; - /* get time */ time (&rtime); - -#ifdef _MSC_VER - localtime_s(itime, &rtime); -#else - itime = localtime(&rtime); -#endif - + itime = platform_localtime(&rtime); strftime(value, 82, "\"%X\"", itime); return value; @@ -139,7 +123,7 @@ static char *ftepp_predef_line(lex_file *context) { static char *ftepp_predef_file(lex_file *context) { size_t length = strlen(context->name) + 3; /* two quotes and a terminator */ char *value = (char*)mem_a(length); - util_snprintf(value, length, "\"%s\"", context->name); + platform_snprintf(value, length, "\"%s\"", context->name); return value; } @@ -180,27 +164,14 @@ static char *ftepp_predef_randomlast(lex_file *context) { /* __TIMESTAMP__ */ static char *ftepp_predef_timestamp(lex_file *context) { struct stat finfo; - char *find; + const char *find; char *value; size_t size; -#ifdef _MSC_VER - char buffer[64]; -#endif + if (stat(context->name, &finfo)) return util_strdup("\"\""); - /* - * ctime and its fucking annoying newline char, no worries, we're - * professionals here. - */ - -#ifndef _MSC_VER - find = ctime(&finfo.st_mtime); -#else - ctime_s(buffer, sizeof(buffer), &finfo.st_mtime); - find = buffer; -#endif - + find = platform_ctime(&finfo.st_mtime); value = (char*)mem_a(strlen(find) + 1); memcpy(&value[1], find, (size = strlen(find)) - 1); @@ -893,7 +864,7 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param if (resetline && !ftepp->in_macro) { char lineno[128]; - util_snprintf(lineno, 128, "\n#pragma line(%lu)\n", (unsigned long)(old_lexer->sline)); + platform_snprintf(lineno, 128, "\n#pragma line(%lu)\n", (unsigned long)(old_lexer->sline)); ftepp_out(ftepp, lineno, false); } @@ -1493,7 +1464,7 @@ static bool ftepp_include(ftepp_t *ftepp) ftepp_out(ftepp, "\n#pragma file(", false); ftepp_out(ftepp, ctx.file, false); - util_snprintf(lineno, sizeof(lineno), ")\n#pragma line(%lu)\n", (unsigned long)(ctx.line+1)); + platform_snprintf(lineno, sizeof(lineno), ")\n#pragma line(%lu)\n", (unsigned long)(ctx.line+1)); ftepp_out(ftepp, lineno, false); /* skip the line */ @@ -1872,12 +1843,12 @@ ftepp_t *ftepp_create() minor[2] = '"'; } else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_GMQCC) { ftepp_add_define(ftepp, NULL, "__STD_GMQCC__"); - util_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR); - util_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR); + platform_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR); + platform_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR); } else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCCX) { ftepp_add_define(ftepp, NULL, "__STD_QCCX__"); - util_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR); - util_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR); + platform_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR); + platform_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR); } else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCC) { ftepp_add_define(ftepp, NULL, "__STD_QCC__"); /* 1.0 */ diff --git a/gmqcc.h b/gmqcc.h index cb70d66..75f70a5 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -24,6 +24,7 @@ #ifndef GMQCC_HDR #define GMQCC_HDR #include +#include /* TODO: remove this? */ #include /* TODO: remove this */ /* @@ -343,18 +344,8 @@ uint16_t util_crc16(uint16_t crc, const char *data, size_t len); void util_seed(uint32_t); uint32_t util_rand(void); -/* - * String functions (formatting, copying, concatenating, errors). These are wrapped - * to use the MSVC _safe_ versions when using MSVC, plus some implementations of - * these are non-conformant or don't exist such as asprintf and snprintf, which are - * not supported in C90, but do exist in C99. - */ -int util_vasprintf(char **ret, const char *fmt, va_list); -int util_asprintf (char **ret, const char *fmt, ...); -int util_snprintf (char *src, size_t bytes, const char *format, ...); -char *util_strcat (char *dest, const char *src); -char *util_strncpy (char *dest, const char *src, size_t num); -const char *util_strerror (int num); +int util_vasprintf(char **ret, const char *fmt, va_list); +int util_asprintf (char **ret, const char *fmt, ...); /* * A flexible vector implementation: all vector pointers contain some @@ -470,6 +461,18 @@ int fs_dir_close (DIR *); struct dirent *fs_dir_read (DIR *); +int platform_vsnprintf(char *buffer, size_t bytes, const char *format, va_list arg); +int platform_sscanf(const char *str, const char *format, ...); +const struct tm *platform_localtime(const time_t *timer); +const char *platform_ctime(const time_t *timer); +char *platform_strncat(char *dest, const char *src, size_t num); +const char *platform_tmpnam(char *str); +const char *platform_getenv(char *var); +int platform_snprintf(char *src, size_t bytes, const char *format, ...); +char *platform_strcat(char *dest, const char *src); +char *platform_strncpy(char *dest, const char *src, size_t num); +const char *platform_strerror(int err); + /*===================================================================*/ /*=========================== correct.c =============================*/ /*===================================================================*/ diff --git a/include.mk b/include.mk index 20ffdd4..ed7822a 100644 --- a/include.mk +++ b/include.mk @@ -14,10 +14,10 @@ LDFLAGS += LIBS += -lm #objects -OBJ_C = main.o lexer.o parser.o fs.o stat.o util.o code.o ast.o ir.o conout.o ftepp.o opts.o utf8.o correct.o fold.o intrin.o -OBJ_P = util.o fs.o conout.o opts.o pak.o stat.o -OBJ_T = test.o util.o opts.o conout.o fs.o stat.o -OBJ_X = exec-standalone.o util.o opts.o conout.o fs.o stat.o +OBJ_C = main.o ansi.o util.o stat.o fs.o lexer.o parser.o code.o ast.o ir.o conout.o ftepp.o opts.o utf8.o correct.o fold.o intrin.o +OBJ_P = pak.o ansi.o util.o stat.o fs.o conout.o opts.o pak.o +OBJ_T = test.o ansi.o util.o stat.o fs.o opts.o conout.o +OBJ_X = exec-standalone.o ansi.o util.o stat.o fs.o opts.o conout.o #gource flags GOURCEFLAGS = \ diff --git a/intrin.c b/intrin.c index 94b4202..49de952 100644 --- a/intrin.c +++ b/intrin.c @@ -39,8 +39,8 @@ static GMQCC_INLINE ast_function *intrin_value(intrin_t *intrin, ast_value **val char buffer[1024]; char stype [1024]; - util_snprintf(buffer, sizeof(buffer), "__builtin_%s", name); - util_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]); + platform_snprintf(buffer, sizeof(buffer), "__builtin_%s", name); + platform_snprintf(stype, sizeof(stype), "<%s>", type_name[vtype]); *value = ast_value_new(intrin_ctx(intrin), buffer, TYPE_FUNCTION); (*value)->intrinsic = true; diff --git a/ir.c b/ir.c index f0274e1..1da5d7c 100644 --- a/ir.c +++ b/ir.c @@ -3320,7 +3320,7 @@ static ir_value* ir_gen_extparam_proto(ir_builder *ir) ir_value *global; char name[128]; - util_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(vec_size(ir->extparam_protos))); + platform_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(vec_size(ir->extparam_protos))); global = ir_value_var(name, store_global, TYPE_VECTOR); vec_push(ir->extparam_protos, global); @@ -3977,10 +3977,6 @@ bool ir_builder_generate(ir_builder *self, const char *filename) #define IND_BUFSZ 1024 -#ifdef _MSC_VER -# define strncat(dst, src, sz) strncat_s(dst, sz, src, _TRUNCATE) -#endif - static const char *qc_opname(int op) { if (op < 0) return ""; @@ -4039,7 +4035,7 @@ void ir_function_dump(ir_function *f, char *ind, return; } oprintf("%sfunction %s\n", ind, f->name); - strncat(ind, "\t", IND_BUFSZ-1); + platform_strncat(ind, "\t", IND_BUFSZ-1); if (vec_size(f->locals)) { oprintf("%s%i locals:\n", ind, (int)vec_size(f->locals)); @@ -4135,7 +4131,7 @@ void ir_block_dump(ir_block* b, char *ind, { size_t i; oprintf("%s:%s\n", ind, b->label); - strncat(ind, "\t", IND_BUFSZ-1); + platform_strncat(ind, "\t", IND_BUFSZ-1); if (b->instr && b->instr[0]) oprintf("%s (%i) [entry]\n", ind, (int)(b->instr[0]->eid-1)); @@ -4169,7 +4165,7 @@ void ir_instr_dump(ir_instr *in, char *ind, return; } - strncat(ind, "\t", IND_BUFSZ-1); + platform_strncat(ind, "\t", IND_BUFSZ-1); if (in->_ops[0] && (in->_ops[1] || in->_ops[2])) { ir_value_dump(in->_ops[0], oprintf); diff --git a/lexer.c b/lexer.c index 5882bdb..2d36afb 100644 --- a/lexer.c +++ b/lexer.c @@ -1473,14 +1473,10 @@ int lex_do(lex_file *lex) lex_endtoken(lex); lex->tok.ttype = TOKEN_CHARCONST; - /* It's a vector if we can successfully scan 3 floats */ -#ifdef _MSC_VER - if (sscanf_s(lex->tok.value, " %f %f %f ", - &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3) -#else - if (sscanf(lex->tok.value, " %f %f %f ", + + /* It's a vector if we can successfully scan 3 floats */ + if (platform_sscanf(lex->tok.value, " %f %f %f ", &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3) -#endif { lex->tok.ttype = TOKEN_VECTORCONST; diff --git a/msvc.c b/msvc.c new file mode 100644 index 0000000..904ef28 --- /dev/null +++ b/msvc.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2012, 2013 + * 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" + +#define CTIME_BUFFER 64 +#define GETENV_BUFFER 4096 +#define STRERROR_BUFFER 128 + +static void **platform_mem_pool = NULL; +static void platform_mem_atexit() { + size_t i; + for (i = 0; i < vec_size(platform_mem_pool); i++) + mem_d(platform_mem_pool[i]); + vec_free(platform_mem_pool); +} + +static void *platform_mem_allocate(size_t bytes) { + void *mem = NULL; + if (!platform_mem_pool) { + atexit(&platform_mem_atexit); + vec_push(platform_mem_pool, NULL); + } + + mem = mem_a(bytes); + vec_push(platform_mem_pool, mem); + + return mem; +} + +int platform_vsnprintf(char *buffer, size_t bytes, const char *format, va_list arg) { + vsnprintf_s(buffer, bytes, bytes, format, arg); +} + +int platform_sscanf(const char *str, const char *format, ...) { + va_list va; + va_start(va, format); + vsscanf_s(str, format, va); + va_end(va); +} + +const struct tm *platform_localtime(const time_t *timer) { + struct tm *t; + t = (struct tm*)platform_mem_allocate(sizeof(struct tm)); + localtime_s(&t, timer); + return &t; +} + +const char *platform_ctime(const time_t *timer) { + char *buffer = (char *)platform_mem_allocate(CTIME_BUFFER); + ctime_s(buffer, CTIME_BUFFER, timer); + return buffer; +} + +char *platform_strncat(char *dest, const char *src, size_t num) { + return strncat_s(dest, num, src, _TRUNCATE); +} + +const char *platform_tmpnam(char *str) { + return tmpnam_s(str, L_tmpnam); +} + +const char *platform_getenv(char *var) { + char *buffer = (char *)platform_mem_allocate(GETENV_BUFFER); + size_t size; + getenv_s(&size, buffer, GETENV_BUFFER, var); + return buffer; +} + +int platform_snprintf(char *src, size_t bytes, const char *format, ...) { + int rt; + va_list va; + va_start(va, format); + + rt = vsprintf_s(src, bytes, format, va); + va_end (va); + + return rt; +} + +char *platform_strcat(char *dest, const char *src) { + strcat_s(dest, strlen(src), src); + return dest; +} + +char *platform_strncpy(char *dest, const char *src, size_t num) { + strncpy_s(dest, num, src, num); + return dest; +} + +const char *platform_strerror(int err) { + char *buffer = (char*)platform_mem_allocate(STRERROR_BUFFER); + strerror_s(buffer, STRERROR_BUFFER, err); + return buffer; +} diff --git a/opts.c b/opts.c index 27d6a56..570b578 100644 --- a/opts.c +++ b/opts.c @@ -251,7 +251,7 @@ static size_t opts_ini_parse ( /* section found */ if (*(parse_end = opts_ini_next(parse_beg + 1, ']')) == ']') { * parse_end = '\0'; /* terminate bro */ - util_strncpy(section_data, parse_beg + 1, sizeof(section_data)); + platform_strncpy(section_data, parse_beg + 1, sizeof(section_data)); section_data[sizeof(section_data) - 1] = '\0'; *oldname_data = '\0'; } else if (!error) { @@ -272,7 +272,7 @@ static size_t opts_ini_parse ( opts_ini_rstrip(read_value); /* valid name value pair, lets call down to handler */ - util_strncpy(oldname_data, read_name, sizeof(oldname_data)); + platform_strncpy(oldname_data, read_name, sizeof(oldname_data)); oldname_data[sizeof(oldname_data) - 1] ='\0'; if ((*errorhandle = loadhandle(section_data, read_name, read_value)) && !error) diff --git a/pak.c b/pak.c index 0b3f221..fbc2262 100644 --- a/pak.c +++ b/pak.c @@ -98,14 +98,14 @@ static void pak_tree_build(const char *entry) { memset(pathsplit, 0, 56); - util_strncpy(directory, entry, 56); + platform_strncpy(directory, entry, 56); for (itr = 0; (token = pak_tree_sep(&directory, "/")) != NULL; itr++) { elements[itr] = token; } for (jtr = 0; jtr < itr - 1; jtr++) { - util_strcat(pathsplit, elements[jtr]); - util_strcat(pathsplit, "/"); + platform_strcat(pathsplit, elements[jtr]); + platform_strcat(pathsplit, "/"); if (fs_dir_make(pathsplit)) { mem_d(pathsplit); @@ -366,7 +366,7 @@ static bool pak_insert_one(pak_file_t *pak, const char *file) { if (strlen(file) >= 56) goto err; - util_strncpy(dir.name, file, strlen(file)); + platform_strncpy(dir.name, file, strlen(file)); /* * Allocate some memory for loading in the data that will be diff --git a/parser.c b/parser.c index 15bb921..47563f3 100644 --- a/parser.c +++ b/parser.c @@ -4023,13 +4023,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var) varargs->expression.flags |= AST_FLAG_IS_VARARG; varargs->expression.next = (ast_expression*)ast_value_new(ast_ctx(var), NULL, TYPE_VECTOR); varargs->expression.count = 0; - util_snprintf(name, sizeof(name), "%s##va##SET", var->name); + platform_snprintf(name, sizeof(name), "%s##va##SET", var->name); if (!parser_create_array_setter_proto(parser, varargs, name)) { ast_delete(varargs); ast_block_delete(block); goto enderrfn; } - util_snprintf(name, sizeof(name), "%s##va##GET", var->name); + platform_snprintf(name, sizeof(name), "%s##va##GET", var->name); if (!parser_create_array_getter_proto(parser, varargs, varargs->expression.next, name)) { ast_delete(varargs); ast_block_delete(block); @@ -4926,10 +4926,10 @@ static bool parser_check_qualifiers(parser_t *parser, const ast_value *var, cons static bool create_array_accessors(parser_t *parser, ast_value *var) { char name[1024]; - util_snprintf(name, sizeof(name), "%s##SET", var->name); + platform_snprintf(name, sizeof(name), "%s##SET", var->name); if (!parser_create_array_setter(parser, var, name)) return false; - util_snprintf(name, sizeof(name), "%s##GET", var->name); + platform_snprintf(name, sizeof(name), "%s##GET", var->name); if (!parser_create_array_getter(parser, var, var->expression.next, name)) return false; return true; @@ -5457,14 +5457,14 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield goto cleanup; } - util_snprintf(name, sizeof(name), "%s##SETF", var->name); + platform_snprintf(name, sizeof(name), "%s##SETF", var->name); if (!parser_create_array_field_setter(parser, array, name)) goto cleanup; telem = ast_type_copy(ast_ctx(var), array->expression.next); tfield = ast_value_new(ast_ctx(var), "<.type>", TYPE_FIELD); tfield->expression.next = telem; - util_snprintf(name, sizeof(name), "%s##GETFP", var->name); + platform_snprintf(name, sizeof(name), "%s##GETFP", var->name); if (!parser_create_array_getter(parser, array, (ast_expression*)tfield, name)) { ast_delete(tfield); goto cleanup; diff --git a/test.c b/test.c index fdf3777..07ca9ca 100644 --- a/test.c +++ b/test.c @@ -162,13 +162,8 @@ static int task_pclose(FILE **handles) { char *cmd = NULL; popen_t *open = (popen_t*)mem_a(sizeof(popen_t)); -#ifndef _MSC_VER - tmpnam(open->name_err); - tmpnam(open->name_out); -#else - tmpnam_s(open->name_err, L_tmpnam); - tmpnam_s(open->name_out, L_tmpnam); -#endif + platform_tmpnam(open->name_err); + platform_tmpnam(open->name_out); (void)mode; /* excluded */ @@ -507,7 +502,7 @@ static task_template_t *task_template_compile(const char *file, const char *dir, FILE *tempfile = NULL; task_template_t *tmpl = NULL; - util_snprintf(fullfile, sizeof(fullfile), "%s/%s", dir, file); + platform_snprintf(fullfile, sizeof(fullfile), "%s/%s", dir, file); tempfile = fs_file_open(fullfile, "r"); tmpl = (task_template_t*)mem_a(sizeof(task_template_t)); @@ -717,7 +712,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { dir = fs_dir_open(directories[i]); while ((files = fs_dir_read(dir))) { - util_snprintf(buffer, sizeof(buffer), "%s/%s", directories[i], files->d_name); + platform_snprintf(buffer, sizeof(buffer), "%s/%s", directories[i], files->d_name); if (stat(buffer, &directory) == -1) { con_err("internal error: stat failed, aborting\n"); abort(); @@ -733,7 +728,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { if (strcmp(files->d_name + strlen(files->d_name) - 5, ".tmpl") == 0) { task_template_t *tmpl = task_template_compile(files->d_name, directories[i], pad); char buf[4096]; /* one page should be enough */ - char *qcflags = NULL; + const char *qcflags = NULL; task_t task; found ++; @@ -754,16 +749,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { * to test compile flags for all tests. This needs to be * BEFORE other flags (so that the .tmpl can override them) */ - #ifdef _MSC_VER - { - char buffer[4096]; - size_t size; - getenv_s(&size, buffer, sizeof(buffer), "QCFLAGS"); - qcflags = buffer; - } - #else - qcflags = getenv("QCFLAGS"); - #endif + qcflags = platform_getenv("QCFLAGS"); /* * Generate the command required to open a pipe to a process @@ -773,7 +759,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { if (strcmp(tmpl->proceduretype, "-pp")) { if (qcflags) { if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { - util_snprintf(buf, sizeof(buf), "%s %s/%s %s %s -o %s", + platform_snprintf(buf, sizeof(buf), "%s %s/%s %s %s -o %s", task_bins[TASK_COMPILE], directories[i], tmpl->sourcefile, @@ -782,7 +768,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { tmpl->tempfilename ); } else { - util_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s %s -o %s", + platform_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s %s -o %s", task_bins[TASK_COMPILE], curdir, defs, @@ -795,7 +781,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { } } else { if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { - util_snprintf(buf, sizeof(buf), "%s %s/%s %s -o %s", + platform_snprintf(buf, sizeof(buf), "%s %s/%s %s -o %s", task_bins[TASK_COMPILE], directories[i], tmpl->sourcefile, @@ -803,7 +789,7 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { tmpl->tempfilename ); } else { - util_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s -o %s", + platform_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s -o %s", task_bins[TASK_COMPILE], curdir, defs, @@ -817,14 +803,14 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { } else { /* Preprocessing (qcflags mean shit all here we don't allow them) */ if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { - util_snprintf(buf, sizeof(buf), "%s -E %s/%s -o %s", + platform_snprintf(buf, sizeof(buf), "%s -E %s/%s -o %s", task_bins[TASK_COMPILE], directories[i], tmpl->sourcefile, tmpl->tempfilename ); } else { - util_snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s -o %s", + platform_snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s -o %s", task_bins[TASK_COMPILE], curdir, defs, @@ -850,14 +836,14 @@ static bool task_propagate(const char *curdir, size_t *pad, const char *defs) { * Open up some file desciptors for logging the stdout/stderr * to our own. */ - util_snprintf(buf, sizeof(buf), "%s.stdout", tmpl->tempfilename); + platform_snprintf(buf, sizeof(buf), "%s.stdout", tmpl->tempfilename); task.stdoutlogfile = util_strdup(buf); if (!(task.stdoutlog = fs_file_open(buf, "w"))) { con_err("error opening %s for stdout\n", buf); continue; } - util_snprintf(buf, sizeof(buf), "%s.stderr", tmpl->tempfilename); + platform_snprintf(buf, sizeof(buf), "%s.stderr", tmpl->tempfilename); task.stderrlogfile = util_strdup(buf); if (!(task.stderrlog = fs_file_open(buf, "w"))) { con_err("error opening %s for stderr\n", buf); @@ -892,7 +878,7 @@ static void task_precleanup(const char *curdir) { strstr(files->d_name, ".stdout") || strstr(files->d_name, ".stderr")) { - util_snprintf(buffer, sizeof(buffer), "%s/%s", curdir, files->d_name); + platform_snprintf(buffer, sizeof(buffer), "%s/%s", curdir, files->d_name); if (remove(buffer)) con_err("error removing temporary file: %s\n", buffer); } @@ -961,12 +947,12 @@ static bool task_trymatch(size_t i, char ***line) { * actually specified. */ if (!strcmp(tmpl->executeflags, "$null")) { - util_snprintf(buffer, sizeof(buffer), "%s %s", + platform_snprintf(buffer, sizeof(buffer), "%s %s", task_bins[TASK_EXECUTE], tmpl->tempfilename ); } else { - util_snprintf(buffer, sizeof(buffer), "%s %s %s", + platform_snprintf(buffer, sizeof(buffer), "%s %s %s", task_bins[TASK_EXECUTE], tmpl->executeflags, tmpl->tempfilename @@ -1111,11 +1097,11 @@ static size_t task_schedualize(size_t *pad) { size_t j = 0; size_t failed = 0; - util_snprintf(space[0], sizeof(space[0]), "%d", (int)vec_size(task_tasks)); + platform_snprintf(space[0], sizeof(space[0]), "%d", (int)vec_size(task_tasks)); for (; i < vec_size(task_tasks); i++) { memset(space[1], 0, sizeof(space[1])); - util_snprintf(space[1], sizeof(space[1]), "%d", (int)(i + 1)); + platform_snprintf(space[1], sizeof(space[1]), "%d", (int)(i + 1)); con_out("test #%u %*s", i + 1, strlen(space[0]) - strlen(space[1]), ""); diff --git a/util.c b/util.c index 9b32e48..f454ae7 100644 --- a/util.c +++ b/util.c @@ -295,93 +295,6 @@ int util_asprintf(char **ret, const char *fmt, ...) { return read; } -/* - * These are various re-implementations (wrapping the real ones) of - * string functions that MSVC considers unsafe. We wrap these up and - * use the safe variations on MSVC. - */ -#ifdef _MSC_VER - static char **util_strerror_allocated() { - static char **data = NULL; - return data; - } - - static void util_strerror_cleanup(void) { - size_t i; - char **data = util_strerror_allocated(); - for (i = 0; i < vec_size(data); i++) - mem_d(data[i]); - vec_free(data); - } - - const char *util_strerror(int num) { - char *allocated = NULL; - static bool install = false; - static size_t tries = 0; - char **vector = util_strerror_allocated(); - - /* try installing cleanup handler */ - while (!install) { - if (tries == 32) - return "(unknown)"; - - install = !atexit(&util_strerror_cleanup); - tries ++; - } - - allocated = (char*)mem_a(4096); /* A page must be enough */ - strerror_s(allocated, 4096, num); - - vec_push(vector, allocated); - return (const char *)allocated; - } - - int util_snprintf(char *src, size_t bytes, const char *format, ...) { - int rt; - va_list va; - va_start(va, format); - - rt = vsprintf_s(src, bytes, format, va); - va_end (va); - - return rt; - } - - char *util_strcat(char *dest, const char *src) { - strcat_s(dest, strlen(src), src); - return dest; - } - - char *util_strncpy(char *dest, const char *src, size_t num) { - strncpy_s(dest, num, src, num); - return dest; - } -#else - const char *util_strerror(int num) { - return strerror(num); - } - - int util_snprintf(char *src, size_t bytes, const char *format, ...) { - int rt; - va_list va; - va_start(va, format); - rt = vsnprintf(src, bytes, format, va); - va_end (va); - - return rt; - } - - char *util_strcat(char *dest, const char *src) { - return strcat(dest, src); - } - - char *util_strncpy(char *dest, const char *src, size_t num) { - return strncpy(dest, src, num); - } - -#endif /*! _MSC_VER */ - - void util_seed(uint32_t value) { srand((int)value); }