]> de.git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ftepp.c
when recursinve into macros copy the previous line number; fixes macros showing line...
[xonotic/gmqcc.git] / ftepp.c
diff --git a/ftepp.c b/ftepp.c
index 96c20bf4f937f7ad0d55c9050e31b6813a3ab1a3..21669a8aa6a492910c23b12dcb3d8482c4fb09a8 100644 (file)
--- a/ftepp.c
+++ b/ftepp.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012
+ * Copyright (C) 2012, 2013
  *     Wolfgang Bumiller
  *     Dale Weiler 
  *
@@ -68,6 +68,77 @@ 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.
+ */  
+static uint32_t ftepp_predef_countval = 0;
+static uint32_t ftepp_predef_randval  = 0;
+
+/* __LINE__ */
+char *ftepp_predef_line(lex_file *context) {
+    char   *value;
+    util_asprintf(&value, "%d", (int)context->line);
+    return value;
+}
+/* __FILE__ */
+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);
+    memset (value, 0, length);
+    sprintf(value, "\"%s\"", context->name);
+
+    return value;
+}
+/* __COUNTER_LAST__ */
+char *ftepp_predef_counterlast(lex_file *context) {
+    char   *value;
+    util_asprintf(&value, "%u", ftepp_predef_countval);
+
+    (void)context;
+    return value;
+}
+/* __COUNTER__ */
+char *ftepp_predef_counter(lex_file *context) {
+    char   *value;
+    ftepp_predef_countval ++;
+    util_asprintf(&value, "%u", ftepp_predef_countval);
+    (void)context;
+
+    return value;
+}
+/* __RANDOM__ */
+char *ftepp_predef_random(lex_file *context) {
+    char  *value;
+    ftepp_predef_randval = (util_rand() % 0xFF) + 1;
+    util_asprintf(&value, "%u", ftepp_predef_randval);
+
+    (void)context;
+    return value;
+}
+/* __RANDOM_LAST__ */
+char *ftepp_predef_randomlast(lex_file *context) {
+    char   *value;
+    util_asprintf(&value, "%u", ftepp_predef_randval);
+
+    (void)context;
+    return value;
+}
+
+static const predef_t ftepp_predefs[] = {
+    { "__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  },
+};
+
 #define ftepp_tokval(f) ((f)->lex->tok.value)
 #define ftepp_ctx(f)    ((f)->lex->tok.ctx)
 
@@ -163,6 +234,7 @@ static ftepp_t* ftepp_new()
 static void ftepp_delete(ftepp_t *self)
 {
     size_t i;
+    ftepp_flush(self);
     if (self->itemname)
         mem_d(self->itemname);
     if (self->includename)
@@ -575,6 +647,8 @@ static bool ftepp_macro_expand(ftepp_t *ftepp, ppmacro *macro, macroparam *param
         goto cleanup;
     }
     ftepp->output_string = old_string;
+    inlex->line = ftepp->lex->line;
+    inlex->sline = ftepp->lex->sline;
     ftepp->lex = inlex;
     ftepp_recursion_header(ftepp);
     if (!ftepp_preprocess(ftepp)) {
@@ -991,9 +1065,9 @@ static char *ftepp_include_find_path(const char *file, const char *pathfile)
     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);
@@ -1010,14 +1084,15 @@ static char *ftepp_include_find(ftepp_t *ftepp, const char *file)
     return filename;
 }
 
-static void ftepp_directive_warning(ftepp_t *ftepp) {
+static bool ftepp_directive_warning(ftepp_t *ftepp) {
     char *message = NULL;
 
     if (!ftepp_skipspace(ftepp))
-        return;
+        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) {
@@ -1025,13 +1100,13 @@ static void ftepp_directive_warning(ftepp_t *ftepp) {
             ftepp_next(ftepp);
         }
         vec_push(message, '\0');
-        (void)!!ftepp_warn(ftepp, WARN_CPP, message);
+        store = ftepp_warn(ftepp, WARN_CPP, message);
         vec_free(message);
-        return;
+        return store;
     }
 
     unescape  (ftepp_tokval(ftepp), ftepp_tokval(ftepp));
-    (void)!!ftepp_warn(ftepp, WARN_CPP, "#warning %s", ftepp_tokval(ftepp));
+    return ftepp_warn(ftepp, WARN_CPP, "#warning %s", ftepp_tokval(ftepp));
 }
 
 static void ftepp_directive_error(ftepp_t *ftepp) {
@@ -1297,6 +1372,10 @@ static bool ftepp_preprocess(ftepp_t *ftepp)
     ppmacro *macro;
     bool     newline = true;
 
+    /* predef stuff */
+    char    *expand  = NULL;
+    size_t   i;
+
     ftepp->lex->flags.preprocessing = true;
     ftepp->lex->flags.mergelines    = false;
     ftepp->lex->flags.noops         = true;
@@ -1314,10 +1393,25 @@ static bool ftepp_preprocess(ftepp_t *ftepp)
             case TOKEN_KEYWORD:
             case TOKEN_IDENT:
             case TOKEN_TYPENAME:
+                /* is it a predef? */
+                if (OPTS_FLAG(FTEPP_PREDEFS)) {
+                    for (i = 0; i < sizeof(ftepp_predefs) / sizeof (*ftepp_predefs); i++) {
+                        if (!strcmp(ftepp_predefs[i].name, ftepp_tokval(ftepp))) {
+                            expand = ftepp_predefs[i].func(ftepp->lex);
+                            ftepp_out(ftepp, expand, false);
+                            ftepp_next(ftepp); /* skip */
+
+                            mem_d(expand); /* free memory */
+                            break;
+                        }
+                    }
+                }
+
                 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);