[gtk+/wip/otte/shader: 28/28] gskslpreprocessor: Implement #define and #undef
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 28/28] gskslpreprocessor: Implement #define and #undef
- Date: Sun, 24 Sep 2017 03:51:48 +0000 (UTC)
commit d4298e7517e3b399aada1f54425f81b57c0d04a9
Author: Benjamin Otte <otte redhat com>
Date: Sun Sep 24 05:45:49 2017 +0200
gskslpreprocessor: Implement #define and #undef
gsk/gskslpreprocessor.c | 251 +++++++++++++++++++++++++++-------------
gsk/gskslpreprocessorprivate.h | 6 +
2 files changed, 178 insertions(+), 79 deletions(-)
---
diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c
index 26537e7..19ed0ff 100644
--- a/gsk/gskslpreprocessor.c
+++ b/gsk/gskslpreprocessor.c
@@ -116,34 +116,75 @@ gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc)
static gboolean
gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc,
- GskSlPpToken *pp)
+ GskSlPpToken *pp,
+ gboolean *last_was_newline)
{
- gboolean was_newline;
+ gboolean contained_newline = FALSE;
pp->token = (GskSlToken) { 0, };
do
{
pp->location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
- was_newline = gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_NEWLINE);
+ *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 was_newline;
+ return contained_newline || gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_EOF);
}
static void
-gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
+gsk_sl_preprocessor_append_token (GskSlPreprocessor *preproc,
+ GskSlPpToken *pp,
+ GSList *used_defines)
{
- GskSlPpToken pp;
+ if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ GskSlDefine *define;
+ char *ident = pp->token.str;
- gboolean was_newline = gsk_sl_preprocessor_next_token (preproc, &pp);
+ 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;
- /* empty # line */
- if (was_newline)
+ 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);
+ }
+
+ g_array_append_val (preproc->tokens, *pp);
+}
+
+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;
+ gboolean was_newline;
+
+ if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
{
- gsk_sl_preprocessor_clear_token (&pp);
+ /* empty # line */
+ gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
return;
}
@@ -151,96 +192,145 @@ gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc)
{
if (g_str_equal (pp.token.str, "define"))
{
- gsk_sl_preprocessor_error (preproc, "Unknown preprocessor directive #define.");
gsk_sl_preprocessor_clear_token (&pp);
+ if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
+ {
+ gsk_sl_preprocessor_error_full (preproc, &pp.location, &pp.token, "No variable after
#define.");
+ gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+ return;
+ }
+ if (!gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ gsk_sl_preprocessor_error_full (preproc, &pp.location, &pp.token, "Expected identifier after
#define.");
+ gsk_sl_preprocessor_clear_token (&pp);
+ }
+ else
+ {
+ GskSlDefine *define;
+
+ if (g_hash_table_lookup (preproc->defines, pp.token.str))
+ gsk_sl_preprocessor_error_full (preproc, &pp.location, &pp.token, "\"%s\" redefined.",
pp.token.str);
+
+ define = gsk_sl_define_new (pp.token.str, NULL);
+ gsk_sl_preprocessor_clear_token (&pp);
+
+ while (!gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
+ {
+ gsk_sl_define_add_token (define, &pp.location, &pp.token);
+ gsk_sl_preprocessor_clear_token (&pp);
+ }
+ g_hash_table_replace (preproc->defines, gsk_sl_define_get_name (define), define);
+ gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+ return;
+ }
}
#if 0
- else if (g_str_equal (preproc->token.str, "else"))
+ else if (g_str_equal (pp.token.str, "else"))
{
}
- else if (g_str_equal (preproc->token.str, "elif"))
+ else if (g_str_equal (pp.token.str, "elif"))
{
}
- else if (g_str_equal (preproc->token.str, "endif"))
+ else if (g_str_equal (pp.token.str, "endif"))
{
}
- else if (g_str_equal (preproc->token.str, "error"))
+ else if (g_str_equal (pp.token.str, "error"))
{
}
- else if (g_str_equal (preproc->token.str, "extension"))
+ else if (g_str_equal (pp.token.str, "extension"))
{
}
- else if (g_str_equal (preproc->token.str, "if"))
+ else if (g_str_equal (pp.token.str, "if"))
{
}
- else if (g_str_equal (preproc->token.str, "ifdef"))
+ else if (g_str_equal (pp.token.str, "ifdef"))
{
}
- else if (g_str_equal (preproc->token.str, "ifndef"))
+ else if (g_str_equal (pp.token.str, "ifndef"))
{
}
- else if (g_str_equal (preproc->token.str, "line"))
+ else if (g_str_equal (pp.token.str, "line"))
{
}
- else if (g_str_equal (preproc->token.str, "pragma"))
+ else if (g_str_equal (pp.token.str, "pragma"))
{
}
- else if (g_str_equal (preproc->token.str, "undef"))
+#endif
+ else if (g_str_equal (pp.token.str, "undef"))
{
+ gsk_sl_preprocessor_clear_token (&pp);
+ if (gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
+ {
+ gsk_sl_preprocessor_error_full (preproc, &pp.location, &pp.token, "No variable after #undef.");
+ gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+ return;
+ }
+ if (!gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ gsk_sl_preprocessor_error_full (preproc, &pp.location, &pp.token, "Expected identifier after
#undef.");
+ gsk_sl_preprocessor_clear_token (&pp);
+ }
+ else
+ {
+ g_hash_table_remove (preproc->defines, pp.token.str);
+
+ if (!gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline))
+ {
+ gsk_sl_preprocessor_error_full (preproc, &pp.location, &pp.token, "Expected newline after
#undef.");
+ gsk_sl_preprocessor_clear_token (&pp);
+ }
+ else
+ {
+ gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline);
+ }
+ return;
+ }
}
- else if (g_str_equal (preproc->token.str, "version"))
+#if 0
+ else if (g_str_equal (pp.token.str, "version"))
{
}
#endif
else
{
- gsk_sl_preprocessor_error (preproc, "Unknown preprocessor directive #%s.", pp.token.str);
+ gsk_sl_preprocessor_error_full (preproc, &pp.location, &pp.token, "Unknown preprocessor directive
#%s.", pp.token.str);
gsk_sl_preprocessor_clear_token (&pp);
}
}
else
{
- gsk_sl_preprocessor_error (preproc, "Missing identifier for preprocessor directive.");
+ gsk_sl_preprocessor_error_full (preproc, &pp.location, &pp.token, "Missing identifier for preprocessor
directive.");
gsk_sl_preprocessor_clear_token (&pp);
}
- while (!gsk_sl_preprocessor_next_token (preproc, &pp))
+ 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);
}
static void
-gsk_sl_preprocessor_append_token (GskSlPreprocessor *preproc,
+gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
GskSlPpToken *pp,
- GSList *used_defines)
+ gboolean was_newline)
{
- if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_IDENTIFIER))
+ if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_HASH))
{
- GskSlDefine *define;
- char *ident = pp->token.str;
-
- define = g_hash_table_lookup (preproc->defines, ident);
- if (define &&
- !g_slist_find (used_defines, define))
+ if (!was_newline)
{
- 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_error (preproc, "Unexpected \"#\" - preprocessor directives must be at start
of line.");
gsk_sl_preprocessor_clear_token (pp);
- return;
}
-
- gsk_sl_token_init_from_identifier (&pp->token, ident);
- g_free (ident);
+ else
+ {
+ gsk_sl_preprocessor_clear_token (pp);
+ gsk_sl_preprocessor_handle_preprocessor_directive (preproc);
+ }
+ }
+ else
+ {
+ gsk_sl_preprocessor_append_token (preproc, pp, NULL);
}
-
- g_array_append_val (preproc->tokens, *pp);
}
static void
@@ -249,36 +339,12 @@ gsk_sl_preprocessor_ensure (GskSlPreprocessor *preproc)
GskSlPpToken pp;
gboolean was_newline = FALSE;
- if (preproc->tokens->len > 0)
- return;
-
- was_newline = gsk_sl_preprocessor_next_token (preproc, &pp);
-
- while (TRUE)
+ while (preproc->tokens->len <= 0)
{
- if (gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_HASH))
- {
- if (!was_newline &&
- pp.location.bytes != 0)
- {
- gsk_sl_preprocessor_error (preproc, "Unexpected \"#\" - preprocessor directives must be at
start of line.");
- 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;
- }
- }
- else
- {
- break;
- }
- }
+ gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline);
- gsk_sl_preprocessor_append_token (preproc, &pp, NULL);
+ gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline || pp.location.bytes == 0);
+ }
}
const GskSlToken *
@@ -307,6 +373,33 @@ gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
}
void
+gsk_sl_preprocessor_error_full (GskSlPreprocessor *preproc,
+ const GskCodeLocation *location,
+ const GskSlToken *token,
+ const char *format,
+ ...)
+{
+ GError *error;
+ va_list args;
+
+ va_start (args, format);
+ error = g_error_new_valist (G_FILE_ERROR,
+ G_FILE_ERROR_FAILED,
+ format,
+ args);
+ va_end (args);
+
+ gsk_sl_preprocessor_error_func (preproc->tokenizer,
+ TRUE,
+ location,
+ token,
+ error,
+ NULL);
+
+ g_error_free (error);
+}
+
+void
gsk_sl_preprocessor_error (GskSlPreprocessor *preproc,
const char *format,
...)
diff --git a/gsk/gskslpreprocessorprivate.h b/gsk/gskslpreprocessorprivate.h
index 02991c5..acb7d22 100644
--- a/gsk/gskslpreprocessorprivate.h
+++ b/gsk/gskslpreprocessorprivate.h
@@ -22,6 +22,7 @@
#include <glib.h>
#include "gsksltypesprivate.h"
+#include "gsksltokenizerprivate.h"
G_BEGIN_DECLS
@@ -39,6 +40,11 @@ void gsk_sl_preprocessor_consume (GskSlPreprocess
void gsk_sl_preprocessor_error (GskSlPreprocessor *preproc,
const char *format,
...) G_GNUC_PRINTF(2, 3);
+void gsk_sl_preprocessor_error_full (GskSlPreprocessor *preproc,
+ const GskCodeLocation *location,
+ const GskSlToken *token,
+ const char *format,
+ ...) G_GNUC_PRINTF(4, 5);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]