X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ftepp.c;h=763850169675aca88781a7c2e09a145c8173b4d6;hb=f598fbeaea1a4d5a21d059b0ab21f19d1e813f77;hp=d6cdb3de37f06578dc0730b5c3a561d4623aae58;hpb=07fa97b8e741cf31f1b2dfee9d39643d99cf598e;p=xonotic%2Fgmqcc.git diff --git a/ftepp.c b/ftepp.c index d6cdb3d..7638501 100644 --- a/ftepp.c +++ b/ftepp.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2012 * Wolfgang Bumiller + * 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 @@ -55,7 +56,6 @@ typedef struct { typedef struct { lex_file *lex; int token; - bool newline; unsigned int errors; bool output_on; @@ -95,21 +95,13 @@ static void ftepp_error(ftepp_t *ftepp, const char *fmt, ...) static bool GMQCC_WARN ftepp_warn(ftepp_t *ftepp, int warntype, const char *fmt, ...) { + bool r; va_list ap; - int lvl = LVL_WARNING; - - if (!OPTS_WARN(warntype)) - return false; - - if (opts_werror) { - lvl = LVL_ERROR; - ftepp->errors++; - } va_start(ap, fmt); - con_cvprintmsg((void*)&ftepp->lex->tok.ctx, lvl, "error", fmt, ap); + r = vcompile_warning(ftepp->lex->tok.ctx, warntype, fmt, ap); va_end(ap); - return opts_werror; + return r; } static pptoken *pptoken_make(ftepp_t *ftepp) @@ -136,7 +128,7 @@ 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); @@ -225,7 +217,7 @@ static void ftepp_macro_delete(ftepp_t *ftepp, const char *name) } } -static inline int ftepp_next(ftepp_t *ftepp) +static GMQCC_INLINE int ftepp_next(ftepp_t *ftepp) { return (ftepp->token = lex_do(ftepp->lex)); } @@ -295,7 +287,6 @@ static bool ftepp_define_params(ftepp_t *ftepp, ppmacro *macro) static bool ftepp_define_body(ftepp_t *ftepp, ppmacro *macro) { pptoken *ptok; - size_t l = ftepp_ctx(ftepp).line; while (ftepp->token != TOKEN_EOL && ftepp->token < TOKEN_EOF) { ptok = pptoken_make(ftepp); vec_push(macro->output, ptok); @@ -306,14 +297,14 @@ static bool ftepp_define_body(ftepp_t *ftepp, ppmacro *macro) ftepp_error(ftepp, "unexpected junk after macro or unexpected end of file"); return false; } - for (; l < ftepp_ctx(ftepp).line; ++l) - ftepp_out(ftepp, "\n", true); return true; } static bool ftepp_define(ftepp_t *ftepp) { ppmacro *macro; + size_t l = ftepp_ctx(ftepp).line; + (void)ftepp_next(ftepp); if (!ftepp_skipspace(ftepp)) return false; @@ -354,6 +345,9 @@ static bool ftepp_define(ftepp_t *ftepp) else { ppmacro_delete(macro); } + + for (; l < ftepp_ctx(ftepp).line; ++l) + ftepp_out(ftepp, "\n", true); return true; } @@ -992,20 +986,14 @@ static char *ftepp_include_find_path(const char *file, const char *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, '/'); - } len = strlen(file); memcpy(vec_add(filename, len+1), file, len); vec_last(filename) = 0; - fp = util_fopen(filename, "rb"); + fp = file_open(filename, "rb"); if (fp) { - fclose(fp); + file_close(fp); return filename; } vec_free(filename); @@ -1022,6 +1010,55 @@ static char *ftepp_include_find(ftepp_t *ftepp, const char *file) return filename; } +static bool ftepp_directive_warning(ftepp_t *ftepp) { + char *message = NULL; + + if (!ftepp_skipspace(ftepp)) + return false; + + /* handle the odd non string constant case so it works like C */ + if (ftepp->token != TOKEN_STRINGCONST) { + bool store = false; + vec_upload(message, "#warning", 8); + ftepp_next(ftepp); + while (ftepp->token != TOKEN_EOL) { + vec_upload(message, ftepp_tokval(ftepp), strlen(ftepp_tokval(ftepp))); + ftepp_next(ftepp); + } + vec_push(message, '\0'); + store = ftepp_warn(ftepp, WARN_CPP, message); + vec_free(message); + return store; + } + + unescape (ftepp_tokval(ftepp), ftepp_tokval(ftepp)); + return ftepp_warn(ftepp, WARN_CPP, "#warning %s", ftepp_tokval(ftepp)); +} + +static void ftepp_directive_error(ftepp_t *ftepp) { + char *message = NULL; + + if (!ftepp_skipspace(ftepp)) + return; + + /* handle the odd non string constant case so it works like C */ + if (ftepp->token != TOKEN_STRINGCONST) { + vec_upload(message, "#error", 6); + ftepp_next(ftepp); + while (ftepp->token != TOKEN_EOL) { + vec_upload(message, ftepp_tokval(ftepp), strlen(ftepp_tokval(ftepp))); + ftepp_next(ftepp); + } + vec_push(message, '\0'); + ftepp_error(ftepp, message); + vec_free(message); + return; + } + + unescape (ftepp_tokval(ftepp), ftepp_tokval(ftepp)); + ftepp_error(ftepp, "#error %s", ftepp_tokval(ftepp)); +} + /** * Include a file. * FIXME: do we need/want a -I option? @@ -1060,7 +1097,7 @@ static bool ftepp_include(ftepp_t *ftepp) } inlex = lex_open(filename); if (!inlex) { - ftepp_error(ftepp, "failed to open include file `%s`", filename); + ftepp_error(ftepp, "open failed on include file `%s`", filename); vec_free(filename); return false; } @@ -1217,9 +1254,22 @@ static bool ftepp_hash(ftepp_t *ftepp) ftepp_out(ftepp, "#", false); break; } + else if (!strcmp(ftepp_tokval(ftepp), "warning")) { + ftepp_directive_warning(ftepp); + break; + } + else if (!strcmp(ftepp_tokval(ftepp), "error")) { + ftepp_directive_error(ftepp); + break; + } else { - ftepp_error(ftepp, "unrecognized preprocessor directive: `%s`", ftepp_tokval(ftepp)); - return false; + if (ftepp->output_on) { + ftepp_error(ftepp, "unrecognized preprocessor directive: `%s`", ftepp_tokval(ftepp)); + return false; + } else { + ftepp_next(ftepp); + break; + } } /* break; never reached */ default: @@ -1258,18 +1308,17 @@ static bool ftepp_preprocess(ftepp_t *ftepp) if (ftepp->token >= TOKEN_EOF) break; #if 0 - ftepp->newline = newline; - newline = false; -#else - /* For the sake of FTE compatibility... FU, really */ - ftepp->newline = newline = true; + newline = true; #endif switch (ftepp->token) { case TOKEN_KEYWORD: case TOKEN_IDENT: case TOKEN_TYPENAME: - macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp)); + if (ftepp->output_on) + macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp)); + else + macro = NULL; if (!macro) { ftepp_out(ftepp, ftepp_tokval(ftepp), false); ftepp_next(ftepp); @@ -1279,7 +1328,7 @@ static bool ftepp_preprocess(ftepp_t *ftepp) ftepp->token = TOKEN_ERROR; break; case '#': - if (!ftepp->newline) { + if (!newline) { ftepp_out(ftepp, ftepp_tokval(ftepp), false); ftepp_next(ftepp); break; @@ -1299,7 +1348,13 @@ static bool ftepp_preprocess(ftepp_t *ftepp) ftepp_out(ftepp, "\n", true); ftepp_next(ftepp); break; + case TOKEN_WHITE: + /* same as default but don't set newline=false */ + ftepp_out(ftepp, ftepp_tokval(ftepp), false); + ftepp_next(ftepp); + break; default: + newline = false; ftepp_out(ftepp, ftepp_tokval(ftepp), false); ftepp_next(ftepp); break; @@ -1310,8 +1365,7 @@ static bool ftepp_preprocess(ftepp_t *ftepp) vec_push(ftepp->output_string, 0); vec_shrinkby(ftepp->output_string, 1); - newline = ftepp->token == TOKEN_EOF; - return newline; + return (ftepp->token == TOKEN_EOF); } /* Like in parser.c - files keep the previous state so we have one global @@ -1361,20 +1415,68 @@ bool ftepp_preprocess_string(const char *name, const char *str) return ftepp_preprocess_done(); } + +void ftepp_add_macro(const char *name, const char *value) { + char *create = NULL; + + /* use saner path for empty macros */ + if (!value) { + ftepp_add_define("__builtin__", name); + return; + } + + vec_upload(create, "#define ", 8); + vec_upload(create, name, strlen(name)); + vec_push (create, ' '); + vec_upload(create, value, strlen(value)); + vec_push (create, 0); + + ftepp_preprocess_string("__builtin__", create); + vec_free (create); +} + bool ftepp_init() { + char minor[32]; + char major[32]; + ftepp = ftepp_new(); if (!ftepp) return false; + memset(minor, 0, sizeof(minor)); + memset(major, 0, sizeof(major)); + /* set the right macro based on the selected standard */ ftepp_add_define(NULL, "GMQCC"); - if (opts_standard == COMPILER_FTEQCC) + if (opts.standard == COMPILER_FTEQCC) { ftepp_add_define(NULL, "__STD_FTEQCC__"); - else if (opts_standard == COMPILER_GMQCC) + /* 1.00 */ + major[0] = '"'; + major[1] = '1'; + major[2] = '"'; + + minor[0] = '"'; + minor[1] = '0'; + minor[2] = '"'; + } else if (opts.standard == COMPILER_GMQCC) { ftepp_add_define(NULL, "__STD_GMQCC__"); - else if (opts_standard == COMPILER_QCC) + sprintf(major, "\"%d\"", GMQCC_VERSION_MAJOR); + sprintf(minor, "\"%d\"", GMQCC_VERSION_MINOR); + } else if (opts.standard == COMPILER_QCC) { ftepp_add_define(NULL, "__STD_QCC__"); + /* 1.0 */ + major[0] = '"'; + major[1] = '1'; + major[2] = '"'; + + minor[0] = '"'; + minor[1] = '0'; + minor[2] = '"'; + } + + ftepp_add_macro("__STD_VERSION_MINOR__", minor); + ftepp_add_macro("__STD_VERSION_MAJOR__", major); return true; }