Strictly speaking, the GLSL specification only allows for the '#' to appear in
a shader in two places:

        1. To introduce a pre-processing directive

           In this case, the '#' must be the first character on a line after
           ignoring any comments and horizontal whitespace.

        2. As part of the token-pasting operator

           In this case, the '#' must appear as part of the sequence "##" and
           can only appear in the replacement list of a macro definition.

Since commit f062f0506a5b827667b7eb52136d8420b7e8113b, glcpp has been strict
about '#' characters, such that any occurence outside of either of the above
two cases would result in a syntax error of "Unexpected HASH_TOKEN" from the
grammar.

(Prior to that commit, these illegal '#' would be silently ignored and printed
to stdout. And if it hadn't been for that commit, these illegal '#' would have
triggered internal errors with later commits.)

With this commit, glcpp relaxes its strictness and treats such appearances of
'#' as just another piece of punctuation. This would make it legal to do
something like:

        #define FOO # something here

and then use "#ifdef FOO" and similar, (though if FOO were ever directly
expanded, this should trigger a syntax error in the main GLSL compiler).

Relaxing strict conformance compared to GLSL seems somewhat dubious here, but
might be justified for a few reasons:

        1. GCC's preprocessor allows this, (though C is not GLSL, of course)

        2. glcpp is generally soft about illegal characters, (compare to
           non-ASCII characters which glcpp happily passes through, trusting
           the GLSL compiler to catch them).

        3. At least one game in the wild (Reactive Quake) has been observed
           with a bogus '#' in it:

                #define USE_DISCARD#line 0

           Note that the shader (that we've seen) with this line does not ever
           *use* the USE_DISCARD macro. Note also that this shader is accepted
           by both Nvidia's OpenGL implementation as well as Mesa prior to
           the commit referenced above.
---
 src/glsl/glcpp/glcpp-lex.l   | 12 +++++++-----
 src/glsl/glcpp/glcpp-parse.y |  1 +
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l
index c126850..cf517ad 100644
--- a/src/glsl/glcpp/glcpp-lex.l
+++ b/src/glsl/glcpp/glcpp-lex.l
@@ -270,15 +270,17 @@ HEXADECIMAL_INTEGER       0[xX][0-9a-fA-F]+[uU]?
 
        /* If the '#' is the first non-whitespace, non-comment token on this
         * line, then it introduces a directive, switch to the <HASH> start
-        * condition.
+        * condition and return a HASH_TOKEN token.
         *
-        * Otherwise, this is just punctuation, so return the HASH_TOKEN
-         * token. */
+        * Otherwise, this is just punctuation, so just return a literal '#'
+        * token, (which will not be interpreted as a directive).
+        */
        if (parser->first_non_space_token_this_line) {
                BEGIN HASH;
+               RETURN_TOKEN_NEVER_SKIP (HASH_TOKEN);
+       } else {
+               RETURN_TOKEN ('#');
        }
-
-       RETURN_TOKEN_NEVER_SKIP (HASH_TOKEN);
 }
 
 <HASH>version{HSPACE}+ {
diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
index 4ee4110..b281b01 100644
--- a/src/glsl/glcpp/glcpp-parse.y
+++ b/src/glsl/glcpp/glcpp-parse.y
@@ -744,6 +744,7 @@ operator:
 |      PASTE                   { $$ = PASTE; }
 |      PLUS_PLUS               { $$ = PLUS_PLUS; }
 |      MINUS_MINUS             { $$ = MINUS_MINUS; }
+|      '#'                     { $$ = '#'; }
 ;
 
 %%
-- 
2.0.0

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to