/*
* Copyright (C) 2012, 2013
* Wolfgang Bumiller
- * Dale Weiler
+ * 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
* SOFTWARE.
*/
#include <time.h>
+#include <sys/stat.h>
#include "gmqcc.h"
#include "lexer.h"
/*
* Implement the predef subsystem now. We can do this safely with the
* help of lexer contexts.
- */
+ */
static uint32_t ftepp_predef_countval = 0;
static uint32_t ftepp_predef_randval = 0;
/* __DATE__ */
char *ftepp_predef_date(lex_file *context) {
- struct tm *itime;
+ 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 */
/* get time */
time (&rtime);
+
+#ifdef _MSC_VER
+ localtime_s(itime, &rtime);
+#else
itime = localtime(&rtime);
+#endif
strftime(value, 82, "\"%b %d %Y\"", itime);
/* __TIME__ */
char *ftepp_predef_time(lex_file *context) {
- struct tm *itime;
+ 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 */
/* get time */
time (&rtime);
+
+#ifdef _MSC_VER
+ localtime_s(itime, &rtime);
+#else
itime = localtime(&rtime);
+#endif
strftime(value, 82, "\"%X\"", itime);
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);
- snprintf(value, length, "\"%s\"", context->name);
+ util_snprintf(value, length, "\"%s\"", context->name);
return value;
}
(void)context;
return value;
}
+/* __TIMESTAMP__ */
+char *ftepp_predef_timestamp(lex_file *context) {
+ struct stat finfo;
+ char *find;
+ char *value;
+ size_t size;
+ 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.
+ */
+ find = ctime(&finfo.st_mtime);
+ value = (char*)mem_a(strlen(find) + 1);
+ memcpy(&value[1], find, (size = strlen(find)) - 1);
+
+ value[0] = '"';
+ value[size] = '"';
+
+ return value;
+}
const ftepp_predef_t ftepp_predefs[FTEPP_PREDEF_COUNT] = {
{ "__LINE__", &ftepp_predef_line },
{ "__RANDOM__", &ftepp_predef_random },
{ "__RANDOM_LAST__", &ftepp_predef_randomlast },
{ "__DATE__", &ftepp_predef_date },
- { "__TIME__", &ftepp_predef_time }
+ { "__TIME__", &ftepp_predef_time },
+ { "__TIME_STAMP__", &ftepp_predef_timestamp }
};
#define ftepp_tokval(f) ((f)->lex->tok.value)
return token;
}
-static void pptoken_delete(pptoken *self)
+static GMQCC_INLINE void pptoken_delete(pptoken *self)
{
mem_d(self->value);
mem_d(self);
return ftepp;
}
-static void ftepp_flush_do(ftepp_t *self)
+static GMQCC_INLINE void ftepp_flush_do(ftepp_t *self)
{
vec_free(self->output_string);
}
if (self->includename)
vec_free(self->includename);
- /*
- for (i = 0; i < vec_size(self->macros); ++i)
- ppmacro_delete(self->macros[i]);
-
- vec_free(self->macros);
-*/
-
util_htrem(self->macros, (void (*)(void*))&ppmacro_delete);
vec_free(self->conditions);
}
}
-static void ftepp_update_output_condition(ftepp_t *ftepp)
+static GMQCC_INLINE void ftepp_update_output_condition(ftepp_t *ftepp)
{
size_t i;
ftepp->output_on = true;
ftepp->output_on = ftepp->output_on && ftepp->conditions[i].on;
}
-static ppmacro* ftepp_macro_find(ftepp_t *ftepp, const char *name)
+static GMQCC_INLINE ppmacro* ftepp_macro_find(ftepp_t *ftepp, const char *name)
{
- return util_htget(ftepp->macros, name);
+ return (ppmacro*)util_htget(ftepp->macros, name);
}
-static void ftepp_macro_delete(ftepp_t *ftepp, const char *name)
+static GMQCC_INLINE void ftepp_macro_delete(ftepp_t *ftepp, const char *name)
{
util_htrm(ftepp->macros, name, NULL);
}
if (resetline && !ftepp->in_macro) {
char lineno[128];
- snprintf(lineno, 128, "\n#pragma line(%lu)\n", (unsigned long)(old_lexer->sline));
+ util_snprintf(lineno, 128, "\n#pragma line(%lu)\n", (unsigned long)(old_lexer->sline));
ftepp_out(ftepp, lineno, false);
}
ftepp_out(ftepp, "\n#pragma file(", false);
ftepp_out(ftepp, ctx.file, false);
- snprintf(lineno, sizeof(lineno), ")\n#pragma line(%lu)\n", (unsigned long)(ctx.line+1));
+ util_snprintf(lineno, sizeof(lineno), ")\n#pragma line(%lu)\n", (unsigned long)(ctx.line+1));
ftepp_out(ftepp, lineno, false);
/* skip the line */
minor[2] = '"';
} else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_GMQCC) {
ftepp_add_define(ftepp, NULL, "__STD_GMQCC__");
- snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR);
- snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR);
+ util_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR);
+ util_snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR);
} else if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_QCCX) {
ftepp_add_define(ftepp, NULL, "__STD_QCCX__");
- snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR);
- snprintf(minor, 32, "\"%d\"", GMQCC_VERSION_MINOR);
+ util_snprintf(major, 32, "\"%d\"", GMQCC_VERSION_MAJOR);
+ util_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 */
ftepp_add_macro(ftepp, "__STD_VERSION_MINOR__", minor);
ftepp_add_macro(ftepp, "__STD_VERSION_MAJOR__", major);
+ /*
+ * We're going to just make __NULL__ nil, which works for 60% of the
+ * cases of __NULL_ for fteqcc.
+ */
+ ftepp_add_macro(ftepp, "__NULL__", "nil");
+
return ftepp;
}