[gtk+/wip/otte/shader: 6/69] gskslcompiler: Add support for adding defines
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 6/69] gskslcompiler: Add support for adding defines
- Date: Wed, 4 Oct 2017 00:37:42 +0000 (UTC)
commit b2ce95ce8e1c4c4d978a79e8b5e6bbb8e1c323d3
Author: Benjamin Otte <otte redhat com>
Date: Sun Sep 24 03:34:31 2017 +0200
gskslcompiler: Add support for adding defines
gtk-glsl implements this via the usual -D and -U options.
Preprocessor directives aren't implemented yet, but defines are replaced
in the source code already.
gsk/gskslcompiler.c | 130 ++++++++++++++++++++-
gsk/gskslcompiler.h | 9 ++
gsk/gskslcompilerprivate.h | 30 +++++
gsk/gsksldefine.c | 132 +++++++++++++++++++++
gsk/gsksldefineprivate.h | 51 ++++++++
gsk/gskslpreprocessor.c | 143 ++++++++++++++++-------
gsk/gsksltokenizer.c | 273 +++++++++++++++++++++++++++++++++++++++++++
gsk/gsksltokenizerprivate.h | 5 +-
gsk/meson.build | 1 +
gtk/glsl.c | 44 +++++++-
10 files changed, 769 insertions(+), 49 deletions(-)
---
diff --git a/gsk/gskslcompiler.c b/gsk/gskslcompiler.c
index 66ad1da..757867c 100644
--- a/gsk/gskslcompiler.c
+++ b/gsk/gskslcompiler.c
@@ -18,13 +18,17 @@
#include "config.h"
-#include "gskslcompiler.h"
+#include "gskslcompilerprivate.h"
+#include "gsksldefineprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprogramprivate.h"
+#include "gsksltokenizerprivate.h"
struct _GskSlCompiler {
GObject parent_instance;
+
+ GHashTable *defines;
};
G_DEFINE_TYPE (GskSlCompiler, gsk_sl_compiler, G_TYPE_OBJECT)
@@ -32,7 +36,9 @@ G_DEFINE_TYPE (GskSlCompiler, gsk_sl_compiler, G_TYPE_OBJECT)
static void
gsk_sl_compiler_dispose (GObject *object)
{
- //GskSlCompiler *compiler = GSK_SL_COMPILER (object);
+ GskSlCompiler *compiler = GSK_SL_COMPILER (object);
+
+ g_hash_table_destroy (compiler->defines);
G_OBJECT_CLASS (gsk_sl_compiler_parent_class)->dispose (object);
}
@@ -48,6 +54,8 @@ gsk_sl_compiler_class_init (GskSlCompilerClass *klass)
static void
gsk_sl_compiler_init (GskSlCompiler *compiler)
{
+ compiler->defines = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) gsk_sl_define_unref);
}
GskSlCompiler *
@@ -56,6 +64,124 @@ gsk_sl_compiler_new (void)
return g_object_new (GSK_TYPE_SL_COMPILER, NULL);
}
+static void
+gsk_sl_compiler_add_define_error_func (GskSlTokenizer *parser,
+ gboolean fatal,
+ const GskCodeLocation *location,
+ const GskSlToken *token,
+ const GError *error,
+ gpointer user_data)
+{
+ GError **real_error = user_data;
+
+ if (!fatal)
+ return;
+
+ if (*real_error)
+ return;
+
+ g_propagate_prefixed_error (real_error,
+ error,
+ "%3zu:%2zu: ",
+ location->lines + 1,
+ location->line_bytes);
+}
+
+gboolean
+gsk_sl_compiler_add_define (GskSlCompiler *compiler,
+ const char *name,
+ const char *definition,
+ GError **error)
+{
+ GskSlTokenizer *tokenizer;
+ GskSlDefine *define;
+ GskCodeLocation location;
+ GskSlToken token = { 0, };
+ GError *real_error = NULL;
+ GBytes *bytes;
+
+ g_return_val_if_fail (GSK_IS_SL_COMPILER (compiler), FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (!gsk_sl_string_is_valid_identifier (name))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Define name \"%s\" is not a valid identifier",
name);
+ return FALSE;
+ }
+
+ if (definition == NULL)
+ definition = "1";
+
+ define = gsk_sl_define_new (name, NULL);
+ bytes = g_bytes_new_static (definition, strlen (definition));
+ tokenizer = gsk_sl_tokenizer_new (bytes,
+ gsk_sl_compiler_add_define_error_func,
+ &real_error,
+ NULL);
+
+ while (TRUE)
+ {
+ do
+ {
+ gsk_sl_token_clear (&token);
+ location = *gsk_sl_tokenizer_get_location (tokenizer);
+ gsk_sl_tokenizer_read_token (tokenizer, &token);
+ }
+ while (gsk_sl_token_is_skipped (&token));
+
+ if (gsk_sl_token_is (&token, GSK_SL_TOKEN_EOF))
+ break;
+
+ gsk_sl_define_add_token (define, &location, &token);
+ }
+
+ gsk_sl_token_clear (&token);
+ gsk_sl_tokenizer_unref (tokenizer);
+ g_bytes_unref (bytes);
+
+ if (real_error == NULL)
+ {
+ g_hash_table_replace (compiler->defines, gsk_sl_define_get_name (define), define);
+ return TRUE;
+ }
+ else
+ {
+ gsk_sl_define_unref (define);
+ g_propagate_error (error, real_error);
+ return FALSE;
+ }
+}
+
+void
+gsk_sl_compiler_remove_define (GskSlCompiler *compiler,
+ const char *name)
+{
+ g_return_if_fail (GSK_IS_SL_COMPILER (compiler));
+ g_return_if_fail (name != NULL);
+
+ g_hash_table_remove (compiler->defines, name);
+}
+
+GHashTable *
+gsk_sl_compiler_copy_defines (GskSlCompiler *compiler)
+{
+ GHashTable *copy;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ copy = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) gsk_sl_define_unref);
+
+ g_hash_table_iter_init (&iter, compiler->defines);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ g_hash_table_replace (copy, key, gsk_sl_define_ref (value));
+ }
+
+ return copy;
+}
+
GskSlProgram *
gsk_sl_compiler_compile (GskSlCompiler *compiler,
GBytes *source)
diff --git a/gsk/gskslcompiler.h b/gsk/gskslcompiler.h
index 910897d..94c2763 100644
--- a/gsk/gskslcompiler.h
+++ b/gsk/gskslcompiler.h
@@ -35,6 +35,15 @@ GDK_AVAILABLE_IN_3_92
GskSlCompiler * gsk_sl_compiler_new (void);
GDK_AVAILABLE_IN_3_92
+gboolean gsk_sl_compiler_add_define (GskSlCompiler *compiler,
+ const char *name,
+ const char *definition,
+ GError **error);
+GDK_AVAILABLE_IN_3_92
+void gsk_sl_compiler_remove_define (GskSlCompiler *compiler,
+ const char *name);
+
+GDK_AVAILABLE_IN_3_92
GskSlProgram * gsk_sl_compiler_compile (GskSlCompiler *compiler,
GBytes *source);
diff --git a/gsk/gskslcompilerprivate.h b/gsk/gskslcompilerprivate.h
new file mode 100644
index 0000000..184502f
--- /dev/null
+++ b/gsk/gskslcompilerprivate.h
@@ -0,0 +1,30 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSK_SL_COMPILER_PRIVATE_H__
+#define __GSK_SL_COMPILER_PRIVATE_H__
+
+#include "gsk/gskslcompiler.h"
+
+G_BEGIN_DECLS
+
+GHashTable * gsk_sl_compiler_copy_defines (GskSlCompiler *compiler);
+
+G_END_DECLS
+
+#endif /* __GSK_SL_COMPILER_PRIVATE_H__ */
diff --git a/gsk/gsksldefine.c b/gsk/gsksldefine.c
new file mode 100644
index 0000000..c3ad56b
--- /dev/null
+++ b/gsk/gsksldefine.c
@@ -0,0 +1,132 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gsksldefineprivate.h"
+
+typedef struct _GskSlDefineToken GskSlDefineToken;
+
+struct _GskSlDefineToken {
+ GskCodeLocation location;
+ GskSlToken token;
+};
+
+struct _GskSlDefine {
+ int ref_count;
+
+ char *name;
+ GFile *source_file;
+
+ GArray *tokens;
+};
+
+GskSlDefine *
+gsk_sl_define_new (const char *name,
+ GFile *source_file)
+{
+ GskSlDefine *result;
+
+ result = g_slice_new0 (GskSlDefine);
+
+ result->ref_count = 1;
+ result->name = g_strdup (name);
+ if (source_file)
+ result->source_file = g_object_ref (source_file);
+ result->tokens = g_array_new (FALSE, FALSE, sizeof (GskSlDefineToken));
+
+ return result;
+}
+
+GskSlDefine *
+gsk_sl_define_ref (GskSlDefine *define)
+{
+ g_return_val_if_fail (define != NULL, NULL);
+
+ define->ref_count += 1;
+
+ return define;
+}
+
+void
+gsk_sl_define_unref (GskSlDefine *define)
+{
+ if (define == NULL)
+ return;
+
+ define->ref_count -= 1;
+ if (define->ref_count > 0)
+ return;
+
+ g_array_free (define->tokens, TRUE);
+
+ if (define->source_file)
+ g_object_unref (define->source_file);
+ g_free (define->name);
+
+ g_slice_free (GskSlDefine, define);
+}
+
+const char *
+gsk_sl_define_get_name (GskSlDefine *define)
+{
+ return define->name;
+}
+
+GFile *
+gsk_sl_define_get_source_file (GskSlDefine *define)
+{
+ return define->source_file;
+}
+
+guint
+gsk_sl_define_get_n_tokens (GskSlDefine *define)
+{
+ return define->tokens->len;
+}
+
+void
+gsk_sl_define_get_token (GskSlDefine *define,
+ guint i,
+ GskCodeLocation *location,
+ GskSlToken *token)
+{
+ GskSlDefineToken *dt;
+
+ dt = &g_array_index (define->tokens, GskSlDefineToken, i);
+
+ if (location)
+ *location = dt->location;
+ if (token)
+ gsk_sl_token_copy (token, &dt->token);
+}
+
+void
+gsk_sl_define_add_token (GskSlDefine *define,
+ const GskCodeLocation *location,
+ const GskSlToken *token)
+{
+ GskSlDefineToken dt;
+
+ dt.location = *location;
+ gsk_sl_token_copy (&dt.token, token);
+
+ g_array_append_val (define->tokens, dt);
+}
+
+
diff --git a/gsk/gsksldefineprivate.h b/gsk/gsksldefineprivate.h
new file mode 100644
index 0000000..92ac0db
--- /dev/null
+++ b/gsk/gsksldefineprivate.h
@@ -0,0 +1,51 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSK_SL_DEFINE_PRIVATE_H__
+#define __GSK_SL_DEFINE_PRIVATE_H__
+
+#include <glib.h>
+
+#include "gsksltokenizerprivate.h"
+#include "gsksltypesprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GskSlDefine GskSlDefine;
+
+GskSlDefine * gsk_sl_define_new (const char *name,
+ GFile *source_file);
+
+GskSlDefine * gsk_sl_define_ref (GskSlDefine *define);
+void gsk_sl_define_unref (GskSlDefine *define);
+
+const char * gsk_sl_define_get_name (GskSlDefine *define);
+GFile * gsk_sl_define_get_source_file (GskSlDefine *define);
+guint gsk_sl_define_get_n_tokens (GskSlDefine *define);
+void gsk_sl_define_get_token (GskSlDefine *define,
+ guint i,
+ GskCodeLocation *location,
+ GskSlToken *token);
+
+void gsk_sl_define_add_token (GskSlDefine *define,
+ const GskCodeLocation *location,
+ const GskSlToken *token);
+
+G_END_DECLS
+
+#endif /* __GSK_SL_DEFINE_PRIVATE_H__ */
diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c
index eec8d0b..efa154f 100644
--- a/gsk/gskslpreprocessor.c
+++ b/gsk/gskslpreprocessor.c
@@ -20,16 +20,25 @@
#include "gskslpreprocessorprivate.h"
+#include "gskslcompilerprivate.h"
+#include "gsksldefineprivate.h"
#include "gsksltokenizerprivate.h"
+typedef struct _GskSlPpToken GskSlPpToken;
+
+struct _GskSlPpToken {
+ GskCodeLocation location;
+ GskSlToken token;
+};
+
struct _GskSlPreprocessor
{
int ref_count;
GskSlCompiler *compiler;
GskSlTokenizer *tokenizer;
- GskCodeLocation location;
- GskSlToken token;
+ GArray *tokens;
+ GHashTable *defines;
};
/* API */
@@ -48,6 +57,14 @@ gsk_sl_preprocessor_error_func (GskSlTokenizer *parser,
error->message);
}
+static void
+gsk_sl_preprocessor_clear_token (gpointer data)
+{
+ GskSlPpToken *pp = data;
+
+ gsk_sl_token_clear (&pp->token);
+}
+
GskSlPreprocessor *
gsk_sl_preprocessor_new (GskSlCompiler *compiler,
GBytes *source)
@@ -62,6 +79,9 @@ gsk_sl_preprocessor_new (GskSlCompiler *compiler,
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;
}
@@ -86,35 +106,29 @@ gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc)
if (preproc->ref_count > 0)
return;
+ g_hash_table_destroy (preproc->defines);
gsk_sl_tokenizer_unref (preproc->tokenizer);
- gsk_sl_token_clear (&preproc->token);
g_object_unref (preproc->compiler);
+ g_array_free (preproc->tokens, TRUE);
g_slice_free (GskSlPreprocessor, preproc);
}
static gboolean
-gsk_sl_token_is_skipped (const GskSlToken *token)
-{
- return gsk_sl_token_is (token, GSK_SL_TOKEN_ERROR)
- || gsk_sl_token_is (token, GSK_SL_TOKEN_NEWLINE)
- || gsk_sl_token_is (token, GSK_SL_TOKEN_WHITESPACE)
- || gsk_sl_token_is (token, GSK_SL_TOKEN_COMMENT)
- || gsk_sl_token_is (token, GSK_SL_TOKEN_SINGLE_LINE_COMMENT);
-}
-
-static gboolean
-gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc)
+gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc,
+ GskSlPpToken *pp)
{
gboolean was_newline;
+ pp->token = (GskSlToken) { 0, };
+
do
{
- preproc->location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
- was_newline = gsk_sl_token_is (&preproc->token, GSK_SL_TOKEN_NEWLINE);
- gsk_sl_tokenizer_read_token (preproc->tokenizer, &preproc->token);
+ pp->location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
+ was_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 (&preproc->token));
+ while (gsk_sl_token_is_skipped (&pp->token));
return was_newline;
}
@@ -122,17 +136,23 @@ gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc)
static void
gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
{
- gboolean was_newline = gsk_sl_preprocessor_next_token (preproc);
+ GskSlPpToken pp;
+
+ gboolean was_newline = gsk_sl_preprocessor_next_token (preproc, &pp);
/* empty # line */
if (was_newline)
- return;
+ {
+ gsk_sl_preprocessor_clear_token (&pp);
+ return;
+ }
- if (gsk_sl_token_is (&preproc->token, GSK_SL_TOKEN_IDENTIFIER))
+ if (gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
{
- if (g_str_equal (preproc->token.str, "define"))
+ if (g_str_equal (pp.token.str, "define"))
{
gsk_sl_preprocessor_error (preproc, "Unknown preprocessor directive #define.");
+ gsk_sl_preprocessor_clear_token (&pp);
}
#if 0
else if (g_str_equal (preproc->token.str, "else"))
@@ -165,49 +185,89 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
else if (g_str_equal (preproc->token.str, "pragma"))
{
}
+ else if (g_str_equal (preproc->token.str, "undef"))
+ {
+ }
else if (g_str_equal (preproc->token.str, "version"))
{
}
#endif
else
{
- gsk_sl_preprocessor_error (preproc, "Unknown preprocessor directive #%s.", preproc->token.str);
+ gsk_sl_preprocessor_error (preproc, "Unknown preprocessor directive #%s.", pp.token.str);
+ gsk_sl_preprocessor_clear_token (&pp);
}
}
- else if (gsk_sl_token_is (&preproc->token, GSK_SL_TOKEN_ELSE))
- {
- gsk_sl_preprocessor_error (preproc, "Unknown preprocessor directive #else.");
- }
else
{
gsk_sl_preprocessor_error (preproc, "Missing identifier for preprocessor directive.");
+ gsk_sl_preprocessor_clear_token (&pp);
+ }
+
+ while (!gsk_sl_preprocessor_next_token (preproc, &pp))
+ gsk_sl_preprocessor_clear_token (&pp);
+}
+
+static void
+gsk_sl_preprocessor_append_token (GskSlPreprocessor *preproc,
+ GskSlPpToken *pp,
+ GSList *used_defines)
+{
+ if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ GskSlDefine *define;
+ char *ident = pp->token.str;
+
+ define = g_hash_table_lookup (preproc->defines, ident);
+ if (define &&
+ !g_slist_find (used_defines, define))
+ {
+ GSList new_defines = { define, used_defines };
+ GskSlPpToken dpp;
+ guint i;
+
+ for (i = 0; i < gsk_sl_define_get_n_tokens (define); i++)
+ {
+ gsk_sl_define_get_token (define, i, &dpp.location, &dpp.token);
+ gsk_sl_preprocessor_append_token (preproc, &dpp, &new_defines);
+ }
+
+ gsk_sl_preprocessor_clear_token (pp);
+ return;
+ }
+
+ gsk_sl_token_init_from_identifier (&pp->token, ident);
+ g_free (ident);
}
- while (!gsk_sl_preprocessor_next_token (preproc));
+ g_array_append_val (preproc->tokens, *pp);
}
static void
gsk_sl_preprocessor_ensure (GskSlPreprocessor *preproc)
{
+ GskSlPpToken pp;
gboolean was_newline = FALSE;
- if (!gsk_sl_token_is (&preproc->token, GSK_SL_TOKEN_EOF))
+ if (preproc->tokens->len > 0)
return;
- was_newline = gsk_sl_preprocessor_next_token (preproc);
+ was_newline = gsk_sl_preprocessor_next_token (preproc, &pp);
while (TRUE)
{
- if (gsk_sl_token_is (&preproc->token, GSK_SL_TOKEN_HASH))
+ if (gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_HASH))
{
if (!was_newline &&
- preproc->location.bytes != 0)
+ pp.location.bytes != 0)
{
gsk_sl_preprocessor_error (preproc, "Unexpected \"#\" - preprocessor directives must be at
start of line.");
- was_newline = gsk_sl_preprocessor_next_token (preproc);
+ gsk_sl_preprocessor_clear_token (&pp);
+ was_newline = gsk_sl_preprocessor_next_token (preproc, &pp);
}
else
{
+ gsk_sl_preprocessor_clear_token (&pp);
gsk_sl_preprocessor_handle_preprocessor_directive (preproc);
was_newline = TRUE;
}
@@ -218,12 +278,7 @@ gsk_sl_preprocessor_ensure (GskSlPreprocessor *preproc)
}
}
- if (gsk_sl_token_is (&preproc->token, GSK_SL_TOKEN_IDENTIFIER))
- {
- char *ident = preproc->token.str;
- gsk_sl_token_init_from_identifier (&preproc->token, ident);
- g_free (ident);
- }
+ gsk_sl_preprocessor_append_token (preproc, &pp, NULL);
}
const GskSlToken *
@@ -231,7 +286,7 @@ gsk_sl_preprocessor_get (GskSlPreprocessor *preproc)
{
gsk_sl_preprocessor_ensure (preproc);
- return &preproc->token;
+ return &g_array_index (preproc->tokens, GskSlPpToken, 0).token;
}
const GskCodeLocation *
@@ -239,7 +294,7 @@ gsk_sl_preprocessor_get_location (GskSlPreprocessor *preproc)
{
gsk_sl_preprocessor_ensure (preproc);
- return &preproc->location;
+ return &g_array_index (preproc->tokens, GskSlPpToken, 0).location;
}
void
@@ -248,7 +303,7 @@ gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
{
gsk_sl_preprocessor_ensure (preproc);
- gsk_sl_token_clear (&preproc->token);
+ g_array_remove_index (preproc->tokens, 0);
}
void
@@ -269,8 +324,8 @@ gsk_sl_preprocessor_error (GskSlPreprocessor *preproc,
gsk_sl_preprocessor_ensure (preproc);
gsk_sl_preprocessor_error_func (preproc->tokenizer,
TRUE,
- &preproc->location,
- &preproc->token,
+ gsk_sl_preprocessor_get_location (preproc),
+ gsk_sl_preprocessor_get (preproc),
error,
NULL);
diff --git a/gsk/gsksltokenizer.c b/gsk/gsksltokenizer.c
index 5e056ae..e5a8c5d 100644
--- a/gsk/gsksltokenizer.c
+++ b/gsk/gsksltokenizer.c
@@ -310,6 +310,252 @@ gsk_sl_token_clear (GskSlToken *token)
token->type = GSK_SL_TOKEN_EOF;
}
+void
+gsk_sl_token_copy (GskSlToken *dest,
+ const GskSlToken *src)
+{
+ dest->type = src->type;
+
+ switch (src->type)
+ {
+ case GSK_SL_TOKEN_IDENTIFIER:
+ dest->str = g_strdup (src->str);
+ break;
+
+ case GSK_SL_TOKEN_BOOLCONSTANT:
+ dest->b = src->b;
+ break;
+
+ case GSK_SL_TOKEN_FLOATCONSTANT:
+ dest->f = src->f;
+ break;
+
+ case GSK_SL_TOKEN_DOUBLECONSTANT:
+ dest->d = src->d;
+ break;
+
+ case GSK_SL_TOKEN_INTCONSTANT:
+ dest->i32 = src->i32;
+ break;
+
+ case GSK_SL_TOKEN_UINTCONSTANT:
+ dest->u32 = src->u32;
+ break;
+
+ case GSK_SL_TOKEN_EOF:
+ case GSK_SL_TOKEN_ERROR:
+ case GSK_SL_TOKEN_NEWLINE:
+ case GSK_SL_TOKEN_WHITESPACE:
+ case GSK_SL_TOKEN_COMMENT:
+ case GSK_SL_TOKEN_SINGLE_LINE_COMMENT:
+ case GSK_SL_TOKEN_CONST:
+ case GSK_SL_TOKEN_BREAK:
+ case GSK_SL_TOKEN_CONTINUE:
+ case GSK_SL_TOKEN_DO:
+ case GSK_SL_TOKEN_ELSE:
+ case GSK_SL_TOKEN_FOR:
+ case GSK_SL_TOKEN_IF:
+ case GSK_SL_TOKEN_DISCARD:
+ case GSK_SL_TOKEN_RETURN:
+ case GSK_SL_TOKEN_SWITCH:
+ case GSK_SL_TOKEN_CASE:
+ case GSK_SL_TOKEN_DEFAULT:
+ case GSK_SL_TOKEN_SUBROUTINE:
+ case GSK_SL_TOKEN_BVEC2:
+ case GSK_SL_TOKEN_BVEC3:
+ case GSK_SL_TOKEN_BVEC4:
+ case GSK_SL_TOKEN_IVEC2:
+ case GSK_SL_TOKEN_IVEC3:
+ case GSK_SL_TOKEN_IVEC4:
+ case GSK_SL_TOKEN_UVEC2:
+ case GSK_SL_TOKEN_UVEC3:
+ case GSK_SL_TOKEN_UVEC4:
+ case GSK_SL_TOKEN_VEC2:
+ case GSK_SL_TOKEN_VEC3:
+ case GSK_SL_TOKEN_VEC4:
+ case GSK_SL_TOKEN_MAT2:
+ case GSK_SL_TOKEN_MAT3:
+ case GSK_SL_TOKEN_MAT4:
+ case GSK_SL_TOKEN_CENTROID:
+ case GSK_SL_TOKEN_IN:
+ case GSK_SL_TOKEN_OUT:
+ case GSK_SL_TOKEN_INOUT:
+ case GSK_SL_TOKEN_UNIFORM:
+ case GSK_SL_TOKEN_PATCH:
+ case GSK_SL_TOKEN_SAMPLE:
+ case GSK_SL_TOKEN_BUFFER:
+ case GSK_SL_TOKEN_SHARED:
+ case GSK_SL_TOKEN_COHERENT:
+ case GSK_SL_TOKEN_VOLATILE:
+ case GSK_SL_TOKEN_RESTRICT:
+ case GSK_SL_TOKEN_READONLY:
+ case GSK_SL_TOKEN_WRITEONLY:
+ case GSK_SL_TOKEN_DVEC2:
+ case GSK_SL_TOKEN_DVEC3:
+ case GSK_SL_TOKEN_DVEC4:
+ case GSK_SL_TOKEN_DMAT2:
+ case GSK_SL_TOKEN_DMAT3:
+ case GSK_SL_TOKEN_DMAT4:
+ case GSK_SL_TOKEN_NOPERSPECTIVE:
+ case GSK_SL_TOKEN_FLAT:
+ case GSK_SL_TOKEN_SMOOTH:
+ case GSK_SL_TOKEN_LAYOUT:
+ case GSK_SL_TOKEN_MAT2X2:
+ case GSK_SL_TOKEN_MAT2X3:
+ case GSK_SL_TOKEN_MAT2X4:
+ case GSK_SL_TOKEN_MAT3X2:
+ case GSK_SL_TOKEN_MAT3X3:
+ case GSK_SL_TOKEN_MAT3X4:
+ case GSK_SL_TOKEN_MAT4X2:
+ case GSK_SL_TOKEN_MAT4X3:
+ case GSK_SL_TOKEN_MAT4X4:
+ case GSK_SL_TOKEN_DMAT2X2:
+ case GSK_SL_TOKEN_DMAT2X3:
+ case GSK_SL_TOKEN_DMAT2X4:
+ case GSK_SL_TOKEN_DMAT3X2:
+ case GSK_SL_TOKEN_DMAT3X3:
+ case GSK_SL_TOKEN_DMAT3X4:
+ case GSK_SL_TOKEN_DMAT4X2:
+ case GSK_SL_TOKEN_DMAT4X3:
+ case GSK_SL_TOKEN_DMAT4X4:
+ case GSK_SL_TOKEN_ATOMIC_UINT:
+ case GSK_SL_TOKEN_SAMPLER1D:
+ case GSK_SL_TOKEN_SAMPLER2D:
+ case GSK_SL_TOKEN_SAMPLER3D:
+ case GSK_SL_TOKEN_SAMPLERCUBE:
+ case GSK_SL_TOKEN_SAMPLER1DSHADOW:
+ case GSK_SL_TOKEN_SAMPLER2DSHADOW:
+ case GSK_SL_TOKEN_SAMPLERCUBESHADOW:
+ case GSK_SL_TOKEN_SAMPLER1DARRAY:
+ case GSK_SL_TOKEN_SAMPLER2DARRAY:
+ case GSK_SL_TOKEN_SAMPLER1DARRAYSHADOW:
+ case GSK_SL_TOKEN_SAMPLER2DARRAYSHADOW:
+ case GSK_SL_TOKEN_ISAMPLER1D:
+ case GSK_SL_TOKEN_ISAMPLER2D:
+ case GSK_SL_TOKEN_ISAMPLER3D:
+ case GSK_SL_TOKEN_ISAMPLERCUBE:
+ case GSK_SL_TOKEN_ISAMPLER1DARRAY:
+ case GSK_SL_TOKEN_ISAMPLER2DARRAY:
+ case GSK_SL_TOKEN_USAMPLER1D:
+ case GSK_SL_TOKEN_USAMPLER2D:
+ case GSK_SL_TOKEN_USAMPLER3D:
+ case GSK_SL_TOKEN_USAMPLERCUBE:
+ case GSK_SL_TOKEN_USAMPLER1DARRAY:
+ case GSK_SL_TOKEN_USAMPLER2DARRAY:
+ case GSK_SL_TOKEN_SAMPLER2DRECT:
+ case GSK_SL_TOKEN_SAMPLER2DRECTSHADOW:
+ case GSK_SL_TOKEN_ISAMPLER2DRECT:
+ case GSK_SL_TOKEN_USAMPLER2DRECT:
+ case GSK_SL_TOKEN_SAMPLERBUFFER:
+ case GSK_SL_TOKEN_ISAMPLERBUFFER:
+ case GSK_SL_TOKEN_USAMPLERBUFFER:
+ case GSK_SL_TOKEN_SAMPLERCUBEARRAY:
+ case GSK_SL_TOKEN_SAMPLERCUBEARRAYSHADOW:
+ case GSK_SL_TOKEN_ISAMPLERCUBEARRAY:
+ case GSK_SL_TOKEN_USAMPLERCUBEARRAY:
+ case GSK_SL_TOKEN_SAMPLER2DMS:
+ case GSK_SL_TOKEN_ISAMPLER2DMS:
+ case GSK_SL_TOKEN_USAMPLER2DMS:
+ case GSK_SL_TOKEN_SAMPLER2DMSARRAY:
+ case GSK_SL_TOKEN_ISAMPLER2DMSARRAY:
+ case GSK_SL_TOKEN_USAMPLER2DMSARRAY:
+ case GSK_SL_TOKEN_IMAGE1D:
+ case GSK_SL_TOKEN_IIMAGE1D:
+ case GSK_SL_TOKEN_UIMAGE1D:
+ case GSK_SL_TOKEN_IMAGE2D:
+ case GSK_SL_TOKEN_IIMAGE2D:
+ case GSK_SL_TOKEN_UIMAGE2D:
+ case GSK_SL_TOKEN_IMAGE3D:
+ case GSK_SL_TOKEN_IIMAGE3D:
+ case GSK_SL_TOKEN_UIMAGE3D:
+ case GSK_SL_TOKEN_IMAGE2DRECT:
+ case GSK_SL_TOKEN_IIMAGE2DRECT:
+ case GSK_SL_TOKEN_UIMAGE2DRECT:
+ case GSK_SL_TOKEN_IMAGECUBE:
+ case GSK_SL_TOKEN_IIMAGECUBE:
+ case GSK_SL_TOKEN_UIMAGECUBE:
+ case GSK_SL_TOKEN_IMAGEBUFFER:
+ case GSK_SL_TOKEN_IIMAGEBUFFER:
+ case GSK_SL_TOKEN_UIMAGEBUFFER:
+ case GSK_SL_TOKEN_IMAGE1DARRAY:
+ case GSK_SL_TOKEN_IIMAGE1DARRAY:
+ case GSK_SL_TOKEN_UIMAGE1DARRAY:
+ case GSK_SL_TOKEN_IMAGE2DARRAY:
+ case GSK_SL_TOKEN_IIMAGE2DARRAY:
+ case GSK_SL_TOKEN_UIMAGE2DARRAY:
+ case GSK_SL_TOKEN_IMAGECUBEARRAY:
+ case GSK_SL_TOKEN_IIMAGECUBEARRAY:
+ case GSK_SL_TOKEN_UIMAGECUBEARRAY:
+ case GSK_SL_TOKEN_IMAGE2DMS:
+ case GSK_SL_TOKEN_IIMAGE2DMS:
+ case GSK_SL_TOKEN_UIMAGE2DMS:
+ case GSK_SL_TOKEN_IMAGE2DMSARRAY:
+ case GSK_SL_TOKEN_IIMAGE2DMSARRAY:
+ case GSK_SL_TOKEN_UIMAGE2DMSARRAY:
+ case GSK_SL_TOKEN_STRUCT:
+ case GSK_SL_TOKEN_VOID:
+ case GSK_SL_TOKEN_WHILE:
+ case GSK_SL_TOKEN_FLOAT:
+ case GSK_SL_TOKEN_DOUBLE:
+ case GSK_SL_TOKEN_INT:
+ case GSK_SL_TOKEN_UINT:
+ case GSK_SL_TOKEN_BOOL:
+ case GSK_SL_TOKEN_LEFT_OP:
+ case GSK_SL_TOKEN_RIGHT_OP:
+ case GSK_SL_TOKEN_INC_OP:
+ case GSK_SL_TOKEN_DEC_OP:
+ case GSK_SL_TOKEN_LE_OP:
+ case GSK_SL_TOKEN_GE_OP:
+ case GSK_SL_TOKEN_EQ_OP:
+ case GSK_SL_TOKEN_NE_OP:
+ case GSK_SL_TOKEN_AND_OP:
+ case GSK_SL_TOKEN_OR_OP:
+ case GSK_SL_TOKEN_XOR_OP:
+ case GSK_SL_TOKEN_MUL_ASSIGN:
+ case GSK_SL_TOKEN_DIV_ASSIGN:
+ case GSK_SL_TOKEN_ADD_ASSIGN:
+ case GSK_SL_TOKEN_MOD_ASSIGN:
+ case GSK_SL_TOKEN_LEFT_ASSIGN:
+ case GSK_SL_TOKEN_RIGHT_ASSIGN:
+ case GSK_SL_TOKEN_AND_ASSIGN:
+ case GSK_SL_TOKEN_XOR_ASSIGN:
+ case GSK_SL_TOKEN_OR_ASSIGN:
+ case GSK_SL_TOKEN_SUB_ASSIGN:
+ case GSK_SL_TOKEN_LEFT_PAREN:
+ case GSK_SL_TOKEN_RIGHT_PAREN:
+ case GSK_SL_TOKEN_LEFT_BRACKET:
+ case GSK_SL_TOKEN_RIGHT_BRACKET:
+ case GSK_SL_TOKEN_LEFT_BRACE:
+ case GSK_SL_TOKEN_RIGHT_BRACE:
+ case GSK_SL_TOKEN_DOT:
+ case GSK_SL_TOKEN_COMMA:
+ case GSK_SL_TOKEN_COLON:
+ case GSK_SL_TOKEN_EQUAL:
+ case GSK_SL_TOKEN_SEMICOLON:
+ case GSK_SL_TOKEN_BANG:
+ case GSK_SL_TOKEN_DASH:
+ case GSK_SL_TOKEN_TILDE:
+ case GSK_SL_TOKEN_PLUS:
+ case GSK_SL_TOKEN_STAR:
+ case GSK_SL_TOKEN_SLASH:
+ case GSK_SL_TOKEN_PERCENT:
+ case GSK_SL_TOKEN_LEFT_ANGLE:
+ case GSK_SL_TOKEN_RIGHT_ANGLE:
+ case GSK_SL_TOKEN_VERTICAL_BAR:
+ case GSK_SL_TOKEN_CARET:
+ case GSK_SL_TOKEN_AMPERSAND:
+ case GSK_SL_TOKEN_QUESTION:
+ case GSK_SL_TOKEN_HASH:
+ case GSK_SL_TOKEN_INVARIANT:
+ case GSK_SL_TOKEN_PRECISE:
+ case GSK_SL_TOKEN_HIGH_PRECISION:
+ case GSK_SL_TOKEN_MEDIUM_PRECISION:
+ case GSK_SL_TOKEN_LOW_PRECISION:
+ case GSK_SL_TOKEN_PRECISION:
+ break;
+ }
+}
+
static const char *keywords[] = {
[GSK_SL_TOKEN_CONST] = "const",
[GSK_SL_TOKEN_BOOL] = "bool",
@@ -1480,6 +1726,23 @@ gsk_sl_token_reader_read_identifier (GskSlTokenReader *reader,
token->str = g_string_free (string, FALSE);
}
+gboolean
+gsk_sl_string_is_valid_identifier (const char *ident)
+{
+ guint i;
+
+ if (!is_identifier_start (ident[0]))
+ return FALSE;
+
+ for (i = 1; ident[i]; i++)
+ {
+ if (!is_identifier (ident[i]))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
void
gsk_sl_token_init_from_identifier (GskSlToken *token,
const char *ident)
@@ -1514,6 +1777,16 @@ gsk_sl_token_init_from_identifier (GskSlToken *token,
token->str = g_strdup (ident);
}
+gboolean
+gsk_sl_token_is_skipped (const GskSlToken *token)
+{
+ return gsk_sl_token_is (token, GSK_SL_TOKEN_ERROR)
+ || gsk_sl_token_is (token, GSK_SL_TOKEN_NEWLINE)
+ || gsk_sl_token_is (token, GSK_SL_TOKEN_WHITESPACE)
+ || gsk_sl_token_is (token, GSK_SL_TOKEN_COMMENT)
+ || gsk_sl_token_is (token, GSK_SL_TOKEN_SINGLE_LINE_COMMENT);
+}
+
void
gsk_sl_tokenizer_read_token (GskSlTokenizer *tokenizer,
GskSlToken *token)
diff --git a/gsk/gsksltokenizerprivate.h b/gsk/gsksltokenizerprivate.h
index f39e64f..e968d31 100644
--- a/gsk/gsksltokenizerprivate.h
+++ b/gsk/gsksltokenizerprivate.h
@@ -265,11 +265,14 @@ struct _GskSlToken {
};
void gsk_sl_token_clear (GskSlToken *token);
+void gsk_sl_token_copy (GskSlToken *dest,
+ const GskSlToken *src);
+gboolean gsk_sl_string_is_valid_identifier (const char *ident);
void gsk_sl_token_init_from_identifier (GskSlToken *token,
const char *ident);
-gboolean gsk_sl_token_is_finite (const GskSlToken *token);
+gboolean gsk_sl_token_is_skipped (const GskSlToken *token);
#define gsk_sl_token_is(token, _type) ((token)->type == (_type))
gboolean gsk_sl_token_is_ident (const GskSlToken *token,
const char *ident);
diff --git a/gsk/meson.build b/gsk/meson.build
index 17b82cc..292b67f 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -34,6 +34,7 @@ gsk_private_sources = files([
'gskprivate.c',
'gskprofiler.c',
'gskshaderbuilder.c',
+ 'gsksldefine.c',
'gskslfunction.c',
'gskslnode.c',
'gskslpreprocessor.c',
diff --git a/gtk/glsl.c b/gtk/glsl.c
index fcb9a56..c698521 100644
--- a/gtk/glsl.c
+++ b/gtk/glsl.c
@@ -132,6 +132,41 @@ usage (GOptionContext *ctx)
exit (EXIT_FAILURE);
}
+static gboolean
+define (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ GskSlCompiler *compiler = data;
+ char **tokens;
+ gboolean result;
+
+ tokens = g_strsplit (value, "=", 2);
+
+ result = gsk_sl_compiler_add_define (compiler,
+ tokens[0],
+ tokens[1],
+ error);
+
+ g_strfreev (tokens);
+
+ return result;
+}
+
+static gboolean
+undefine (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ GskSlCompiler *compiler = data;
+
+ gsk_sl_compiler_remove_define (compiler, value);
+
+ return TRUE;
+}
+
int
main (int argc, char *argv[])
{
@@ -139,13 +174,16 @@ main (int argc, char *argv[])
char **filenames = NULL;
char *output_file = NULL;
gboolean print = FALSE;
- GskSlCompiler *compiler;
const GOptionEntry entries[] = {
+ { "define", 'D', 0, G_OPTION_ARG_CALLBACK, define, "Add a preprocssor definition", "NAME[=VALUE]" },
+ { "undef", 'U', 0, G_OPTION_ARG_CALLBACK, undefine, "Cancel previous preprocessor definition", "NAME" },
{ "print", 'p', 0, G_OPTION_ARG_NONE, &print, "Print instead of compiling", NULL },
{ "output", 'o', 0, G_OPTION_ARG_FILENAME, &output_file, "Output filename", "FILE" },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, "List of input files", "FILE
[FILE...]" },
{ NULL, }
};
+ GskSlCompiler *compiler;
+ GOptionGroup *group;
GError *error = NULL;
GOutputStream *output;
gboolean success = TRUE;
@@ -157,7 +195,9 @@ main (int argc, char *argv[])
compiler = gsk_sl_compiler_new ();
ctx = g_option_context_new (NULL);
- g_option_context_add_main_entries (ctx, entries, NULL);
+ group = g_option_group_new (NULL, NULL, NULL, g_object_ref (compiler), g_object_unref);
+ g_option_group_add_entries (group, entries);
+ g_option_context_set_main_group (ctx, group);
if (!g_option_context_parse (ctx, &argc, &argv, &error))
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]