Added tests for ifdef and ifndef
authorLukas Krickl <lukas@krickl.dev>
Sun, 12 Nov 2023 16:15:10 +0000 (17:15 +0100)
committerLukas Krickl <lukas@krickl.dev>
Sun, 12 Nov 2023 16:15:10 +0000 (17:15 +0100)
src/test.c
src/ulas.c

index 366f8249e9a9028bf94a0fc12e75b71ba77f42e6..ab04ee6eba0fb2b7d401dbd3d44447cbbe5fda08 100644 (file)
@@ -120,8 +120,23 @@ void test_preproc(void) {
       "#macro test\nnested macro $1\n#macro "
       "nested\ncontent $1\n#endmacro\nafter\nnested n1\n#endmacro\ntest t1");
 
-  assert_preproc("test defined!\n", 0,
-                 "#define test\n#ifdef test\ntest defined!\n#endif");
+  // ifdef
+  assert_preproc(
+      "before\nifdeftest defined!\nafter", 0,
+      "before\n#define test\n#ifdef test\nifdeftest defined!\n#endif\nafter");
+  assert_preproc("before\nafter", 0,
+                 "before\n#ifdef test\nifdeftest defined!\n#endif\nafter");
+  assert_preproc("ifdeftest defined!\n", -1,
+                 "#define test\n#ifdef test\nifdeftest defined!\n");
+
+  // ifndef
+  assert_preproc("before\nifndeftest defined!\nafter", 0,
+                 "before\n#ifndef test\nifndeftest defined!\n#endif\nafter");
+  assert_preproc(
+      "before\nafter", 0,
+      "before\n#define test\n#ifndef test\nifndeftest defined!\n#endif\nafter");
+  assert_preproc("ifndeftest defined!\n", -1,
+                 "#ifndef test\nifndeftest defined!\n");
 
   TESTEND("preproc");
 }
index a9b82b502ea9406c98842653f0897851d8c97c3b..24a34668ac0ddff97f5b264cba8b7197f0496604 100644 (file)
@@ -411,6 +411,11 @@ void ulas_trimend(char c, char *buf, size_t n) {
 
 int ulas_preprocline(struct ulas_preproc *pp, FILE *dst, FILE *src,
                      const char *raw_line, size_t n) {
+  /**
+   * We do use raw pointers to the line here... which is fine
+   * as long as it is never used after a recursive call to the preprocessor!
+   * never use this pointer after such a recursive call!
+   */
   char *line = ulas_preprocexpand(pp, raw_line, &n);
   const char *pline = line;
 
@@ -445,7 +450,6 @@ found:
 
   if (found_dir != ULAS_PPDIR_NONE) {
     ulas_trimend('\n', line, strlen(line));
-
     switch (found_dir) {
     case ULAS_PPDIR_DEF: {
       // next token is a name
@@ -536,6 +540,8 @@ found:
         ULASERR("Expected name for #if(n)def\n");
         return -1;
       }
+      struct ulas_ppdef *def =
+          ulas_preprocgetdef(pp, pp->tok.buf, pp->tok.maxlen);
 
       // the end of a directive should have no further tokens!
       if (ulas_preprochasstray(pp, pline, n)) {
@@ -546,14 +552,18 @@ found:
       char buf[ULAS_LINEMAX];
       memset(buf, 0, ULAS_LINEMAX);
 
-      FILE *defdst = dst;
+      FILE *defdst = NULL;
+      if ((def && found_dir == ULAS_PPDIR_IFDEF) ||
+          (!def && found_dir == ULAS_PPDIR_IFNDEF)) {
+        defdst = dst;
+      }
 
       // loop until end of line or endif
       int rc = 0;
       while ((rc = ulas_preprocnext(pp, defdst, src, buf, ULAS_LINEMAX)) > 0) {
         if (rc == ULAS_PPDIR_ENDIF) {
           // we need to clear the line buffer to now echo back
-          // the #endmacro directive
+          // the #endif directive
           pp->line.buf[0] = '\0';
           break;
         }