Revert "glcpp: Rewrite line-continuation support to act globally."
authorCarl Worth <cworth@cworth.org>
Sat, 1 Dec 2012 01:17:56 +0000 (17:17 -0800)
committerCarl Worth <cworth@cworth.org>
Sat, 1 Dec 2012 01:17:56 +0000 (17:17 -0800)
This reverts commit 962a1c07b44fe500b79b3ca6806d72a432c1f055.

Further testing revealed that this commit can cause the pre-processor to enter
infinite loops. For now, simply revert this code until a cleaner,
better-tested version is available.

src/glsl/glcpp/pp.c

index 427f09ae7d373f3bcbb4a360c4ee19bc91c11c84..11b29417be262b1eb3105dcb0304c9b3f4a1e4aa 100644 (file)
@@ -70,59 +70,82 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
                                     &parser->info_log_length, "\n");
 }
 
-/* Remove any line continuation characters in the shader, (whether in
- * preprocessing directives or in GLSL code).
+/* Searches backwards for '^ *#' from a given starting point. */
+static int
+in_directive(const char *shader, const char *ptr)
+{
+       assert(ptr >= shader);
+
+       /* Search backwards for '#'. If we find a \n first, it doesn't count */
+       for (; ptr >= shader && *ptr != '#'; ptr--) {
+               if (*ptr == '\n')
+                       return 0;
+       }
+       if (ptr >= shader) {
+               /* Found '#'...look for spaces preceded by a newline */
+               for (ptr--; ptr >= shader && isblank(*ptr); ptr--);
+               // FIXME: I don't think the '\n' case can happen
+               if (ptr < shader || *ptr == '\n')
+                       return 1;
+       }
+       return 0;
+}
+
+/* Remove any line continuation characters in preprocessing directives.
+ * However, ignore any in GLSL code, as "There is no line continuation
+ * character" (1.30 page 9) in GLSL.
  */
 static char *
 remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
 {
+       int in_continued_line = 0;
+       int extra_newlines = 0;
        char *clean = ralloc_strdup(ctx, "");
-       const char *backslash, *newline;
-       int collapsed_newlines = 0;
-
-       while (true) {
-               backslash = strchr(shader, '\\');
-
-               /* If we have previously collapsed any line-continuations,
-                * then we want to insert additional newlines at the next
-                * occurrence of a newline character to avoid changing any
-                * line numbers.
-                */
-               if (collapsed_newlines) {
-                       newline = strchr(shader, '\n');
-                       if (newline &&
-                           (backslash == NULL || newline < backslash))
-                       {
-                               ralloc_strncat(&clean, shader,
-                                              newline - shader + 1);
-                               while (collapsed_newlines--)
-                                       ralloc_strcat(&clean, "\n");
-                               shader = newline + 1;
-                       }
+       const char *search_start = shader;
+       const char *newline;
+       while ((newline = strchr(search_start, '\n')) != NULL) {
+               const char *backslash = NULL;
+
+               /* # of characters preceding the newline. */
+               int n = newline - shader;
+
+               /* Find the preceding '\', if it exists */
+               if (n >= 1 && newline[-1] == '\\')
+                       backslash = newline - 1;
+               else if (n >= 2 && newline[-1] == '\r' && newline[-2] == '\\')
+                       backslash = newline - 2;
+
+               /* Double backslashes don't count (the backslash is escaped) */
+               if (backslash != NULL && backslash[-1] == '\\') {
+                       backslash = NULL;
                }
 
-               if (backslash == NULL)
-                       break;
-
-               /* At each line continuation, (backslash followed by a
-                * newline), copy all preceding text to the output, then
-                * advance the shader pointer to the character after the
-                * newline.
-                */
-               if (backslash[1] == '\n' ||
-                   (backslash[1] == '\r' && backslash[2] == '\n'))
-               {
-                       collapsed_newlines++;
-                       ralloc_strncat(&clean, shader, backslash - shader);
-                       if (backslash[1] == '\n')
-                               shader = backslash + 2;
-                       else
-                               shader = backslash + 3;
+               if (backslash != NULL) {
+                       /* We found a line continuation, but do we care? */
+                       if (!in_continued_line) {
+                               if (in_directive(shader, backslash)) {
+                                       in_continued_line = 1;
+                                       extra_newlines = 0;
+                               }
+                       }
+                       if (in_continued_line) {
+                               /* Copy everything before the \ */
+                               ralloc_strncat(&clean, shader, backslash - shader);
+                               shader = newline + 1;
+                               extra_newlines++;
+                       }
+               } else if (in_continued_line) {
+                       /* Copy everything up to and including the \n */
+                       ralloc_strncat(&clean, shader, newline - shader + 1);
+                       shader = newline + 1;
+                       /* Output extra newlines to make line numbers match */
+                       for (; extra_newlines > 0; extra_newlines--)
+                               ralloc_strcat(&clean, "\n");
+                       in_continued_line = 0;
                }
+               search_start = newline + 1;
        }
-
        ralloc_strcat(&clean, shader);
-
        return clean;
 }