diff options
Diffstat (limited to 'mesalib/src/glsl/glcpp')
-rwxr-xr-x | mesalib/src/glsl/glcpp/.gitignore | 1 | ||||
-rw-r--r-- | mesalib/src/glsl/glcpp/glcpp-lex.l | 2 | ||||
-rw-r--r-- | mesalib/src/glsl/glcpp/glcpp-parse.y | 28 | ||||
-rw-r--r-- | mesalib/src/glsl/glcpp/glcpp.c | 59 | ||||
-rw-r--r-- | mesalib/src/glsl/glcpp/glcpp.h | 5 | ||||
-rw-r--r-- | mesalib/src/glsl/glcpp/pp.c | 123 |
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); |