]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
## concatenation, -Wpreprocessor warning about redefining macros, #undef
authorWolfgang (Blub) Bumiller <blub@speed.at>
Fri, 16 Nov 2012 21:54:59 +0000 (22:54 +0100)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Fri, 16 Nov 2012 21:54:59 +0000 (22:54 +0100)
ftepp.c
main.c
opts.def

diff --git a/ftepp.c b/ftepp.c
index ba8829d9ce7a2741c7acaf87206d44ce8c6bb88d..1a2ff21f6aa69881ea148e90000ddcaefc631481 100644 (file)
--- a/ftepp.c
+++ b/ftepp.c
@@ -91,6 +91,25 @@ static void ftepp_error(ftepp_t *ftepp, const char *fmt, ...)
     va_end(ap);
 }
 
+static bool GMQCC_WARN ftepp_warn(ftepp_t *ftepp, int warntype, const char *fmt, ...)
+{
+    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_vprintmsg(lvl, ftepp->lex->tok.ctx.file, ftepp->lex->tok.ctx.line, "error", fmt, ap);
+    va_end(ap);
+    return opts_werror;
+}
+
 static pptoken *pptoken_make(ftepp_t *ftepp)
 {
     pptoken *token = (pptoken*)mem_a(sizeof(pptoken));
@@ -187,6 +206,17 @@ static ppmacro* ftepp_macro_find(ftepp_t *ftepp, const char *name)
     return NULL;
 }
 
+static void ftepp_macro_delete(ftepp_t *ftepp, const char *name)
+{
+    size_t i;
+    for (i = 0; i < vec_size(ftepp->macros); ++i) {
+        if (!strcmp(name, ftepp->macros[i]->name)) {
+            vec_remove(ftepp->macros, i, 1);
+            return;
+        }
+    }
+}
+
 static inline int ftepp_next(ftepp_t *ftepp)
 {
     return (ftepp->token = lex_do(ftepp->lex));
@@ -281,6 +311,12 @@ static bool ftepp_define(ftepp_t *ftepp)
         case TOKEN_IDENT:
         case TOKEN_TYPENAME:
         case TOKEN_KEYWORD:
+            macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp));
+            if (macro) {
+                if (ftepp_warn(ftepp, WARN_PREPROCESSOR, "redefining `%s`", ftepp_tokval(ftepp)))
+                    return false;
+                ftepp_macro_delete(ftepp, ftepp_tokval(ftepp));
+            }
             macro = ppmacro_new(ftepp_ctx(ftepp), ftepp_tokval(ftepp));
             break;
         default:
@@ -435,6 +471,14 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param
                     }
                 }
                 break;
+            case '#':
+                if (o + 1 < vec_size(macro->output) && macro->output[o+1]->token == '#') {
+                    /* raw concatenation */
+                    ++o;
+                    break;
+                }
+                ftepp_out(ftepp, "#", false);
+                break;
             case TOKEN_EOL:
                 ftepp_out(ftepp, "\n", false);
                 break;
@@ -704,14 +748,48 @@ static bool ftepp_ifdef(ftepp_t *ftepp, ppcondition *cond)
     (void)ftepp_next(ftepp);
     if (!ftepp_skipspace(ftepp))
         return false;
-    if (ftepp->token != TOKEN_EOL) {
+    /* relaxing this condition
+    if (ftepp->token != TOKEN_EOL && ftepp->token != TOKEN_EOF) {
         ftepp_error(ftepp, "stray tokens after #ifdef");
         return false;
     }
+    */
     cond->on = !!macro;
     return true;
 }
 
+/**
+ * undef is also simple
+ */
+static bool ftepp_undef(ftepp_t *ftepp)
+{
+    (void)ftepp_next(ftepp);
+    if (!ftepp_skipspace(ftepp))
+        return false;
+
+    switch (ftepp->token) {
+        case TOKEN_IDENT:
+        case TOKEN_TYPENAME:
+        case TOKEN_KEYWORD:
+            ftepp_macro_delete(ftepp, ftepp_tokval(ftepp));
+            break;
+        default:
+            ftepp_error(ftepp, "expected macro name");
+            return false;
+    }
+
+    (void)ftepp_next(ftepp);
+    if (!ftepp_skipspace(ftepp))
+        return false;
+    /* relaxing this condition
+    if (ftepp->token != TOKEN_EOL && ftepp->token != TOKEN_EOF) {
+        ftepp_error(ftepp, "stray tokens after #ifdef");
+        return false;
+    }
+    */
+    return true;
+}
+
 /* Basic structure handlers */
 static bool ftepp_else_allowed(ftepp_t *ftepp)
 {
@@ -743,6 +821,9 @@ static bool ftepp_hash(ftepp_t *ftepp)
             if (!strcmp(ftepp_tokval(ftepp), "define")) {
                 return ftepp_define(ftepp);
             }
+            else if (!strcmp(ftepp_tokval(ftepp), "undef")) {
+                return ftepp_undef(ftepp);
+            }
             else if (!strcmp(ftepp_tokval(ftepp), "ifdef")) {
                 if (!ftepp_ifdef(ftepp, &cond))
                     return false;
diff --git a/main.c b/main.c
index ba4cba0ca825a27273a13a62fa0d521ccef0df3b..1c11b27f70cfb675568a4b0cb5040f2287baefbf 100644 (file)
--- a/main.c
+++ b/main.c
@@ -435,6 +435,7 @@ int main(int argc, char **argv) {
     options_set(opts_warn, WARN_EFFECTLESS_STATEMENT, true);
     options_set(opts_warn, WARN_END_SYS_FIELDS, true);
     options_set(opts_warn, WARN_ASSIGN_FUNCTION_TYPES, true);
+    options_set(opts_warn, WARN_PREPROCESSOR, true);
 
     options_set(opts_flags, ADJUST_VECTOR_FIELDS, true);
 
index e628f43471ba9c3bec6dbb37fd114df5acb60b07..1c362d32b8983725ddfd55c271538ad5d0281a89 100644 (file)
--- a/opts.def
+++ b/opts.def
@@ -52,6 +52,7 @@
     GMQCC_DEFINE_FLAG(EFFECTLESS_STATEMENT)
     GMQCC_DEFINE_FLAG(END_SYS_FIELDS)
     GMQCC_DEFINE_FLAG(ASSIGN_FUNCTION_TYPES)
+    GMQCC_DEFINE_FLAG(PREPROCESSOR)
 #endif
 
 /* some cleanup so we don't have to */