[gtk+/wip/otte/shader: 80/176] gskslpreprocessor: Implement #include
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 80/176] gskslpreprocessor: Implement #include
- Date: Wed, 25 Oct 2017 03:23:27 +0000 (UTC)
commit 56a3471eaa01a671372ffea77441295cdb0950cb
Author: Benjamin Otte <otte redhat com>
Date: Mon Oct 2 05:26:20 2017 +0200
gskslpreprocessor: Implement #include
gsk/gskcodesource.c | 3 +-
gsk/gskslcompiler.c | 41 +++++++++++++++++++
gsk/gskslcompilerprivate.h | 6 +++
gsk/gskslpreprocessor.c | 93 +++++++++++++++++++++++++++++++++++++++++--
4 files changed, 137 insertions(+), 6 deletions(-)
---
diff --git a/gsk/gskcodesource.c b/gsk/gskcodesource.c
index 155994f..92b1cac 100644
--- a/gsk/gskcodesource.c
+++ b/gsk/gskcodesource.c
@@ -146,6 +146,7 @@ gsk_code_source_load (GskCodeSource *source,
error))
return NULL;
- return g_bytes_new_take (data, length);
+ source->bytes = g_bytes_new_take (data, length);
+ return g_bytes_ref (source->bytes);
}
diff --git a/gsk/gskslcompiler.c b/gsk/gskslcompiler.c
index aa001f3..a789ba1 100644
--- a/gsk/gskslcompiler.c
+++ b/gsk/gskslcompiler.c
@@ -189,6 +189,47 @@ gsk_sl_compiler_copy_defines (GskSlCompiler *compiler)
return copy;
}
+GskCodeSource *
+gsk_sl_compiler_resolve_include (GskSlCompiler *compiler,
+ GskCodeSource *source,
+ gboolean local,
+ const char *name,
+ GError **error)
+{
+ GskCodeSource *result;
+ GBytes *bytes;
+
+ if (local)
+ {
+ GFile *source_file = gsk_code_source_get_file (source);
+ if (source_file)
+ {
+ GFile *parent, *file;
+
+ parent = g_file_get_parent (source_file);
+ file = g_file_resolve_relative_path (parent, name);
+ result = gsk_code_source_new_for_file (file);
+ g_object_unref (parent);
+ g_object_unref (file);
+ bytes = gsk_code_source_load (result, error);
+ if (bytes)
+ {
+ g_bytes_unref (bytes);
+ return result;
+ }
+
+ g_object_unref (result);
+ }
+ }
+ else
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_EXIST,
+ "Could not resolve \"%s\" in search path.", name);
+ }
+
+ return NULL;
+}
+
static GskSlProgram *
gsk_sl_compiler_compile (GskSlCompiler *compiler,
GskCodeSource *source)
diff --git a/gsk/gskslcompilerprivate.h b/gsk/gskslcompilerprivate.h
index 184502f..32e5660 100644
--- a/gsk/gskslcompilerprivate.h
+++ b/gsk/gskslcompilerprivate.h
@@ -25,6 +25,12 @@ G_BEGIN_DECLS
GHashTable * gsk_sl_compiler_copy_defines (GskSlCompiler *compiler);
+GskCodeSource * gsk_sl_compiler_resolve_include (GskSlCompiler *compiler,
+ GskCodeSource *source,
+ gboolean local,
+ const char *name,
+ GError **error);
+
G_END_DECLS
#endif /* __GSK_SL_COMPILER_PRIVATE_H__ */
diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c
index de92b69..98276c7 100644
--- a/gsk/gskslpreprocessor.c
+++ b/gsk/gskslpreprocessor.c
@@ -38,6 +38,7 @@ struct _GskSlPreprocessor
GskSlCompiler *compiler;
GskSlTokenizer *tokenizer;
+ GSList *pending_tokenizers;
GArray *tokens;
GHashTable *defines;
gboolean fatal_error;
@@ -117,6 +118,7 @@ gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc)
g_slist_free (preproc->conditionals);
g_hash_table_destroy (preproc->defines);
+ g_slist_free_full (preproc->pending_tokenizers, (GDestroyNotify) gsk_sl_tokenizer_unref);
gsk_sl_tokenizer_unref (preproc->tokenizer);
g_object_unref (preproc->compiler);
g_array_free (preproc->tokens, TRUE);
@@ -168,6 +170,54 @@ gsk_sl_preprocessor_in_ignored_conditional (GskSlPreprocessor *preproc)
}
static gboolean
+gsk_sl_preprocessor_include (GskSlPreprocessor *preproc,
+ GskSlPpToken *pp,
+ gboolean include_local)
+{
+ GskCodeSource *source;
+ GError *error = NULL;
+
+ source = gsk_sl_compiler_resolve_include (preproc->compiler,
+ gsk_sl_tokenizer_get_location (preproc->tokenizer)->source,
+ include_local,
+ pp->token.str,
+ &error);
+ if (source == NULL)
+ {
+ gsk_sl_preprocessor_emit_error (preproc, TRUE, &pp->location, error);
+ gsk_sl_preprocessor_clear_token (pp);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ if (g_slist_length (preproc->pending_tokenizers) > 20)
+ {
+ gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp->location, "#include nested too deeply.");
+ gsk_sl_preprocessor_clear_token (pp);
+ return FALSE;
+ }
+
+ gsk_sl_preprocessor_clear_token (pp);
+ pp->location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
+ gsk_sl_tokenizer_read_token (preproc->tokenizer, &pp->token);
+ if (!gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_NEWLINE) &&
+ !gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_EOF))
+ {
+ gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp->location, "Extra content after #include
directive");
+ gsk_sl_preprocessor_clear_token (pp);
+ return FALSE;
+ }
+
+ gsk_sl_preprocessor_clear_token (pp);
+ preproc->pending_tokenizers = g_slist_prepend (preproc->pending_tokenizers, preproc->tokenizer);
+ preproc->tokenizer = gsk_sl_tokenizer_new (source,
+ gsk_sl_preprocessor_error_func,
+ preproc,
+ NULL);
+ return TRUE;
+}
+
+static gboolean
gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc,
GskSlPpToken *pp,
gboolean *last_was_newline)
@@ -189,10 +239,28 @@ gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc,
}
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)
{
+ if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_EOF) &&
+ preproc->pending_tokenizers)
+ {
+ gboolean was_newline;
+ gsk_sl_tokenizer_unref (preproc->tokenizer);
+ preproc->tokenizer = preproc->pending_tokenizers->data;
+ 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);
+ return;
+ }
+
if (gsk_sl_preprocessor_in_ignored_conditional (preproc))
{
gsk_sl_preprocessor_clear_token (pp);
@@ -236,11 +304,6 @@ gsk_sl_preprocessor_append_token (GskSlPreprocessor *preproc,
}
static void
-gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
- GskSlPpToken *pp,
- gboolean was_newline);
-
-static void
gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
{
GskSlPpToken pp;
@@ -440,6 +503,26 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
return;
}
}
+ else if (g_str_equal (pp.token.str, "include"))
+ {
+ 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 filename after
#include.");
+ gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+ return;
+ }
+ if (gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_STRING))
+ {
+ if (gsk_sl_preprocessor_include (preproc, &pp, TRUE))
+ return;
+ }
+ else
+ {
+ gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp.location, "Expected filename after
#include.");
+ gsk_sl_preprocessor_clear_token (&pp);
+ }
+ }
#if 0
else if (g_str_equal (pp.token.str, "line"))
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]