diff --git a/gsk/gsk.h b/gsk/gsk.h index 0b9cbd3b7a..d4490fd004 100644 --- a/gsk/gsk.h +++ b/gsk/gsk.h @@ -20,6 +20,7 @@ #define __GSK_H_INSIDE__ +#include #include #include #include diff --git a/gsk/gskcodesource.c b/gsk/gskcodesource.c new file mode 100644 index 0000000000..155994fdde --- /dev/null +++ b/gsk/gskcodesource.c @@ -0,0 +1,151 @@ +/* GTK - The GIMP Toolkit + * + * Copyright © 2017 Benjamin Otte + * + * 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 . + */ + +#include "config.h" + +#include "gskcodesourceprivate.h" + +struct _GskCodeSource { + GObject parent_instance; + + char *name; + GFile *file; + + GBytes *bytes; +}; + +G_DEFINE_TYPE (GskCodeSource, gsk_code_source, G_TYPE_OBJECT) + +static void +gsk_code_source_dispose (GObject *object) +{ + GskCodeSource *source = GSK_CODE_SOURCE (object); + + g_free (source->name); + if (source->file) + g_object_unref (source->file); + if (source->bytes) + g_bytes_unref (source->bytes); + + G_OBJECT_CLASS (gsk_code_source_parent_class)->dispose (object); +} + +static void +gsk_code_source_class_init (GskCodeSourceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gsk_code_source_dispose; +} + +static void +gsk_code_source_init (GskCodeSource *source) +{ +} + +const char * +gsk_code_source_get_name (GskCodeSource *source) +{ + g_return_val_if_fail (GSK_IS_CODE_SOURCE (source), NULL); + + return source->name; +} + +GFile * +gsk_code_source_get_file (GskCodeSource *source) +{ + g_return_val_if_fail (GSK_IS_CODE_SOURCE (source), NULL); + + return source->file; +} + +GskCodeSource * +gsk_code_source_new_for_bytes (const char *name, + GBytes *data) +{ + GskCodeSource *result; + + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + + result = g_object_new (GSK_TYPE_CODE_SOURCE, NULL); + + result->name = g_strdup (name); + result->bytes = g_bytes_ref (data); + + return result; +} + +static char * +get_name_for_file (GFile *file) +{ + GFileInfo *info; + char *result; + + info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL); + + if (info) + { + result = g_strdup (g_file_info_get_display_name (info)); + g_object_unref (info); + } + else + { + result = g_strdup (""); + } + + return result; +} + +GskCodeSource * +gsk_code_source_new_for_file (GFile *file) +{ + GskCodeSource *result; + + g_return_val_if_fail (G_IS_FILE (file), NULL); + + result = g_object_new (GSK_TYPE_CODE_SOURCE, NULL); + + result->file = g_object_ref (file); + result->name = get_name_for_file (file); + + return result; +} + +GBytes * +gsk_code_source_load (GskCodeSource *source, + GError **error) +{ + gchar *data; + gsize length; + + if (source->bytes) + return g_bytes_ref (source->bytes); + + g_return_val_if_fail (source->file, NULL); + + if (!g_file_load_contents (source->file, + NULL, + &data, &length, + NULL, + error)) + return NULL; + + return g_bytes_new_take (data, length); +} + diff --git a/gsk/gskcodesource.h b/gsk/gskcodesource.h new file mode 100644 index 0000000000..415ed95956 --- /dev/null +++ b/gsk/gskcodesource.h @@ -0,0 +1,41 @@ +/* GTK - The GIMP Toolkit + * + * Copyright © 2017 Benjamin Otte + * + * 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 . + */ + +#ifndef __GSK_CODE_SOURCE_H__ +#define __GSK_CODE_SOURCE_H__ + +#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define GSK_TYPE_CODE_SOURCE (gsk_code_source_get_type ()) + +G_DECLARE_FINAL_TYPE (GskCodeSource, gsk_code_source, GSK, CODE_SOURCE, GObject) + +GDK_AVAILABLE_IN_3_92 +const char * gsk_code_source_get_name (GskCodeSource *source); +GDK_AVAILABLE_IN_3_92 +GFile * gsk_code_source_get_file (GskCodeSource *source); + +G_END_DECLS + +#endif /* __GSK_CODE_SOURCE_H__ */ diff --git a/gsk/gskcodesourceprivate.h b/gsk/gskcodesourceprivate.h new file mode 100644 index 0000000000..83baa2111c --- /dev/null +++ b/gsk/gskcodesourceprivate.h @@ -0,0 +1,35 @@ +/* GTK - The GIMP Toolkit + * + * Copyright © 2017 Benjamin Otte + * + * 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 . + */ + +#ifndef __GSK_CODE_SOURCE_PRIVATE_H__ +#define __GSK_CODE_SOURCE_PRIVATE_H__ + +#include "gsk/gskcodesource.h" + +G_BEGIN_DECLS + +GskCodeSource * gsk_code_source_new_for_bytes (const char *name, + GBytes *data); +GskCodeSource * gsk_code_source_new_for_file (GFile *file); + +GBytes * gsk_code_source_load (GskCodeSource *source, + GError **error); + +G_END_DECLS + +#endif /* __GSK_CODE_SOURCE_PRIVATE_H__ */ diff --git a/gsk/gskslcompiler.c b/gsk/gskslcompiler.c index b473cecf1d..1c0b9c6d31 100644 --- a/gsk/gskslcompiler.c +++ b/gsk/gskslcompiler.c @@ -20,6 +20,7 @@ #include "gskslcompilerprivate.h" +#include "gskcodesourceprivate.h" #include "gsksldefineprivate.h" #include "gskslpreprocessorprivate.h" #include "gskslprogramprivate.h" @@ -101,6 +102,7 @@ gsk_sl_compiler_add_define (GskSlCompiler *compiler, GskCodeLocation location; GskSlToken token = { 0, }; GError *real_error = NULL; + GskCodeSource *source; GBytes *bytes; g_return_val_if_fail (GSK_IS_SL_COMPILER (compiler), FALSE); @@ -118,7 +120,8 @@ gsk_sl_compiler_add_define (GskSlCompiler *compiler, define = gsk_sl_define_new (name, NULL); bytes = g_bytes_new_static (definition, strlen (definition)); - tokenizer = gsk_sl_tokenizer_new (bytes, + source = gsk_code_source_new_for_bytes ("", bytes); + tokenizer = gsk_sl_tokenizer_new (source, gsk_sl_compiler_add_define_error_func, &real_error, NULL); @@ -142,6 +145,7 @@ gsk_sl_compiler_add_define (GskSlCompiler *compiler, gsk_sl_token_clear (&token); gsk_sl_tokenizer_unref (tokenizer); g_bytes_unref (bytes); + g_object_unref (source); if (real_error == NULL) { @@ -187,12 +191,14 @@ gsk_sl_compiler_copy_defines (GskSlCompiler *compiler) GskSlProgram * gsk_sl_compiler_compile (GskSlCompiler *compiler, - GBytes *source) + GBytes *bytes) { GskSlPreprocessor *preproc; + GskCodeSource *source; GskSlProgram *program; program = g_object_new (GSK_TYPE_SL_PROGRAM, NULL); + source = gsk_code_source_new_for_bytes ("", bytes); preproc = gsk_sl_preprocessor_new (compiler, source); @@ -205,6 +211,7 @@ gsk_sl_compiler_compile (GskSlCompiler *compiler, } gsk_sl_preprocessor_unref (preproc); + g_object_unref (source); return program; } diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c index eb22aaa473..de92b69087 100644 --- a/gsk/gskslpreprocessor.c +++ b/gsk/gskslpreprocessor.c @@ -20,6 +20,7 @@ #include "gskslpreprocessorprivate.h" +#include "gskcodesource.h" #include "gskslcompilerprivate.h" #include "gsksldefineprivate.h" #include "gsksltokenizerprivate.h" @@ -75,7 +76,7 @@ gsk_sl_preprocessor_clear_token (gpointer data) GskSlPreprocessor * gsk_sl_preprocessor_new (GskSlCompiler *compiler, - GBytes *source) + GskCodeSource *source) { GskSlPreprocessor *preproc; @@ -609,7 +610,8 @@ gsk_sl_preprocessor_emit_error (GskSlPreprocessor *preproc, { preproc->fatal_error |= fatal; - g_printerr ("%3zu:%2zu: %s: %s\n", + g_printerr ("%s:%zu:%zu: %s: %s\n", + gsk_code_source_get_name (location->source), location->lines + 1, location->line_bytes, fatal ? "error" : "warn", error->message); diff --git a/gsk/gskslpreprocessorprivate.h b/gsk/gskslpreprocessorprivate.h index 13755d11d6..3ea5939605 100644 --- a/gsk/gskslpreprocessorprivate.h +++ b/gsk/gskslpreprocessorprivate.h @@ -26,7 +26,7 @@ G_BEGIN_DECLS GskSlPreprocessor * gsk_sl_preprocessor_new (GskSlCompiler *compiler, - GBytes *source); + GskCodeSource *source); GskSlPreprocessor * gsk_sl_preprocessor_ref (GskSlPreprocessor *preproc); void gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc); diff --git a/gsk/gsksltokenizer.c b/gsk/gsksltokenizer.c index ae3c5e5b47..220e3ad5e8 100644 --- a/gsk/gsksltokenizer.c +++ b/gsk/gsksltokenizer.c @@ -20,6 +20,7 @@ #include "gsksltokenizerprivate.h" #include "gskslcompiler.h" +#include "gskcodesourceprivate.h" #include #include @@ -36,6 +37,7 @@ struct _GskSlTokenReader { struct _GskSlTokenizer { gint ref_count; + GskCodeSource *source; GBytes *bytes; GskSlTokenizerErrorFunc error_func; gpointer user_data; @@ -45,9 +47,10 @@ struct _GskSlTokenizer }; static void -gsk_code_location_init (GskCodeLocation *location) +gsk_code_location_init (GskCodeLocation *location, + GskCodeSource *source) { - memset (location, 0, sizeof (GskCodeLocation)); + *location = (GskCodeLocation) { source, }; } static void @@ -1196,12 +1199,13 @@ gsk_sl_token_init_number (GskSlToken *token, static void gsk_sl_token_reader_init (GskSlTokenReader *reader, + GskCodeSource *source, GBytes *bytes) { reader->data = g_bytes_get_data (bytes, NULL); reader->end = reader->data + g_bytes_get_size (bytes); - gsk_code_location_init (&reader->position); + gsk_code_location_init (&reader->position, source); } static void @@ -1321,22 +1325,48 @@ gsk_sl_token_reader_consume (GskSlTokenReader *reader, reader->data += offset; } +static void +gsk_sl_tokenizer_emit_error (GskSlTokenizer *tokenizer, + const GskCodeLocation *location, + const GskSlToken *token, + const GError *error) +{ + if (tokenizer->error_func) + tokenizer->error_func (tokenizer, TRUE, location, token, error, tokenizer->user_data); + else + g_warning ("Unhandled GLSL error: %zu:%zu: %s", location->lines + 1, location->line_chars + 1, error->message); +} + GskSlTokenizer * -gsk_sl_tokenizer_new (GBytes *bytes, +gsk_sl_tokenizer_new (GskCodeSource *source, GskSlTokenizerErrorFunc func, gpointer user_data, GDestroyNotify user_destroy) { GskSlTokenizer *tokenizer; + GError *error = NULL; tokenizer = g_slice_new0 (GskSlTokenizer); tokenizer->ref_count = 1; - tokenizer->bytes = g_bytes_ref (bytes); + tokenizer->source = g_object_ref (source); tokenizer->error_func = func; tokenizer->user_data = user_data; tokenizer->user_destroy = user_destroy; - gsk_sl_token_reader_init (&tokenizer->reader, bytes); + tokenizer->bytes = gsk_code_source_load (source, &error); + if (tokenizer->bytes == NULL) + { + GskCodeLocation location; + GskSlToken token; + + gsk_code_location_init (&location, tokenizer->source); + gsk_sl_token_init (&token, GSK_SL_TOKEN_EOF); + gsk_sl_tokenizer_emit_error (tokenizer, &location, &token, error); + g_error_free (error); + tokenizer->bytes = g_bytes_new (NULL, 0); + } + + gsk_sl_token_reader_init (&tokenizer->reader, source, tokenizer->bytes); return tokenizer; } @@ -1360,6 +1390,8 @@ gsk_sl_tokenizer_unref (GskSlTokenizer *tokenizer) tokenizer->user_destroy (tokenizer->user_data); g_bytes_unref (tokenizer->bytes); + g_object_unref (tokenizer->source); + g_slice_free (GskSlTokenizer, tokenizer); } @@ -1393,18 +1425,6 @@ set_parse_error (GError **error, va_end (args); } -static void -gsk_sl_tokenizer_emit_error (GskSlTokenizer *tokenizer, - const GskCodeLocation *location, - const GskSlToken *token, - const GError *error) -{ - if (tokenizer->error_func) - tokenizer->error_func (tokenizer, TRUE, location, token, error, tokenizer->user_data); - else - g_warning ("Unhandled GLSL error: %zu:%zu: %s", location->lines + 1, location->line_chars + 1, error->message); -} - static void gsk_sl_token_reader_read_multi_line_comment (GskSlTokenReader *reader, GskSlToken *token, diff --git a/gsk/gsksltokenizerprivate.h b/gsk/gsksltokenizerprivate.h index 381a851a16..897e5aaaad 100644 --- a/gsk/gsksltokenizerprivate.h +++ b/gsk/gsksltokenizerprivate.h @@ -284,10 +284,10 @@ void gsk_sl_token_print (const GskSlToke GString *string); char * gsk_sl_token_to_string (const GskSlToken *token); -GskSlTokenizer * gsk_sl_tokenizer_new (GBytes *bytes, +GskSlTokenizer * gsk_sl_tokenizer_new (GskCodeSource *source, GskSlTokenizerErrorFunc func, - gpointer user_data, - GDestroyNotify user_destroy); + gpointer user_data, + GDestroyNotify user_destroy); GskSlTokenizer * gsk_sl_tokenizer_ref (GskSlTokenizer *tokenizer); void gsk_sl_tokenizer_unref (GskSlTokenizer *tokenizer); diff --git a/gsk/gsktypes.h b/gsk/gsktypes.h index 7323b939b7..613781a8b6 100644 --- a/gsk/gsktypes.h +++ b/gsk/gsktypes.h @@ -27,6 +27,7 @@ #include typedef struct _GskCodeLocation GskCodeLocation; +typedef struct _GskCodeSource GskCodeSource; typedef struct _GskPixelShader GskPixelShader; typedef struct _GskRenderer GskRenderer; typedef struct _GskSlCompiler GskSlCompiler; @@ -35,6 +36,7 @@ typedef struct _GskTexture GskTexture; struct _GskCodeLocation { + GskCodeSource *source; gsize bytes; gsize chars; gsize lines; diff --git a/gsk/meson.build b/gsk/meson.build index fd3ffbe0e1..0bb7a1ff8e 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -14,6 +14,7 @@ gsk_private_source_shaders = [ ] gsk_public_sources = files([ + 'gskcodesource.c', 'gskpixelshader.c', 'gskrenderer.c', 'gskrendernode.c',