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.
This commit is contained in:
Benjamin Otte
2017-09-24 03:34:31 +02:00
parent f8299719b4
commit 67b60b54ac
10 changed files with 774 additions and 50 deletions

View File

@@ -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;
*real_error = g_error_copy (error);
g_prefix_error (real_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, (gpointer) 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)

View File

@@ -34,6 +34,15 @@ G_DECLARE_FINAL_TYPE (GskSlCompiler, gsk_sl_compiler, GSK, SL_COMPILER, GObject)
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);

View File

@@ -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__ */

132
gsk/gsksldefine.c Normal file
View File

@@ -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);
}

51
gsk/gsksldefineprivate.h Normal file
View File

@@ -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__ */

View File

@@ -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;
if (gsk_sl_token_is (&preproc->token, GSK_SL_TOKEN_IDENTIFIER))
{
if (g_str_equal (preproc->token.str, "define"))
gsk_sl_preprocessor_clear_token (&pp);
return;
}
if (gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_IDENTIFIER))
{
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);

View File

@@ -314,6 +314,256 @@ 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;
default:
g_assert_not_reached ();
break;
}
}
static const char *keywords[] = {
[GSK_SL_TOKEN_CONST] = "const",
[GSK_SL_TOKEN_BOOL] = "bool",
@@ -1484,6 +1734,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)
@@ -1518,6 +1785,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)

View File

@@ -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);

View File

@@ -34,6 +34,7 @@ gsk_private_sources = files([
'gskprivate.c',
'gskprofiler.c',
'gskshaderbuilder.c',
'gsksldefine.c',
'gskslfunction.c',
'gskslnode.c',
'gskslpreprocessor.c',

View File

@@ -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))
{