Initial platform / compiler specific code refactoring.

This commit is contained in:
Dale Weiler 2013-10-11 02:39:30 -04:00
parent 14ef6a1c42
commit 151606e255
19 changed files with 304 additions and 251 deletions

View file

@ -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

84
ansi.c Normal file
View file

@ -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 <string.h>
#include <stdlib.h>
#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);
}

20
ast.c
View file

@ -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);

View file

@ -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

27
exec.c
View file

@ -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);

2
fold.c
View file

@ -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

8
fs.c
View file

@ -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);
}

65
ftepp.c
View file

@ -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("\"<failed to determine timestamp>\"");
/*
* 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 */

27
gmqcc.h
View file

@ -24,6 +24,7 @@
#ifndef GMQCC_HDR
#define GMQCC_HDR
#include <stdarg.h>
#include <time.h> /* TODO: remove this? */
#include <stdio.h> /* 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 =============================*/
/*===================================================================*/

View file

@ -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 = \

View file

@ -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;

12
ir.c
View file

@ -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 "<INVALID>";
@ -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);

10
lexer.c
View file

@ -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 ",
/* 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)
#else
if (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;

114
msvc.c Normal file
View file

@ -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;
}

4
opts.c
View file

@ -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)

8
pak.c
View file

@ -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

View file

@ -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;

52
test.c
View file

@ -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]), "");

87
util.c
View file

@ -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);
}