[gtk+/wip/otte/shader: 76/150] gskslpreprocessor: Support parsing #version



commit 60f3a0d02c472de2c920dcfc05ecd6e376df15d2
Author: Benjamin Otte <otte redhat com>
Date:   Mon Oct 2 15:17:40 2017 +0200

    gskslpreprocessor: Support parsing #version
    
    This required a lot of reorganization because we have to track if we're
    at the start of the document.
    
    On the plus side, we now parse the #version tag and if it's correctly
    used, we emit a warning that we don't support it.
    
    Aren't we awesome?

 gsk/gskenums.h          |   17 ++++
 gsk/gskslcompiler.h     |    3 +-
 gsk/gskslpreprocessor.c |  226 +++++++++++++++++++++++++++++++++--------------
 3 files changed, 179 insertions(+), 67 deletions(-)
---
diff --git a/gsk/gskenums.h b/gsk/gskenums.h
index ca9d5a8..ddca9b2 100644
--- a/gsk/gskenums.h
+++ b/gsk/gskenums.h
@@ -175,4 +175,21 @@ typedef enum {
   GSK_SERIALIZATION_INVALID_DATA
 } GskSerializationError;
 
+/**
+ * GskSlProfile:
+ * @GSK_SL_PROFILE_NONE: No profile has been selected. Behaves the same
+ *     as @GSK_SL_PROFILE_CORE.
+ * @GSK_SL_PROFILE_CORE: The OpenGL core profile
+ * @GSK_SL_PROFILE_COMPATIBILITY: The OpenGL compatibility profile
+ * @GSK_SL_PROFILE_ES: The OpenGL-ES profile
+ *
+ * Profile to use for GLSL compilation.
+ **/
+typedef enum {
+  GSK_SL_PROFILE_NONE,
+  GSK_SL_PROFILE_CORE,
+  GSK_SL_PROFILE_COMPATIBILITY,
+  GSK_SL_PROFILE_ES,
+} GskSlProfile;
+
 #endif /* __GSK_TYPES_H__ */
diff --git a/gsk/gskslcompiler.h b/gsk/gskslcompiler.h
index 58c9e3a..16c2f2e 100644
--- a/gsk/gskslcompiler.h
+++ b/gsk/gskslcompiler.h
@@ -43,7 +43,8 @@ typedef enum {
 typedef enum {
   GSK_SL_COMPILER_WARNING_CONSTANT,
   GSK_SL_COMPILER_WARNING_DEAD_CODE,
-  GSK_SL_COMPILER_WARNING_SHADOW
+  GSK_SL_COMPILER_WARNING_SHADOW,
+  GSK_SL_COMPILER_WARNING_UNIMPLEMENTED
 } GskSlCompilerWarning;
 
 #define GSK_SL_COMPILER_ERROR (gsk_sl_compiler_error_quark ())
diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c
index 98276c7..bf22097 100644
--- a/gsk/gskslpreprocessor.c
+++ b/gsk/gskslpreprocessor.c
@@ -76,27 +76,6 @@ gsk_sl_preprocessor_clear_token (gpointer data)
 }
 
 GskSlPreprocessor *
-gsk_sl_preprocessor_new (GskSlCompiler *compiler,
-                         GskCodeSource *source)
-{
-  GskSlPreprocessor *preproc;
-
-  preproc = g_slice_new0 (GskSlPreprocessor);
-
-  preproc->ref_count = 1;
-  preproc->compiler = g_object_ref (compiler);
-  preproc->tokenizer = gsk_sl_tokenizer_new (source, 
-                                             gsk_sl_preprocessor_error_func,
-                                             preproc,
-                                             NULL);
-  preproc->tokens = g_array_new (FALSE, FALSE, sizeof (GskSlPpToken));
-  g_array_set_clear_func (preproc->tokens, gsk_sl_preprocessor_clear_token);
-  preproc->defines = gsk_sl_compiler_copy_defines (compiler);
-
-  return preproc;
-}
-
-GskSlPreprocessor *
 gsk_sl_preprocessor_ref (GskSlPreprocessor *preproc)
 {
   g_return_val_if_fail (preproc != NULL, NULL);
@@ -169,6 +148,69 @@ gsk_sl_preprocessor_in_ignored_conditional (GskSlPreprocessor *preproc)
   return FALSE;
 }
 
+static void
+gsk_sl_preprocessor_handle_version (GskSlPreprocessor *preproc,
+                                    GskCodeLocation   *location,
+                                    int                version,
+                                    const char        *profile_name,
+                                    gboolean           first_token_ever)
+{
+  G_GNUC_UNUSED GskSlProfile profile;
+
+  if (version <= 0)
+    {
+      gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location, "version must be a positive number.");
+      return;
+    }
+  if (profile_name == NULL)
+    profile = GSK_SL_PROFILE_NONE;
+  else if (g_str_equal (profile_name, "core"))
+    profile = GSK_SL_PROFILE_CORE;
+  else if (g_str_equal (profile_name, "compatibility"))
+    profile = GSK_SL_PROFILE_COMPATIBILITY;
+  else if (g_str_equal (profile_name, "es"))
+    profile = GSK_SL_PROFILE_ES;
+  else
+    {
+      gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location, "Unknown #version profile \"%s\".", 
profile_name);
+      return;
+    }
+  if (!first_token_ever)
+    {
+      gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location, "#version directive must be first in 
compilation.");
+      return;
+    }
+  
+  gsk_sl_preprocessor_warn_full (preproc, UNIMPLEMENTED, location, "#version directive not supported.");
+}
+
+static gboolean
+gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc,
+                                GskSlPpToken      *pp,
+                                gboolean          *last_was_newline)
+{
+  gboolean contained_newline = FALSE;
+  
+  pp->token = (GskSlToken) { 0, };
+
+  do 
+    {
+      pp->location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
+      *last_was_newline = gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_NEWLINE);
+      contained_newline |= gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_NEWLINE);
+      gsk_sl_tokenizer_read_token (preproc->tokenizer, &pp->token);
+    }
+  while (gsk_sl_token_is_skipped (&pp->token));
+
+  return contained_newline || gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_EOF);
+}
+
+static void
+gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
+                                  GskSlPpToken      *pp,
+                                  gboolean           was_newline,
+                                  gboolean           was_start_of_document);
+
 static gboolean
 gsk_sl_preprocessor_include (GskSlPreprocessor *preproc,
                              GskSlPpToken      *pp,
@@ -176,6 +218,7 @@ gsk_sl_preprocessor_include (GskSlPreprocessor *preproc,
 {
   GskCodeSource *source;
   GError *error = NULL;
+  gboolean was_newline;
     
   source = gsk_sl_compiler_resolve_include (preproc->compiler,
                                             gsk_sl_tokenizer_get_location (preproc->tokenizer)->source,
@@ -214,36 +257,15 @@ gsk_sl_preprocessor_include (GskSlPreprocessor *preproc,
                                              gsk_sl_preprocessor_error_func,
                                              preproc,
                                              NULL);
-  return TRUE;
-}
-
-static gboolean
-gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc,
-                                GskSlPpToken      *pp,
-                                gboolean          *last_was_newline)
-{
-  gboolean contained_newline = FALSE;
-  
-  pp->token = (GskSlToken) { 0, };
 
-  do 
-    {
-      pp->location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
-      *last_was_newline = gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_NEWLINE);
-      contained_newline |= gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_NEWLINE);
-      gsk_sl_tokenizer_read_token (preproc->tokenizer, &pp->token);
-    }
-  while (gsk_sl_token_is_skipped (&pp->token));
+  /* process first token, so we can ensure it assumes a newline */
+  gsk_sl_preprocessor_next_token (preproc, pp, &was_newline);
+  gsk_sl_preprocessor_handle_token (preproc, pp, TRUE, FALSE);
 
-  return contained_newline || gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_EOF);
+  return TRUE;
 }
 
 static void
-gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
-                                  GskSlPpToken      *pp,
-                                  gboolean           was_newline);
-
-static void
 gsk_sl_preprocessor_append_token (GskSlPreprocessor *preproc,
                                   GskSlPpToken      *pp,
                                   GSList            *used_defines)
@@ -257,7 +279,7 @@ gsk_sl_preprocessor_append_token (GskSlPreprocessor *preproc,
       preproc->pending_tokenizers = g_slist_remove (preproc->pending_tokenizers, preproc->tokenizer);
       gsk_sl_preprocessor_clear_token (pp);
       gsk_sl_preprocessor_next_token (preproc, pp, &was_newline);
-      gsk_sl_preprocessor_handle_token (preproc, pp, TRUE);
+      gsk_sl_preprocessor_handle_token (preproc, pp, TRUE, FALSE);
       return;
     }
 
@@ -304,7 +326,8 @@ gsk_sl_preprocessor_append_token (GskSlPreprocessor *preproc,
 }
 
 static void
-gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
+gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc,
+                                                   gboolean           first_token_ever)
 {
   GskSlPpToken pp;
   gboolean was_newline;
@@ -312,7 +335,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
   if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
     {
       /* empty # line */
-      gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+      gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
       return;
     }
 
@@ -351,7 +374,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
             }
           else
             {
-              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
             }
           return;
         }
@@ -379,7 +402,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
             }
           else
             {
-              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
             }
           return;
         }
@@ -394,7 +417,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
           if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
             {
               gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "No variable after 
#ifdef.");
-              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
               return;
             }
           if (!gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
@@ -420,7 +443,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
                 }
               else
                 {
-                  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+                  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
                 }
               return;
             }
@@ -431,7 +454,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
           if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
             {
               gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "No variable after 
#ifndef.");
-              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
               return;
             }
           if (!gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
@@ -457,7 +480,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
                 }
               else
                 {
-                  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+                  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
                 }
               return;
             }
@@ -475,7 +498,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
           if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
             {
               gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "No variable after 
#define.");
-              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
               return;
             }
           if (!gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
@@ -499,7 +522,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
                   gsk_sl_preprocessor_clear_token (&pp);
                 }
               g_hash_table_replace (preproc->defines, (gpointer) gsk_sl_define_get_name (define), define);
-              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
               return;
             }
         }
@@ -509,7 +532,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
           if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
             {
               gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "No filename after 
#include.");
-              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
               return;
             }
           if (gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_STRING))
@@ -543,7 +566,7 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
           if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
             {
               gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "No variable after 
#undef.");
-              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
               return;
             }
           if (!gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
@@ -562,16 +585,52 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
                 }
               else
                 {
-                  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+                  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
                 }
               return;
             }
         }
-#if 0
       else if (g_str_equal (pp.token.str, "version"))
         {
+          gsk_sl_preprocessor_clear_token (&pp);
+          if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
+            {
+              gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "No version specified 
after #version.");
+              gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
+              return;
+            }
+          if (!gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_INTCONSTANT))
+            {
+              gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "Expected version 
number.");
+              gsk_sl_preprocessor_clear_token (&pp);
+            }
+          else
+            {
+              GskCodeLocation location = pp.location;
+              gint version = pp.token.i32;
+
+              gsk_sl_preprocessor_clear_token (&pp);
+              if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
+                {
+                  gsk_sl_preprocessor_handle_version (preproc, &location, version, NULL, first_token_ever);
+                  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
+                  return;
+                }
+              else if (gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
+                {
+                  gsk_sl_preprocessor_handle_version (preproc, &pp.location, version, pp.token.str, 
first_token_ever);
+                  gsk_sl_preprocessor_clear_token (&pp);
+                  if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
+                    {
+                      gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
+                      return;
+                    }
+                }
+
+              gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "Expected newline 
#version.");
+              gsk_sl_preprocessor_clear_token (&pp);
+            }
         }
-#endif
       else
         {
           gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "Unknown preprocessor 
directive #%s.", pp.token.str);
@@ -587,13 +646,14 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
   while (!gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
     gsk_sl_preprocessor_clear_token (&pp);
 
-  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+  gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
 }
 
 static void
 gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
                                   GskSlPpToken      *pp,
-                                  gboolean           was_newline)
+                                  gboolean           was_newline,
+                                  gboolean           start_of_document)
 {
   if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_HASH))
     {
@@ -605,7 +665,7 @@ gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
       else
         {
           gsk_sl_preprocessor_clear_token (pp);
-          gsk_sl_preprocessor_handle_preprocessor_directive (preproc);
+          gsk_sl_preprocessor_handle_preprocessor_directive (preproc, start_of_document);
         }
     }
   else
@@ -614,6 +674,40 @@ gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
     }
 }
 
+GskSlPreprocessor *
+gsk_sl_preprocessor_new (GskSlCompiler *compiler,
+                         GskCodeSource *source)
+{
+  GskSlPreprocessor *preproc;
+  GskSlPpToken pp;
+
+  preproc = g_slice_new0 (GskSlPreprocessor);
+
+  preproc->ref_count = 1;
+  preproc->compiler = g_object_ref (compiler);
+  preproc->tokenizer = gsk_sl_tokenizer_new (source, 
+                                             gsk_sl_preprocessor_error_func,
+                                             preproc,
+                                             NULL);
+  preproc->tokens = g_array_new (FALSE, FALSE, sizeof (GskSlPpToken));
+  g_array_set_clear_func (preproc->tokens, gsk_sl_preprocessor_clear_token);
+  preproc->defines = gsk_sl_compiler_copy_defines (compiler);
+
+  /* process the first token, so we can parse #version */
+  pp.location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
+  gsk_sl_tokenizer_read_token (preproc->tokenizer, &pp.token);
+  if (!gsk_sl_token_is_skipped (&pp.token))
+    gsk_sl_preprocessor_handle_token (preproc, &pp, TRUE, TRUE);
+  else
+    {
+      gboolean was_newline;
+      gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline);
+      gsk_sl_preprocessor_handle_token (preproc, &pp, TRUE, FALSE);
+    }
+
+  return preproc;
+}
+
 static void
 gsk_sl_preprocessor_ensure (GskSlPreprocessor *preproc)
 {
@@ -624,7 +718,7 @@ gsk_sl_preprocessor_ensure (GskSlPreprocessor *preproc)
     {
       gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline);
 
-      gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline || pp.location.bytes == 0);
+      gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]