X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ftepp.c;h=7969231299a00b2dd8f06bafa0d33e2c8f838bde;hb=8bce855f0b78fe2509d1c6e588cb17691229079e;hp=e677e74a49af7c48b6ea4ea7f09fef6aecd6dc58;hpb=baf69f3725f8eef6a7a34ef4c94264f7daecb9f5;p=xonotic%2Fgmqcc.git diff --git a/ftepp.c b/ftepp.c index e677e74..7969231 100644 --- a/ftepp.c +++ b/ftepp.c @@ -65,6 +65,7 @@ typedef struct { char *output_string; char *itemname; + char *includename; } ftepp_t; #define ftepp_tokval(f) ((f)->lex->tok.value) @@ -77,7 +78,7 @@ static void ftepp_errorat(ftepp_t *ftepp, lex_ctx ctx, const char *fmt, ...) ftepp->errors++; va_start(ap, fmt); - con_vprintmsg(LVL_ERROR, ctx.file, ctx.line, "error", fmt, ap); + con_cvprintmsg((void*)&ctx, LVL_ERROR, "error", fmt, ap); va_end(ap); } @@ -88,7 +89,7 @@ static void ftepp_error(ftepp_t *ftepp, const char *fmt, ...) ftepp->errors++; va_start(ap, fmt); - con_vprintmsg(LVL_ERROR, ftepp->lex->tok.ctx.file, ftepp->lex->tok.ctx.line, "error", fmt, ap); + con_cvprintmsg((void*)&ftepp->lex->tok.ctx, LVL_ERROR, "error", fmt, ap); va_end(ap); } @@ -106,7 +107,7 @@ static bool GMQCC_WARN ftepp_warn(ftepp_t *ftepp, int warntype, const char *fmt, } va_start(ap, fmt); - con_vprintmsg(lvl, ftepp->lex->tok.ctx.file, ftepp->lex->tok.ctx.line, "error", fmt, ap); + con_cvprintmsg((void*)&ftepp->lex->tok.ctx, lvl, "error", fmt, ap); va_end(ap); return opts_werror; } @@ -135,6 +136,8 @@ static void pptoken_delete(pptoken *self) static ppmacro *ppmacro_new(lex_ctx ctx, const char *name) { ppmacro *macro = (ppmacro*)mem_a(sizeof(ppmacro)); + + (void)ctx; memset(macro, 0, sizeof(*macro)); macro->name = util_strdup(name); return macro; @@ -170,6 +173,8 @@ static void ftepp_delete(ftepp_t *self) size_t i; if (self->itemname) mem_d(self->itemname); + 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); @@ -650,7 +655,17 @@ cleanup: * parameter lists on macros are errors * No mathematical calculations are executed */ -static bool ftepp_if_expr(ftepp_t *ftepp, bool *out) +static bool ftepp_if_expr(ftepp_t *ftepp, bool *out, double *value_out); +static bool ftepp_if_op(ftepp_t *ftepp) +{ + ftepp->lex->flags.noops = false; + ftepp_next(ftepp); + if (!ftepp_skipspace(ftepp)) + return false; + ftepp->lex->flags.noops = true; + return true; +} +static bool ftepp_if_value(ftepp_t *ftepp, bool *out, double *value_out) { ppmacro *macro; bool wasnot = false; @@ -702,13 +717,16 @@ static bool ftepp_if_expr(ftepp_t *ftepp, bool *out) macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp)); if (!macro || !vec_size(macro->output)) { *out = false; + *value_out = 0; } else { /* This does not expand recursively! */ switch (macro->output[0]->token) { case TOKEN_INTCONST: - *out = !!(macro->output[0]->constval.f); + *value_out = macro->output[0]->constval.i; + *out = !!(macro->output[0]->constval.i); break; case TOKEN_FLOATCONST: + *value_out = macro->output[0]->constval.f; *out = !!(macro->output[0]->constval.f); break; default: @@ -721,15 +739,17 @@ static bool ftepp_if_expr(ftepp_t *ftepp, bool *out) *out = false; break; case TOKEN_INTCONST: + *value_out = ftepp->lex->tok.constval.i; *out = !!(ftepp->lex->tok.constval.i); break; case TOKEN_FLOATCONST: + *value_out = ftepp->lex->tok.constval.f; *out = !!(ftepp->lex->tok.constval.f); break; case '(': ftepp_next(ftepp); - if (!ftepp_if_expr(ftepp, out)) + if (!ftepp_if_expr(ftepp, out, value_out)) return false; if (ftepp->token != ')') { ftepp_error(ftepp, "expected closing paren in #if expression"); @@ -738,38 +758,89 @@ static bool ftepp_if_expr(ftepp_t *ftepp, bool *out) break; default: - ftepp_error(ftepp, "junk in #if"); + ftepp_error(ftepp, "junk in #if: `%s` ...", ftepp_tokval(ftepp)); return false; } - if (wasnot) + if (wasnot) { *out = !*out; + *value_out = (*out ? 1 : 0); + } + return true; +} - ftepp->lex->flags.noops = false; - ftepp_next(ftepp); - if (!ftepp_skipspace(ftepp)) +/* +static bool ftepp_if_nextvalue(ftepp_t *ftepp, bool *out, double *value_out) +{ + if (!ftepp_next(ftepp)) return false; - ftepp->lex->flags.noops = true; + return ftepp_if_value(ftepp, out, value_out); +} +*/ - if (ftepp->token == ')') - return true; +static bool ftepp_if_expr(ftepp_t *ftepp, bool *out, double *value_out) +{ + if (!ftepp_if_value(ftepp, out, value_out)) + return false; - if (ftepp->token != TOKEN_OPERATOR) + if (!ftepp_if_op(ftepp)) + return false; + + if (ftepp->token == ')' || ftepp->token != TOKEN_OPERATOR) return true; + /* FTEQCC is all right-associative and no precedence here */ if (!strcmp(ftepp_tokval(ftepp), "&&") || !strcmp(ftepp_tokval(ftepp), "||")) { bool next = false; char opc = ftepp_tokval(ftepp)[0]; + double nextvalue; - ftepp_next(ftepp); - if (!ftepp_if_expr(ftepp, &next)) + (void)nextvalue; + if (!ftepp_next(ftepp)) + return false; + if (!ftepp_if_expr(ftepp, &next, &nextvalue)) return false; if (opc == '&') *out = *out && next; else *out = *out || next; + + *value_out = (*out ? 1 : 0); + return true; + } + else if (!strcmp(ftepp_tokval(ftepp), "==") || + !strcmp(ftepp_tokval(ftepp), "!=") || + !strcmp(ftepp_tokval(ftepp), ">=") || + !strcmp(ftepp_tokval(ftepp), "<=") || + !strcmp(ftepp_tokval(ftepp), ">") || + !strcmp(ftepp_tokval(ftepp), "<")) + { + bool next = false; + const char opc0 = ftepp_tokval(ftepp)[0]; + const char opc1 = ftepp_tokval(ftepp)[1]; + double other; + + if (!ftepp_next(ftepp)) + return false; + if (!ftepp_if_expr(ftepp, &next, &other)) + return false; + + if (opc0 == '=') + *out = (*value_out == other); + else if (opc0 == '!') + *out = (*value_out != other); + else if (opc0 == '>') { + if (opc1 == '=') *out = (*value_out >= other); + else *out = (*value_out > other); + } + else if (opc0 == '<') { + if (opc1 == '=') *out = (*value_out <= other); + else *out = (*value_out < other); + } + *value_out = (*out ? 1 : 0); + return true; } else { @@ -781,6 +852,7 @@ static bool ftepp_if_expr(ftepp_t *ftepp, bool *out) static bool ftepp_if(ftepp_t *ftepp, ppcondition *cond) { bool result = false; + double dummy = 0; memset(cond, 0, sizeof(*cond)); (void)ftepp_next(ftepp); @@ -792,7 +864,7 @@ static bool ftepp_if(ftepp_t *ftepp, ppcondition *cond) return false; } - if (!ftepp_if_expr(ftepp, &result)) + if (!ftepp_if_expr(ftepp, &result, &dummy)) return false; cond->on = result; @@ -900,29 +972,50 @@ static void unescape(const char *str, char *out) { *out = 0; } -static char *ftepp_include_find(ftepp_t *ftepp, const char *file) +static char *ftepp_include_find_path(const char *file, const char *pathfile) { - char *filename = NULL; - size_t len; + FILE *fp; + char *filename = NULL; + const char *last_slash; + size_t len; - if (ftepp->itemname) { - const char *last_slash; - last_slash = strrchr(ftepp->itemname, '/'); - if (last_slash) { - len = last_slash - ftepp->itemname; - memcpy(vec_add(filename, len), ftepp->itemname, len); + if (!pathfile) + return NULL; + + last_slash = strrchr(pathfile, '/'); + + if (last_slash) { + len = last_slash - pathfile; + memcpy(vec_add(filename, len), pathfile, len); + vec_push(filename, '/'); + } + else { + len = strlen(pathfile); + memcpy(vec_add(filename, len), pathfile, len); + if (vec_last(filename) != '/') vec_push(filename, '/'); - } - else { - len = strlen(ftepp->itemname); - memcpy(vec_add(filename, len), ftepp->itemname, len); - if (vec_last(filename) != '/') - vec_push(filename, '/'); - } } + len = strlen(file); - memcpy(vec_add(filename, len), file, len); - vec_push(filename, 0); + memcpy(vec_add(filename, len+1), file, len); + vec_last(filename) = 0; + + fp = util_fopen(filename, "rb"); + if (fp) { + fclose(fp); + return filename; + } + vec_free(filename); + return NULL; +} + +static char *ftepp_include_find(ftepp_t *ftepp, const char *file) +{ + char *filename = NULL; + + filename = ftepp_include_find_path(file, ftepp->includename); + if (!filename) + filename = ftepp_include_find_path(file, ftepp->itemname); return filename; } @@ -938,6 +1031,7 @@ static bool ftepp_include(ftepp_t *ftepp) lex_ctx ctx; char lineno[128]; char *filename; + char *old_includename; (void)ftepp_next(ftepp); if (!ftepp_skipspace(ftepp)) @@ -957,19 +1051,28 @@ static bool ftepp_include(ftepp_t *ftepp) ftepp_out(ftepp, ")\n#pragma line(1)\n", false); filename = ftepp_include_find(ftepp, ftepp_tokval(ftepp)); + if (!filename) { + ftepp_error(ftepp, "failed to open include file `%s`", ftepp_tokval(ftepp)); + return false; + } inlex = lex_open(filename); if (!inlex) { ftepp_error(ftepp, "failed to open include file `%s`", filename); vec_free(filename); return false; } - vec_free(filename); ftepp->lex = inlex; + old_includename = ftepp->includename; + ftepp->includename = filename; if (!ftepp_preprocess(ftepp)) { + vec_free(ftepp->includename); + ftepp->includename = old_includename; lex_close(ftepp->lex); ftepp->lex = old_lexer; return false; } + vec_free(ftepp->includename); + ftepp->includename = old_includename; lex_close(ftepp->lex); ftepp->lex = old_lexer; @@ -1200,6 +1303,10 @@ static bool ftepp_preprocess(ftepp_t *ftepp) } } while (!ftepp->errors && ftepp->token < TOKEN_EOF); + /* force a 0 at the end but don't count it as added to the output */ + vec_push(ftepp->output_string, 0); + vec_shrinkby(ftepp->output_string, 1); + newline = ftepp->token == TOKEN_EOF; return newline; } @@ -1212,12 +1319,12 @@ static ftepp_t *ftepp; static bool ftepp_preprocess_done() { bool retval = true; - lex_close(ftepp->lex); - ftepp->lex = NULL; if (vec_size(ftepp->conditions)) { if (ftepp_warn(ftepp, WARN_MULTIFILE_IF, "#if spanning multiple files, is this intended?")) retval = false; } + lex_close(ftepp->lex); + ftepp->lex = NULL; if (ftepp->itemname) { mem_d(ftepp->itemname); ftepp->itemname = NULL; @@ -1233,10 +1340,8 @@ bool ftepp_preprocess_file(const char *filename) con_out("failed to open file \"%s\"\n", filename); return false; } - if (!ftepp_preprocess(ftepp)) { - ftepp_delete(ftepp); + if (!ftepp_preprocess(ftepp)) return false; - } return ftepp_preprocess_done(); } @@ -1248,17 +1353,35 @@ bool ftepp_preprocess_string(const char *name, const char *str) con_out("failed to create lexer for string \"%s\"\n", name); return false; } - if (!ftepp_preprocess(ftepp)) { - ftepp_delete(ftepp); + if (!ftepp_preprocess(ftepp)) return false; - } return ftepp_preprocess_done(); } bool ftepp_init() { ftepp = ftepp_new(); - return !!ftepp; + if (!ftepp) + return false; + + /* set the right macro based on the selected standard */ + if (opts_standard == COMPILER_FTEQCC) + ftepp_add_define(NULL, "FTEQCC"); + else if (opts_standard == COMPILER_GMQCC) + ftepp_add_define(NULL, "GMQCC"); + else if (opts_standard == COMPILER_QCC) + ftepp_add_define(NULL, "QCC"); + + return true; +} + +void ftepp_add_define(const char *source, const char *name) +{ + ppmacro *macro; + lex_ctx ctx = { "__builtin__", 0 }; + ctx.file = source; + macro = ppmacro_new(ctx, name); + vec_push(ftepp->macros, macro); } const char *ftepp_get()