/*
- * Copyright (C) 2012, 2013
+ * Copyright (C) 2012, 2013, 2014
* Wolfgang Bumiller
* Dale Weiler
*
char *itemname;
char *includename;
bool in_macro;
-} ftepp_t;
-/*
- * 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;
+ uint32_t predef_countval;
+ uint32_t predef_randval;
+} ftepp_t;
/* __DATE__ */
-static char *ftepp_predef_date(lex_file *context) {
+static char *ftepp_predef_date(ftepp_t *context) {
const struct tm *itime = NULL;
char *value = (char*)mem_a(82);
time_t rtime;
}
/* __TIME__ */
-static char *ftepp_predef_time(lex_file *context) {
+static char *ftepp_predef_time(ftepp_t *context) {
const struct tm *itime = NULL;
char *value = (char*)mem_a(82);
time_t rtime;
}
/* __LINE__ */
-static char *ftepp_predef_line(lex_file *context) {
- char *value;
- util_asprintf(&value, "%d", (int)context->line);
+static char *ftepp_predef_line(ftepp_t *context) {
+ char *value;
+
+ util_asprintf(&value, "%d", (int)context->lex->line);
return value;
}
/* __FILE__ */
-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);
+static char *ftepp_predef_file(ftepp_t *context) {
+ size_t length = strlen(context->lex->name) + 3; /* two quotes and a terminator */
+ char *value = (char*)mem_a(length);
+ util_snprintf(value, length, "\"%s\"", context->lex->name);
return value;
}
/* __COUNTER_LAST__ */
-static char *ftepp_predef_counterlast(lex_file *context) {
- char *value;
- util_asprintf(&value, "%u", ftepp_predef_countval);
-
- (void)context;
+static char *ftepp_predef_counterlast(ftepp_t *context) {
+ char *value;
+ util_asprintf(&value, "%u", context->predef_countval);
return value;
}
/* __COUNTER__ */
-static char *ftepp_predef_counter(lex_file *context) {
- char *value;
- ftepp_predef_countval ++;
- util_asprintf(&value, "%u", ftepp_predef_countval);
- (void)context;
+static char *ftepp_predef_counter(ftepp_t *context) {
+ char *value;
+
+ context->predef_countval ++;
+ util_asprintf(&value, "%u", context->predef_countval);
return value;
}
/* __RANDOM__ */
-static char *ftepp_predef_random(lex_file *context) {
- char *value;
- ftepp_predef_randval = (util_rand() % 0xFF) + 1;
- util_asprintf(&value, "%u", ftepp_predef_randval);
+static char *ftepp_predef_random(ftepp_t *context) {
+ char *value;
- (void)context;
+ context->predef_randval = (util_rand() % 0xFF) + 1;
+ util_asprintf(&value, "%u", context->predef_randval);
return value;
}
/* __RANDOM_LAST__ */
-static char *ftepp_predef_randomlast(lex_file *context) {
- char *value;
- util_asprintf(&value, "%u", ftepp_predef_randval);
+static char *ftepp_predef_randomlast(ftepp_t *context) {
+ char *value;
- (void)context;
+ util_asprintf(&value, "%u", context->predef_randval);
return value;
}
/* __TIMESTAMP__ */
-static char *ftepp_predef_timestamp(lex_file *context) {
+static char *ftepp_predef_timestamp(ftepp_t *context) {
struct stat finfo;
const char *find;
char *value;
size_t size;
- if (stat(context->name, &finfo))
+ if (stat(context->lex->name, &finfo))
return util_strdup("\"<failed to determine timestamp>\"");
find = util_ctime(&finfo.st_mtime);
typedef struct {
const char *name;
- char *(*func)(lex_file *);
+ char *(*func)(ftepp_t *);
} ftepp_predef_t;
static const ftepp_predef_t ftepp_predefs[] = {
}
/* singleton because we're allowed */
-static GMQCC_INLINE char *(*ftepp_predef(const char *name))(lex_file *context) {
+static GMQCC_INLINE char *(*ftepp_predef(const char *name))(ftepp_t *context) {
size_t i = ftepp_predef_index(name);
return (i != 0) ? ftepp_predefs[i-1].func : NULL;
}
ftepp = (ftepp_t*)mem_a(sizeof(*ftepp));
memset(ftepp, 0, sizeof(*ftepp));
- ftepp->macros = util_htnew(HT_MACROS);
- ftepp->output_on = true;
+ ftepp->macros = util_htnew(HT_MACROS);
+ ftepp->output_on = true;
+ ftepp->predef_countval = 0;
+ ftepp->predef_randval = 0;
return ftepp;
}
return true;
}
+static const char *ftepp_math_constants[][2] = {
+ { "M_E", "2.7182818284590452354" }, /* e */
+ { "M_LOG2E", "1.4426950408889634074" }, /* log_2 e */
+ { "M_LOG10E", "0.43429448190325182765" }, /* log_10 e */
+ { "M_LN2", "0.69314718055994530942" }, /* log_e 2 */
+ { "M_LN10", "2.30258509299404568402" }, /* log_e 10 */
+ { "M_PI", "3.14159265358979323846" }, /* pi */
+ { "M_PI_2", "1.57079632679489661923" }, /* pi/2 */
+ { "M_PI_4", "0.78539816339744830962" }, /* pi/4 */
+ { "M_1_PI", "0.31830988618379067154" }, /* 1/pi */
+ { "M_2_PI", "0.63661977236758134308" }, /* 2/pi */
+ { "M_2_SQRTPI", "1.12837916709551257390" }, /* 2/sqrt(pi) */
+ { "M_SQRT2", "1.41421356237309504880" }, /* sqrt(2) */
+ { "M_SQRT1_2", "0.70710678118654752440" }, /* 1/sqrt(2) */
+ { "M_TAU", "6.28318530717958647692" } /* pi*2 */
+};
+
static bool ftepp_define(ftepp_t *ftepp)
{
ppmacro *macro = NULL;
size_t l = ftepp_ctx(ftepp).line;
+ size_t i;
+ bool mathconstant = false;
(void)ftepp_next(ftepp);
if (!ftepp_skipspace(ftepp))
case TOKEN_IDENT:
case TOKEN_TYPENAME:
case TOKEN_KEYWORD:
+ if (OPTS_FLAG(FTEPP_MATHDEFS)) {
+ for (i = 0; i < GMQCC_ARRAY_COUNT(ftepp_math_constants); i++) {
+ if (!strcmp(ftepp_math_constants[i][0], ftepp_tokval(ftepp))) {
+ mathconstant = true;
+ break;
+ }
+ }
+ }
+
macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp));
+
+ if (OPTS_FLAG(FTEPP_MATHDEFS)) {
+ /* user defined ones take precedence */
+ if (macro && mathconstant) {
+ ftepp_macro_delete(ftepp, ftepp_tokval(ftepp));
+ macro = NULL;
+ }
+ }
+
if (macro && ftepp->output_on) {
if (ftepp_warn(ftepp, WARN_CPP, "redefining `%s`", ftepp_tokval(ftepp)))
return false;
++ch;
}
break;
- case TOKEN_WHITE:
+ /*case TOKEN_WHITE:
ftepp_out(ftepp, " ", false);
- break;
+ break;*/
case TOKEN_EOL:
ftepp_out(ftepp, "\\n", false);
break;
ftepp_out(ftepp, "\n#pragma pop(line)\n", false);
}
+static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *params, bool resetline);
static void ftepp_param_out(ftepp_t *ftepp, macroparam *param)
{
size_t i;
out = param->tokens[i];
if (out->token == TOKEN_EOL)
ftepp_out(ftepp, "\n", false);
- else
- ftepp_out(ftepp, out->value, false);
+ else {
+ ppmacro *find = ftepp_macro_find(ftepp, out->value);
+ if (OPTS_FLAG(FTEPP_INDIRECT_EXPANSION) && find && !find->has_params)
+ ftepp_macro_expand(ftepp, find, NULL, false);
+ else
+ ftepp_out(ftepp, out->value, false);
+ }
}
}
lex_file *inlex;
bool old_inmacro;
+ bool strip = false;
int nextok;
if (nextok == '#') {
/* raw concatenation */
++o;
+ strip = true;
break;
}
if ( (nextok == TOKEN_IDENT ||
macro_params_find(macro, macro->output[o+1]->value, &pi))
{
++o;
+
ftepp_stringify(ftepp, ¶ms[pi]);
break;
}
ftepp_out(ftepp, "\n", false);
break;
default:
- ftepp_out(ftepp, out->value, false);
+ buffer = out->value;
+ #define buffer_stripable(X) ((X) == ' ' || (X) == '\t')
+ if (vec_size(macro->output) > o + 1 && macro->output[o+1]->token == '#' && buffer_stripable(*buffer))
+ buffer++;
+ if (strip) {
+ while (buffer_stripable(*buffer)) buffer++;
+ strip = false;
+ }
+ ftepp_out(ftepp, buffer, false);
break;
}
}
lex_ctx_t ctx;
char lineno[128];
char *filename;
+ char *parsename = NULL;
char *old_includename;
(void)ftepp_next(ftepp);
return false;
if (ftepp->token != TOKEN_STRINGCONST) {
- ftepp_error(ftepp, "expected filename to include");
- return false;
+ ppmacro *macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp));
+ if (macro) {
+ char *backup = ftepp->output_string;
+ ftepp->output_string = NULL;
+ if (ftepp_macro_expand(ftepp, macro, NULL, true)) {
+ parsename = util_strdup(ftepp->output_string);
+ vec_free(ftepp->output_string);
+ ftepp->output_string = backup;
+ } else {
+ ftepp->output_string = backup;
+ ftepp_error(ftepp, "expected filename to include");
+ return false;
+ }
+ } else if (OPTS_FLAG(FTEPP_PREDEFS)) {
+ /* Well it could be a predefine like __LINE__ */
+ char *(*predef)(ftepp_t*) = ftepp_predef(ftepp_tokval(ftepp));
+ if (predef) {
+ parsename = predef(ftepp);
+ } else {
+ ftepp_error(ftepp, "expected filename to include");
+ return false;
+ }
+ }
}
if (!ftepp->output_on) {
- ftepp_next(ftepp);
+ (void)ftepp_next(ftepp);
return true;
}
- ctx = ftepp_ctx(ftepp);
-
- unescape(ftepp_tokval(ftepp), ftepp_tokval(ftepp));
+ if (parsename)
+ unescape(parsename, parsename);
+ else {
+ char *tokval = ftepp_tokval(ftepp);
+ unescape(tokval, tokval);
+ parsename = util_strdup(tokval);
+ }
+ ctx = ftepp_ctx(ftepp);
ftepp_out(ftepp, "\n#pragma file(", false);
- ftepp_out(ftepp, ftepp_tokval(ftepp), false);
+ ftepp_out(ftepp, parsename, false);
ftepp_out(ftepp, ")\n#pragma line(1)\n", false);
- filename = ftepp_include_find(ftepp, ftepp_tokval(ftepp));
+ filename = ftepp_include_find(ftepp, parsename);
if (!filename) {
- ftepp_error(ftepp, "failed to open include file `%s`", ftepp_tokval(ftepp));
+ ftepp_error(ftepp, "failed to open include file `%s`", parsename);
+ mem_d(parsename);
return false;
}
+ mem_d(parsename);
inlex = lex_open(filename);
if (!inlex) {
ftepp_error(ftepp, "open failed on include file `%s`", filename);
case TOKEN_KEYWORD:
case TOKEN_IDENT:
case TOKEN_TYPENAME:
- case TOKEN_ATTRIBUTE_CLOSE:
- case TOKEN_ATTRIBUTE_OPEN:
if (!strcmp(ftepp_tokval(ftepp), "define")) {
ftepp_inmacro(ftepp, "define");
return ftepp_define(ftepp);
case TOKEN_TYPENAME:
/* is it a predef? */
if (OPTS_FLAG(FTEPP_PREDEFS)) {
- char *(*predef)(lex_file*) = ftepp_predef(ftepp_tokval(ftepp));
+ char *(*predef)(ftepp_t*) = ftepp_predef(ftepp_tokval(ftepp));
if (predef) {
- expand = predef(ftepp->lex);
+ expand = predef(ftepp);
ftepp_out (ftepp, expand, false);
ftepp_next(ftepp);
ftepp_t *ftepp;
char minor[32];
char major[32];
+ size_t i;
ftepp = ftepp_new();
if (!ftepp)
*/
ftepp_add_macro(ftepp, "__NULL__", "nil");
+ /* add all the math constants if they can be */
+ if (OPTS_FLAG(FTEPP_MATHDEFS)) {
+ for (i = 0; i < GMQCC_ARRAY_COUNT(ftepp_math_constants); i++)
+ if (!ftepp_macro_find(ftepp, ftepp_math_constants[i][0]))
+ ftepp_add_macro(ftepp, ftepp_math_constants[i][0], ftepp_math_constants[i][1]);
+ }
+
return ftepp;
}