aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/glcpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/glcpp')
-rwxr-xr-xmesalib/src/glsl/glcpp/.gitignore1
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-lex.l2
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y28
-rw-r--r--mesalib/src/glsl/glcpp/glcpp.c59
-rw-r--r--mesalib/src/glsl/glcpp/glcpp.h5
-rw-r--r--mesalib/src/glsl/glcpp/pp.c123
6 files changed, 134 insertions, 84 deletions
diff --git a/mesalib/src/glsl/glcpp/.gitignore b/mesalib/src/glsl/glcpp/.gitignore
index fc93edb36..9f7e0cc3e 100755
--- a/mesalib/src/glsl/glcpp/.gitignore
+++ b/mesalib/src/glsl/glcpp/.gitignore
@@ -3,3 +3,4 @@ glcpp-lex.c
glcpp-parse.output
glcpp-parse.c
glcpp-parse.h
+tests/*.out
diff --git a/mesalib/src/glsl/glcpp/glcpp-lex.l b/mesalib/src/glsl/glcpp/glcpp-lex.l
index fd28711d1..a029f6203 100644
--- a/mesalib/src/glsl/glcpp/glcpp-lex.l
+++ b/mesalib/src/glsl/glcpp/glcpp-lex.l
@@ -260,6 +260,8 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
}
"##" {
+ if (parser->is_gles)
+ glcpp_error(yylloc, yyextra, "Token pasting (##) is illegal in GLES");
return PASTE;
}
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index 380a1d99c..8fba923a2 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -363,6 +363,8 @@ integer_constant:
expression:
integer_constant
| IDENTIFIER {
+ if (parser->is_gles)
+ glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $1);
$$ = 0;
}
| expression OR expression {
@@ -1179,15 +1181,18 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
parser->has_new_source_number = 0;
parser->new_source_number = 0;
+ parser->is_gles = false;
+
/* Add pre-defined macros. */
if (extensions != NULL) {
if (extensions->OES_EGL_image_external)
add_builtin_define(parser, "GL_OES_EGL_image_external", 1);
}
- if (api == API_OPENGLES2)
+ if (api == API_OPENGLES2) {
+ parser->is_gles = true;
add_builtin_define(parser, "GL_ES", 1);
- else {
+ } else {
add_builtin_define(parser, "GL_ARB_draw_buffers", 1);
add_builtin_define(parser, "GL_ARB_texture_rectangle", 1);
@@ -2026,11 +2031,6 @@ static void
_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version,
const char *es_identifier)
{
- /* Note: We assume that if any identifier is present, it means ES.
- * The GLSL parser will double-check that the identifier is correct.
- */
- bool is_es = es_identifier != NULL;
-
macro_t *macro = hash_table_find (parser->defines, "__VERSION__");
if (macro) {
hash_table_remove (parser->defines, "__VERSION__");
@@ -2038,17 +2038,23 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
}
add_builtin_define (parser, "__VERSION__", version);
- if (version == 100)
- is_es = true;
- if (is_es)
+ /* If we didn't have a GLES context to begin with, (indicated
+ * by parser->api), then the version declaration here might
+ * indicate GLES. */
+ if (! parser->is_gles &&
+ (version == 100 ||
+ (es_identifier && (strcmp(es_identifier, "es") == 0))))
+ {
+ parser->is_gles = true;
add_builtin_define (parser, "GL_ES", 1);
+ }
/* Currently, all ES2/ES3 implementations support highp in the
* fragment shader, so we always define this macro in ES2/ES3.
* If we ever get a driver that doesn't support highp, we'll
* need to add a flag to the gl_context and check that here.
*/
- if (version >= 130 || is_es)
+ if (version >= 130 || parser->is_gles)
add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1);
ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length,
diff --git a/mesalib/src/glsl/glcpp/glcpp.c b/mesalib/src/glsl/glcpp/glcpp.c
index bef9fd08e..13a32fd7d 100644
--- a/mesalib/src/glsl/glcpp/glcpp.c
+++ b/mesalib/src/glsl/glcpp/glcpp.c
@@ -24,6 +24,8 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <getopt.h>
+
#include "glcpp.h"
#include "main/mtypes.h"
#include "main/shaderobj.h"
@@ -102,6 +104,37 @@ load_text_file(void *ctx, const char *filename)
return text;
}
+/* Initialize only those things that glcpp cares about.
+ */
+static void
+init_fake_gl_context (struct gl_context *gl_ctx)
+{
+ gl_ctx->API = API_OPENGL_COMPAT;
+ gl_ctx->Const.DisableGLSLLineContinuations = false;
+}
+
+static void
+usage (void)
+{
+ fprintf (stderr,
+ "Usage: glcpp [OPTIONS] [--] [<filename>]\n"
+ "\n"
+ "Pre-process the given filename (stdin if no filename given).\n"
+ "The following options are supported:\n"
+ " --disable-line-continuations Do not interpret lines ending with a\n"
+ " backslash ('\\') as a line continuation.\n");
+}
+
+enum {
+ DISABLE_LINE_CONTINUATIONS_OPT = CHAR_MAX + 1
+};
+
+const static struct option
+long_options[] = {
+ {"disable-line-continuations", no_argument, 0, DISABLE_LINE_CONTINUATIONS_OPT },
+ {0, 0, 0, 0 }
+};
+
int
main (int argc, char *argv[])
{
@@ -110,16 +143,36 @@ main (int argc, char *argv[])
char *info_log = ralloc_strdup(ctx, "");
const char *shader;
int ret;
+ struct gl_context gl_ctx;
+ int c;
+
+ init_fake_gl_context (&gl_ctx);
+
+ while ((c = getopt_long(argc, argv, "", long_options, NULL)) != -1) {
+ switch (c) {
+ case DISABLE_LINE_CONTINUATIONS_OPT:
+ gl_ctx.Const.DisableGLSLLineContinuations = true;
+ break;
+ default:
+ usage ();
+ exit (1);
+ }
+ }
- if (argc) {
- filename = argv[1];
+ if (optind + 1 < argc) {
+ printf ("Unexpected argument: %s\n", argv[optind+1]);
+ usage ();
+ exit (1);
+ }
+ if (optind < argc) {
+ filename = argv[optind];
}
shader = load_text_file (ctx, filename);
if (shader == NULL)
return 1;
- ret = glcpp_preprocess(ctx, &shader, &info_log, NULL, API_OPENGL_COMPAT);
+ ret = glcpp_preprocess(ctx, &shader, &info_log, NULL, &gl_ctx);
printf("%s", shader);
fprintf(stderr, "%s", info_log);
diff --git a/mesalib/src/glsl/glcpp/glcpp.h b/mesalib/src/glsl/glcpp/glcpp.h
index a459289b2..8aaa551d1 100644
--- a/mesalib/src/glsl/glcpp/glcpp.h
+++ b/mesalib/src/glsl/glcpp/glcpp.h
@@ -27,6 +27,8 @@
#include <stdint.h>
#include <stdbool.h>
+#include "main/mtypes.h"
+
#include "../ralloc.h"
#include "program/hash_table.h"
@@ -182,6 +184,7 @@ struct glcpp_parser {
int new_line_number;
bool has_new_source_number;
int new_source_number;
+ bool is_gles;
};
struct gl_extensions;
@@ -197,7 +200,7 @@ glcpp_parser_destroy (glcpp_parser_t *parser);
int
glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log,
- const struct gl_extensions *extensions, int api);
+ const struct gl_extensions *extensions, struct gl_context *g_ctx);
/* Functions for writing to the info log */
diff --git a/mesalib/src/glsl/glcpp/pp.c b/mesalib/src/glsl/glcpp/pp.c
index 11b29417b..789f7f941 100644
--- a/mesalib/src/glsl/glcpp/pp.c
+++ b/mesalib/src/glsl/glcpp/pp.c
@@ -70,92 +70,77 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
&parser->info_log_length, "\n");
}
-/* Searches backwards for '^ *#' from a given starting point. */
-static int
-in_directive(const char *shader, const char *ptr)
-{
- assert(ptr >= shader);
-
- /* Search backwards for '#'. If we find a \n first, it doesn't count */
- for (; ptr >= shader && *ptr != '#'; ptr--) {
- if (*ptr == '\n')
- return 0;
- }
- if (ptr >= shader) {
- /* Found '#'...look for spaces preceded by a newline */
- for (ptr--; ptr >= shader && isblank(*ptr); ptr--);
- // FIXME: I don't think the '\n' case can happen
- if (ptr < shader || *ptr == '\n')
- return 1;
- }
- return 0;
-}
-
-/* Remove any line continuation characters in preprocessing directives.
- * However, ignore any in GLSL code, as "There is no line continuation
- * character" (1.30 page 9) in GLSL.
+/* Remove any line continuation characters in the shader, (whether in
+ * preprocessing directives or in GLSL code).
*/
static char *
remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
{
- int in_continued_line = 0;
- int extra_newlines = 0;
char *clean = ralloc_strdup(ctx, "");
- const char *search_start = shader;
- const char *newline;
- while ((newline = strchr(search_start, '\n')) != NULL) {
- const char *backslash = NULL;
-
- /* # of characters preceding the newline. */
- int n = newline - shader;
-
- /* Find the preceding '\', if it exists */
- if (n >= 1 && newline[-1] == '\\')
- backslash = newline - 1;
- else if (n >= 2 && newline[-1] == '\r' && newline[-2] == '\\')
- backslash = newline - 2;
-
- /* Double backslashes don't count (the backslash is escaped) */
- if (backslash != NULL && backslash[-1] == '\\') {
- backslash = NULL;
- }
-
- if (backslash != NULL) {
- /* We found a line continuation, but do we care? */
- if (!in_continued_line) {
- if (in_directive(shader, backslash)) {
- in_continued_line = 1;
- extra_newlines = 0;
- }
- }
- if (in_continued_line) {
- /* Copy everything before the \ */
- ralloc_strncat(&clean, shader, backslash - shader);
+ const char *backslash, *newline, *search_start;
+ int collapsed_newlines = 0;
+
+ search_start = shader;
+
+ while (true) {
+ backslash = strchr(search_start, '\\');
+
+ /* If we have previously collapsed any line-continuations,
+ * then we want to insert additional newlines at the next
+ * occurrence of a newline character to avoid changing any
+ * line numbers.
+ */
+ if (collapsed_newlines) {
+ newline = strchr(search_start, '\n');
+ if (newline &&
+ (backslash == NULL || newline < backslash))
+ {
+ ralloc_strncat(&clean, shader,
+ newline - shader + 1);
+ while (collapsed_newlines--)
+ ralloc_strcat(&clean, "\n");
shader = newline + 1;
- extra_newlines++;
+ search_start = shader;
}
- } else if (in_continued_line) {
- /* Copy everything up to and including the \n */
- ralloc_strncat(&clean, shader, newline - shader + 1);
- shader = newline + 1;
- /* Output extra newlines to make line numbers match */
- for (; extra_newlines > 0; extra_newlines--)
- ralloc_strcat(&clean, "\n");
- in_continued_line = 0;
}
- search_start = newline + 1;
+
+ search_start = backslash + 1;
+
+ if (backslash == NULL)
+ break;
+
+ /* At each line continuation, (backslash followed by a
+ * newline), copy all preceding text to the output, then
+ * advance the shader pointer to the character after the
+ * newline.
+ */
+ if (backslash[1] == '\n' ||
+ (backslash[1] == '\r' && backslash[2] == '\n'))
+ {
+ collapsed_newlines++;
+ ralloc_strncat(&clean, shader, backslash - shader);
+ if (backslash[1] == '\n')
+ shader = backslash + 2;
+ else
+ shader = backslash + 3;
+ search_start = shader;
+ }
}
+
ralloc_strcat(&clean, shader);
+
return clean;
}
int
glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log,
- const struct gl_extensions *extensions, int api)
+ const struct gl_extensions *extensions, struct gl_context *gl_ctx)
{
int errors;
- glcpp_parser_t *parser = glcpp_parser_create (extensions, api);
- *shader = remove_line_continuations(parser, *shader);
+ glcpp_parser_t *parser = glcpp_parser_create (extensions, gl_ctx->API);
+
+ if (! gl_ctx->Const.DisableGLSLLineContinuations)
+ *shader = remove_line_continuations(parser, *shader);
glcpp_lex_set_source_string (parser, *shader);