]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ftepp.c
this might fix some linenumbering, I hope
[xonotic/gmqcc.git] / ftepp.c
diff --git a/ftepp.c b/ftepp.c
index a5c50ee85544ad98dc808d44f130eb6f3fe98953..77818f8bbe1f2332796e802d7b21dbec8b45344c 100644 (file)
--- a/ftepp.c
+++ b/ftepp.c
@@ -70,11 +70,6 @@ typedef struct {
     char        *includename;
 } ftepp_t;
 
-typedef struct {
-    const char  *name;
-    char      *(*func)(lex_file *);
-} predef_t;
-
 /*
  * Implement the predef subsystem now.  We can do this safely with the
  * help of lexer contexts.
@@ -100,6 +95,24 @@ char *ftepp_predef_date(lex_file *context) {
     return value;
 }
 
+/* __TIME__ */
+char *ftepp_predef_time(lex_file *context) {
+    struct tm *itime;
+    time_t     rtime;
+    char      *value = mem_a(82);
+    /* 82 is enough for strftime but we also have " " in our string */
+
+    (void)context;
+
+    /* get time */
+    time (&rtime);
+    itime = localtime(&rtime);
+
+    strftime(value, 82, "\"%X\"", itime);
+
+    return value;
+}
+
 /* __LINE__ */
 char *ftepp_predef_line(lex_file *context) {
     char   *value;
@@ -150,14 +163,15 @@ char *ftepp_predef_randomlast(lex_file *context) {
     return value;
 }
 
-static const predef_t ftepp_predefs[] = {
+const ftepp_predef_t ftepp_predefs[FTEPP_PREDEF_COUNT] = {
     { "__LINE__",         &ftepp_predef_line        },
     { "__FILE__",         &ftepp_predef_file        },
     { "__COUNTER__",      &ftepp_predef_counter     },
     { "__COUNTER_LAST__", &ftepp_predef_counterlast },
     { "__RANDOM__",       &ftepp_predef_random      },
     { "__RANDOM_LAST__",  &ftepp_predef_randomlast  },
-    { "__DATE__",         &ftepp_predef_date        }
+    { "__DATE__",         &ftepp_predef_date        },
+    { "__TIME__",         &ftepp_predef_time        }
 };
 
 #define ftepp_tokval(f) ((f)->lex->tok.value)
@@ -620,12 +634,13 @@ static void ftepp_param_out(ftepp_t *ftepp, macroparam *param)
 }
 
 static bool ftepp_preprocess(ftepp_t *ftepp);
-static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *params)
+static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *params, bool resetline)
 {
     char     *old_string   = ftepp->output_string;
     lex_file *old_lexer    = ftepp->lex;
     size_t    vararg_start = vec_size(macro->params);
     bool      retval       = true;
+    bool      has_newlines;
     size_t    varargs;
 
     size_t    o, pi;
@@ -698,6 +713,7 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param
         }
     }
     vec_push(ftepp->output_string, 0);
+    has_newlines = (strchr(ftepp->output_string, '\n') != NULL);
     /* Now run the preprocessor recursively on this string buffer */
     /*
     printf("__________\n%s\n=========\n", ftepp->output_string);
@@ -712,7 +728,8 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param
     inlex->line = ftepp->lex->line;
     inlex->sline = ftepp->lex->sline;
     ftepp->lex = inlex;
-    ftepp_recursion_header(ftepp);
+    if (has_newlines)
+        ftepp_recursion_header(ftepp);
     if (!ftepp_preprocess(ftepp)) {
         vec_free(ftepp->lex->open_string);
         old_string = ftepp->output_string;
@@ -721,7 +738,13 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param
         goto cleanup;
     }
     vec_free(ftepp->lex->open_string);
-    ftepp_recursion_footer(ftepp);
+    if (has_newlines)
+        ftepp_recursion_footer(ftepp);
+    if (resetline) {
+        char lineno[128];
+        sprintf(lineno, "\n#pragma line(%lu)\n", old_lexer->sline);
+        ftepp_out(ftepp, lineno, false);
+    }
     old_string = ftepp->output_string;
 
 cleanup:
@@ -735,9 +758,10 @@ static bool ftepp_macro_call(ftepp_t *ftepp, ppmacro *macro)
     size_t     o;
     macroparam *params = NULL;
     bool        retval = true;
+    size_t      paramline;
 
     if (!macro->has_params) {
-        if (!ftepp_macro_expand(ftepp, macro, NULL))
+        if (!ftepp_macro_expand(ftepp, macro, NULL, false))
             return false;
         ftepp_next(ftepp);
         return true;
@@ -753,6 +777,7 @@ static bool ftepp_macro_call(ftepp_t *ftepp, ppmacro *macro)
     }
 
     ftepp_next(ftepp);
+    paramline = ftepp->lex->sline;
     if (!ftepp_macro_call_params(ftepp, &params))
         return false;
 
@@ -767,7 +792,7 @@ static bool ftepp_macro_call(ftepp_t *ftepp, ppmacro *macro)
         goto cleanup;
     }
 
-    if (!ftepp_macro_expand(ftepp, macro, params))
+    if (!ftepp_macro_expand(ftepp, macro, params, (paramline != ftepp->lex->sline)))
         retval = false;
     ftepp_next(ftepp);
 
@@ -808,6 +833,7 @@ static bool ftepp_if_value(ftepp_t *ftepp, bool *out, double *value_out)
 {
     ppmacro *macro;
     bool     wasnot = false;
+    bool     wasneg = false;
 
     if (!ftepp_skipspace(ftepp))
         return false;
@@ -819,6 +845,14 @@ static bool ftepp_if_value(ftepp_t *ftepp, bool *out, double *value_out)
             return false;
     }
 
+    if (ftepp->token == TOKEN_OPERATOR && !strcmp(ftepp_tokval(ftepp), "-"))
+    {
+        wasneg = true;
+        ftepp_next(ftepp);
+        if (!ftepp_skipspace(ftepp))
+            return false;
+    }
+
     switch (ftepp->token) {
         case TOKEN_IDENT:
         case TOKEN_TYPENAME:
@@ -875,6 +909,7 @@ static bool ftepp_if_value(ftepp_t *ftepp, bool *out, double *value_out)
             }
             break;
         case TOKEN_STRINGCONST:
+            *value_out = 0;
             *out = false;
             break;
         case TOKEN_INTCONST:
@@ -898,8 +933,12 @@ static bool ftepp_if_value(ftepp_t *ftepp, bool *out, double *value_out)
 
         default:
             ftepp_error(ftepp, "junk in #if: `%s` ...", ftepp_tokval(ftepp));
+            if (opts.debug)
+                ftepp_error(ftepp, "internal: token %i\n", ftepp->token);
             return false;
     }
+    if (wasneg)
+        *value_out = -*value_out;
     if (wasnot) {
         *out = !*out;
         *value_out = (*out ? 1 : 0);
@@ -1624,6 +1663,10 @@ bool ftepp_init()
         ftepp_add_define(NULL, "__STD_GMQCC__");
         sprintf(major, "\"%d\"", GMQCC_VERSION_MAJOR);
         sprintf(minor, "\"%d\"", GMQCC_VERSION_MINOR);
+    } else if (opts.standard == COMPILER_QCCX) {
+        ftepp_add_define(NULL, "__STD_QCCX__");
+        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 */