[Mesa-dev] [PATCH 1/2] glsl: Support GL_ARB_shading_language_include internally.

Ian Romanick idr at freedesktop.org
Fri Apr 13 12:06:34 PDT 2012


On 04/11/2012 01:46 AM, Olivier Galibert wrote:
> No hookup with GL yet.  Planned to be used to simplify profiles.

I haven't looked at the guts of the patch yet, but I have some comments 
about the general direction.

GL_ARB_shading_language_include is an odd extension (for which I'm 
primarily responsible) that allows applications to create a map of names 
to blobs of shading language code.  When '#include "name"' occurs in a 
shader, it is replaced with a blob of shading language code.

GL_ARB_shading_language_include does *not* provide access to the file 
system.  It also doesn't provide a way to demand-load replacements for 
names that don't exist in the map.

This patch adds #include to the glcpp to allow access to the file 
system.  This is contrary to the function of the extension, but it is 
very useful for the usage in the second patch.  This particular 
implementation of #include should only ever be exposed by the standalone 
compiler (and perhaps the standalone glcpp).

Until the rest of the name-to-code mapping is implemented, #include 
should not be exposed outside the standalone compiler at all.

One way to do this is to make a fake extension, 
GL_MESAX_shading_language_include_file or something, that is only 
enabled in the standalone compiler.  The #include keyword can be 
accepted, with differing behavior, when either extension is enabled.

> Signed-off-by: Olivier Galibert<galibert at pobox.com>
> ---
>   src/glsl/ast.h                  |   12 ++-
>   src/glsl/glcpp/glcpp-lex.l      |  135 ++++++++++++++++++++++++--
>   src/glsl/glcpp/glcpp-parse.y    |   75 +++++++++++++-
>   src/glsl/glcpp/glcpp.c          |   14 +++-
>   src/glsl/glcpp/glcpp.h          |   56 ++++++++++-
>   src/glsl/glcpp/pp.c             |   92 ++++++++++++++++-
>   src/glsl/glsl_lexer.ll          |   32 ++++++-
>   src/glsl/glsl_parser.yy         |  203 ++++++++++++++++++++-------------------
>   src/glsl/glsl_parser_extras.cpp |   23 ++++-
>   src/glsl/glsl_parser_extras.h   |   16 +++-
>   src/glsl/main.cpp               |   24 ++++-
>   src/glsl/test_optpass.cpp       |    2 +-
>   src/mesa/program/ir_to_mesa.cpp |    2 +-
>   13 files changed, 542 insertions(+), 144 deletions(-)
>
> diff --git a/src/glsl/ast.h b/src/glsl/ast.h
> index 1f78af8..b0bfb28 100644
> --- a/src/glsl/ast.h
> +++ b/src/glsl/ast.h
> @@ -65,6 +65,9 @@ public:
>       * ralloc_free in that case. */
>      static void operator delete(void *table)
>      {
> +      ast_node *an = static_cast<ast_node *>(table);
> +      if(an->location.source)
> +	 ralloc_free(an->location.source);
>         ralloc_free(table);
>      }
>
> @@ -92,6 +95,7 @@ public:
>         struct YYLTYPE locp;
>
>         locp.source = this->location.source;
> +      locp.source_id = this->location.source_id;
>         locp.first_line = this->location.line;
>         locp.first_column = this->location.column;
>         locp.last_line = locp.first_line;
> @@ -105,9 +109,10 @@ public:
>       *
>       * \sa ast_node::get_location
>       */
> -   void set_location(const struct YYLTYPE&locp)
> +   void set_location(const struct YYLTYPE&locp, void *ctx)
>      {
> -      this->location.source = locp.source;
> +      this->location.source = locp.source ? ralloc_strdup(ctx, locp.source) : 0;
> +      this->location.source_id = locp.source_id;
>         this->location.line = locp.first_line;
>         this->location.column = locp.first_column;
>      }
> @@ -116,7 +121,8 @@ public:
>       * Source location of the AST node.
>       */
>      struct {
> -      unsigned source;    /**<  GLSL source number. */
> +      unsigned source_id; /**<  GLSL source number (if source is NULL)  */
> +      char *source;       /**<  GLSL source file or NULL */
>         unsigned line;      /**<  Line number within the source string. */
>         unsigned column;    /**<  Column in the line. */
>      } location;
> diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l
> index b34f2c0..2ce1547 100644
> --- a/src/glsl/glcpp/glcpp-lex.l
> +++ b/src/glsl/glcpp/glcpp-lex.l
> @@ -44,6 +44,8 @@ void glcpp_set_column (int  column_no , yyscan_t yyscanner);
>      do {                                                         \
>         yylloc->first_column = yycolumn + 1;                      \
>         yylloc->first_line = yylineno;                            \
> +      yylloc->source = yyextra->source;                         \
> +      yylloc->source_id = yyextra->source_id;                   \
>         yycolumn += yyleng;                                       \
>      } while(0);
>
> @@ -51,17 +53,16 @@ void glcpp_set_column (int  column_no , yyscan_t yyscanner);
>   	do {				\
>   		yylineno = 1;		\
>   		yycolumn = 1;		\
> -		yylloc->source = 0;	\
>   	} while(0)
>   %}
>
> -%option bison-bridge bison-locations reentrant noyywrap
> +%option bison-bridge bison-locations reentrant
>   %option extra-type="glcpp_parser_t *"
>   %option prefix="glcpp_"
>   %option stack
>   %option never-interactive
>
> -%x DONE COMMENT UNREACHABLE SKIP
> +%x DONE COMMENT UNREACHABLE SKIP EXTENSION
>
>   SPACE		[[:space:]]
>   NONSPACE	[^[:space:]]
> @@ -69,7 +70,8 @@ NEWLINE		[\n]
>   HSPACE		[ \t]
>   HASH		^{HSPACE}*#{HSPACE}*
>   IDENTIFIER	[_a-zA-Z][_a-zA-Z0-9]*
> -PUNCTUATION	[][(){}.&*~!/%<>^|;,=+-]
> +PUNCTUATION	[][(){}.&*~!/%<>^|;,=+-:]
> +STRING		"\""[^"\n]+"\""
>
>   /* The OTHER class is simply a catch-all for things that the CPP
>   parser just doesn't care about. Since flex regular expressions that
> @@ -78,7 +80,7 @@ strings, we have to be careful to avoid OTHER matching and hiding
>   something that CPP does care about. So we simply exclude all
>   characters that appear in any other expressions. */
>
> -OTHER		[^][_#[:space:]#a-zA-Z0-9(){}.&*~!/%<>^|;,=+-]
> +OTHER		[^][_#[:space:]#a-zA-Z0-9(){}.&*~!/%<>^|;,=+-:]
>
>   DIGITS			[0-9][0-9]*
>   DECIMAL_INTEGER		[1-9][0-9]*[uU]?
> @@ -120,15 +122,45 @@ HEXADECIMAL_INTEGER	0[xX][0-9a-fA-F]+[uU]?
>   	return HASH_VERSION;
>   }
>
> -	/* glcpp doesn't handle #extension, #version, or #pragma directives.
> +{HASH}extension{HSPACE}+ {
> +	return HASH_EXTENSION;
> +}
> +
> +	/* glcpp doesn't handle #pragma directives.
>   	 * Simply pass them through to the main compiler's lexer/parser. */
> -{HASH}(extension|pragma)[^\n]+ {
> +{HASH}pragma[^\n]+ {
>   	yylval->str = ralloc_strdup (yyextra, yytext);
>   	yylineno++;
>   	yycolumn = 0;
>   	return OTHER;
>   }
>
> +{HASH}include{HSPACE}*{STRING}{HSPACE}*$ {
> +	char *ptr = yytext;
> +	while (*ptr != '"')
> +		ptr++;
> +	ptr++;
> +	char *eptr = ptr;
> +	while (*eptr != '"')
> +		eptr++;
> +	*eptr = 0;
> +	yylval->str = ralloc_strdup (yyextra, ptr);
> +	return HASH_INCLUDE;
> +}
> +
> +{HASH}include{HSPACE}*<[^>\n]>+{HSPACE}*$ {
> +	char *ptr = yytext;
> +	while (*ptr != '<')
> +		ptr++;
> +	ptr++;
> +	char *eptr = ptr;
> +	while (*eptr != '>')
> +		eptr++;
> +	*eptr = 0;
> +	yylval->str = ralloc_strdup (yyextra, ptr);
> +	return HASH_INCLUDE;
> +}
> +
>   {HASH}line{HSPACE}+{DIGITS}{HSPACE}+{DIGITS}{HSPACE}*$ {
>   	/* Eat characters until the first digit is
>   	 * encountered
> @@ -142,7 +174,33 @@ HEXADECIMAL_INTEGER	0[xX][0-9a-fA-F]+[uU]?
>   	 * one-based.
>   	 */
>   	yylineno = strtol(ptr,&ptr, 0) - 1;
> -	yylloc->source = strtol(ptr, NULL, 0);
> +	yyextra->source_id = yylloc->source_id = strtol(ptr, NULL, 0);
> +	yyextra->source = yylloc->source = 0;
> +}
> +
> +{HASH}line{HSPACE}+{DIGITS}{HSPACE}+{STRING}{HSPACE}*$ {
> +	/* Eat characters until the first digit is
> +	 * encountered
> +	 */
> +	char *ptr = yytext;
> +	while (!isdigit(*ptr))
> +		ptr++;
> +
> +	/* Subtract one from the line number because
> +	 * yylineno is zero-based instead of
> +	 * one-based.
> +	 */
> +	yylineno = strtol(ptr,&ptr, 0) - 1;
> +
> +	while (*ptr != '"')
> +		ptr++;
> +	ptr++;
> +	char *eptr = ptr;
> +	while (*eptr != '"')
> +		eptr++;
> +	*eptr = 0;
> +	yyextra->source_id = yylloc->source_id = 0;
> +	yyextra->source = yylloc->source = ralloc_strdup(yyextra, ptr);
>   }
>
>   {HASH}line{HSPACE}+{DIGITS}{HSPACE}*$ {
> @@ -328,5 +386,64 @@ HEXADECIMAL_INTEGER	0[xX][0-9a-fA-F]+[uU]?
>   void
>   glcpp_lex_set_source_string(glcpp_parser_t *parser, const char *shader)
>   {
> -	yy_scan_string(shader, parser->scanner);
> +	parser->current_buffer = yy_scan_string(shader, parser->scanner);
> +	glcpp_set_lineno (1, parser->scanner);
> +}
> +
> +
> +void
> +glcpp_push_input (glcpp_parser_t *parser, const char *data, const char *base_path, const char *file_name)
> +{
> +	struct glcpp_parser_input_file *is = ralloc (parser, struct glcpp_parser_input_file);
> +	is->base_path = parser->base_path;
> +	is->buffer = parser->current_buffer;
> +	is->prev = parser->input_stack;
> +
> +	is->source = parser->source;
> +	is->source_id = parser->source_id;
> +
> +	parser->input_stack = is;
> +
> +	parser->base_path = base_path;
> +	glcpp_lex_set_source_string(parser, data);
> +
> +	parser->source = file_name;
> +	parser->source_id = 0;
> +}
> +
> +int
> +glcpp_wrap (yyscan_t scanner)
> +{
> +	glcpp_parser_t *parser = glcpp_get_extra (scanner);
> +	if (glcpp_input_stack_empty (parser))
> +		return 1;
> +	glcpp_pop_input (parser);
> +	return 0;
> +}
> +
> +int
> +glcpp_input_stack_empty (glcpp_parser_t *parser)
> +{
> +	return !parser->input_stack;
> +}
> +
> +void
> +glcpp_pop_input (glcpp_parser_t *parser)
> +{
> +	struct glcpp_parser_input_file *is = parser->input_stack;
> +	parser->input_stack = is->prev;
> +	parser->base_path = is->base_path;
> +	yy_delete_buffer(parser->current_buffer, parser->scanner);
> +	parser->current_buffer = is->buffer;
> +	yy_switch_to_buffer (parser->current_buffer, parser->scanner);
> +
> +	parser->source = is->source;
> +	parser->source_id = is->source_id;
> +
> +	if (parser->source)
> +		ralloc_asprintf_rewrite_tail (&parser->output,&parser->output_length, "#line %d \"%s\"\n", glcpp_get_lineno (parser->scanner)-1, parser->source);
> +	else
> +		ralloc_asprintf_rewrite_tail (&parser->output,&parser->output_length, "#line %d %d\n", glcpp_get_lineno (parser->scanner)-1, parser->source_id);
> +
> +	ralloc_free (is);
>   }
> diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
> index 47ba54d..ec94290 100644
> --- a/src/glsl/glcpp/glcpp-parse.y
> +++ b/src/glsl/glcpp/glcpp-parse.y
> @@ -150,16 +150,17 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
>   	@$.last_line = 1;
>   	@$.last_column = 1;
>   	@$.source = 0;
> +	@$.source_id = 0;
>   }
>
>   %parse-param {glcpp_parser_t *parser}
>   %lex-param {glcpp_parser_t *parser}
>
>   %expect 0
> -%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE
> -%token PASTE
> +%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF HASH_VERSION HASH_INCLUDE HASH_EXTENSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE
> +%token PASTE ':'
>   %type<ival>  expression INTEGER operator SPACE integer_constant
> -%type<str>  IDENTIFIER INTEGER_STRING OTHER
> +%type<str>  IDENTIFIER INTEGER_STRING OTHER HASH_INCLUDE
>   %type<string_list>  identifier_list
>   %type<token>  preprocessing_token conditional_token
>   %type<token_list>  pp_tokens replacement_list text_line conditional_tokens
> @@ -193,6 +194,8 @@ line:
>   	}
>   |	expanded_line
>   |	HASH non_directive
> +|	extension_line
> +|	include_line
>   ;
>
>   expanded_line:
> @@ -325,6 +328,59 @@ control_line:
>   |	HASH NEWLINE
>   ;
>
> +extension_line:
> +	HASH_EXTENSION IDENTIFIER space_or_nothing ':' space_or_nothing IDENTIFIER space_or_nothing NEWLINE {
> +		if (!strcmp ($2, "GL_ARB_shading_language_include")) {
> +			if (!strcmp ($6, "enable") || !strcmp($6, "require"))
> +				parser->include_mode = INCLUDE_OK;
> +			else if (!strcmp ($6, "disable"))
> +				parser->include_mode = INCLUDE_DISABLED;
> +			else if (!strcmp ($6, "warn"))
> +				parser->include_mode = INCLUDE_WARN;
> +			else
> +				yyerror (&  @6, parser, "Unknown extension behavior");
> +		}
> +		else
> +		{
> +			if (!strcmp ($2, "all")) {
> +				if (!strcmp ($6, "warn"))
> +					parser->include_mode = INCLUDE_WARN;
> +				else if (!strcmp ($6, "disable"))
> +					parser->include_mode = INCLUDE_DISABLED;
> +			}
> +			ralloc_asprintf_rewrite_tail (&parser->output,&parser->output_length, "#extension %s : %s\n", $2, $6);
> +			ralloc_free ($2);
> +			ralloc_free ($6);
> +		}
> +	}
> +;
> +
> +include_line:
> +	HASH_INCLUDE {
> +		if (parser->include_mode == INCLUDE_DISABLED)
> +			glcpp_error (&@1, parser, "#include encountered with GL_ARB_shading_language_include disabled\n");
> +		else
> +		{
> +			if (parser->include_mode == INCLUDE_WARN)
> +				glcpp_error (&@1, parser, "#include encountered with GL_ARB_shading_language_include set to warn\n");
> +			char *new_base_path = glcpp_canonicalize_path (parser, parser->base_path, $1);
> +			char *new_file_name = glcpp_add_file_name (parser, new_base_path, $1);
> +			const char *subshader = parser->include_get_string (parser->include_param, new_file_name);
> +			if (!subshader)
> +				glcpp_error (&@1, parser, "Could not find string for inclusion: %s\n", new_file_name);
> +			else {
> +				ralloc_asprintf_rewrite_tail (&parser->output,&parser->output_length, "#line 1 \"%s\"\n", new_file_name);
> +				glcpp_push_input (parser, subshader, new_base_path, new_file_name);
> +			}
> +		}
> +	}
> +;
> +
> +space_or_nothing:
> +	SPACE
> +|	/* empty */
> +;
> +
>   integer_constant:
>   	INTEGER_STRING {
>   		if (strlen ($1)>= 3&&  strncmp ($1, "0x", 2) == 0) {
> @@ -551,7 +607,6 @@ operator:
>   |	'='			{ $$ = '='; }
>   |	PASTE			{ $$ = PASTE; }
>   ;
> -
>   %%
>
>   string_list_t *
> @@ -1081,7 +1136,9 @@ static void add_builtin_define(glcpp_parser_t *parser,
>   }
>
>   glcpp_parser_t *
> -glcpp_parser_create (const struct gl_extensions *extensions, int api)
> +glcpp_parser_create (const struct gl_extensions *extensions, int api,
> +	   const char *base_path,
> +	   const char *(*get_string)(void *param, const char *), void *param)
>   {
>   	glcpp_parser_t *parser;
>   	int language_version;
> @@ -1097,6 +1154,13 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
>   	parser->newline_as_space = 0;
>   	parser->in_control_line = 0;
>   	parser->paren_count = 0;
> +	parser->include_mode = INCLUDE_DISABLED;
> +	parser->base_path = base_path;
> +	parser->include_get_string = get_string;
> +	parser->include_param = param;
> +	parser->input_stack = NULL;
> +	parser->source = 0;
> +	parser->source_id = 0;
>
>   	parser->skip_stack = NULL;
>
> @@ -1763,7 +1827,6 @@ glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser)
>
>   	if (parser->lex_from_list == NULL) {
>   		ret = glcpp_lex (yylval, yylloc, parser->scanner);
> -
>   		/* XXX: This ugly block of code exists for the sole
>   		 * purpose of converting a NEWLINE token into a SPACE
>   		 * token, but only in the case where we have seen a
> diff --git a/src/glsl/glcpp/glcpp.c b/src/glsl/glcpp/glcpp.c
> index e461a65..8fce570 100644
> --- a/src/glsl/glcpp/glcpp.c
> +++ b/src/glsl/glcpp/glcpp.c
> @@ -24,6 +24,7 @@
>   #include<stdio.h>
>   #include<string.h>
>   #include<errno.h>
> +#include<unistd.h>
>   #include "glcpp.h"
>   #include "main/mtypes.h"
>   #include "main/shaderobj.h"
> @@ -94,6 +95,12 @@ load_text_file(void *ctx, const char *filename)
>   	return text;
>   }
>
> +static const char *
> +get_string (void *ctx, const char *name)
> +{
> +	return load_text_file(ctx, name);
> +}
> +
>   int
>   main (int argc, char *argv[])
>   {
> @@ -107,11 +114,16 @@ main (int argc, char *argv[])
>   		filename = argv[1];
>   	}
>
> +	char *cur_dir = get_current_dir_name();
> +	char *base_path = glcpp_canonicalize_path(NULL, cur_dir, filename ? filename : "");
> +	free(cur_dir);
> +
>   	shader = load_text_file (ctx, filename);
>   	if (shader == NULL)
>   	   return 1;
>
> -	ret = preprocess(ctx,&shader,&info_log, NULL, API_OPENGL);
> +	ret = preprocess(ctx,&shader,&info_log, NULL, API_OPENGL, base_path, get_string, ctx);
> +	ralloc_free(base_path);
>
>   	printf("%s", shader);
>   	fprintf(stderr, "%s", info_log);
> diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h
> index 2d7cad2..ebcd90b 100644
> --- a/src/glsl/glcpp/glcpp.h
> +++ b/src/glsl/glcpp/glcpp.h
> @@ -64,10 +64,11 @@ typedef struct YYLTYPE {
>      int first_column;
>      int last_line;
>      int last_column;
> -   unsigned source;
> +   const char *source;
> +   unsigned source_id;
>   } YYLTYPE;
>   # define YYLTYPE_IS_DECLARED 1
> -# define YYLTYPE_IS_TRIVIAL 1
> +# undef YYLTYPE_IS_TRIVIAL
>
>   # define YYLLOC_DEFAULT(Current, Rhs, N)			\
>   do {								\
> @@ -77,6 +78,8 @@ do {								\
>         (Current).first_column = YYRHSLOC(Rhs, 1).first_column;	\
>         (Current).last_line    = YYRHSLOC(Rhs, N).last_line;	\
>         (Current).last_column  = YYRHSLOC(Rhs, N).last_column;	\
> +      (Current).source       = YYRHSLOC(Rhs, 1).source;         \
> +      (Current).source_id    = YYRHSLOC(Rhs, 1).source_id;      \
>      }								\
>      else								\
>      {								\
> @@ -84,6 +87,8 @@ do {								\
>   	 YYRHSLOC(Rhs, 0).last_line;				\
>         (Current).first_column = (Current).last_column =		\
>   	 YYRHSLOC(Rhs, 0).last_column;				\
> +      (Current).source       = YYRHSLOC(Rhs, 0).source;         \
> +      (Current).source_id    = YYRHSLOC(Rhs, 0).source_id;      \
>      }								\
>      (Current).source = 0;					\
>   } while (0)
> @@ -160,6 +165,20 @@ typedef struct active_list {
>   	struct active_list *next;
>   } active_list_t;
>
> +typedef enum {
> +	INCLUDE_DISABLED,
> +	INCLUDE_WARN,
> +	INCLUDE_OK
> +} include_mode_t;
> +
> +struct glcpp_parser_input_file {
> +	struct glcpp_parser_input_file *prev;
> +	struct yy_buffer_state *buffer;
> +	const char *base_path;
> +	const char *source;
> +	unsigned source_id;
> +};
> +
>   struct glcpp_parser {
>   	yyscan_t scanner;
>   	struct hash_table *defines;
> @@ -169,6 +188,7 @@ struct glcpp_parser {
>   	int newline_as_space;
>   	int in_control_line;
>   	int paren_count;
> +	include_mode_t include_mode;
>   	skip_node_t *skip_stack;
>   	token_list_t *lex_from_list;
>   	token_node_t *lex_from_node;
> @@ -177,12 +197,21 @@ struct glcpp_parser {
>   	size_t output_length;
>   	size_t info_log_length;
>   	int error;
> +	unsigned int source_id;
> +	const char *base_path;
> +	const char *source;
> +	const char *(*include_get_string)(void *param, const char *);
> +	void *include_param;
> +	struct yy_buffer_state *current_buffer;
> +	struct glcpp_parser_input_file *input_stack;
>   };
>
>   struct gl_extensions;
>
>   glcpp_parser_t *
> -glcpp_parser_create (const struct gl_extensions *extensions, int api);
> +glcpp_parser_create (const struct gl_extensions *extensions, int api,
> +		     const char *base_path,
> +		     const char *(*get_string)(void *param, const char *), void *param);
>
>   int
>   glcpp_parser_parse (glcpp_parser_t *parser);
> @@ -192,7 +221,9 @@ glcpp_parser_destroy (glcpp_parser_t *parser);
>
>   int
>   preprocess(void *ralloc_ctx, const char **shader, char **info_log,
> -	   const struct gl_extensions *extensions, int api);
> +	   const struct gl_extensions *extensions, int api,
> +	   const char *base_path,
> +	   const char *(*get_string)(void *param, const char *), void *param);
>
>   /* Functions for writing to the info log */
>
> @@ -202,6 +233,23 @@ glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...);
>   void
>   glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...);
>
> +/* Functions for include support */
> +
> +char *
> +glcpp_canonicalize_path (void *ctx, const char *base_path, const char *file_name);
> +
> +char *
> +glcpp_add_file_name (void *ctx, const char *base_path, const char *file_name);
> +
> +void
> +glcpp_push_input (glcpp_parser_t *parser, const char *data, const char *base_path, const char *file_name);
> +
> +int
> +glcpp_input_stack_empty (glcpp_parser_t *parser);
> +
> +void
> +glcpp_pop_input (glcpp_parser_t *parser);
> +
>   /* Generated by glcpp-lex.l to glcpp-lex.c */
>
>   int
> diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c
> index 3640896..10c239c 100644
> --- a/src/glsl/glcpp/pp.c
> +++ b/src/glsl/glcpp/pp.c
> @@ -32,10 +32,17 @@ glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
>   {
>   	va_list ap;
>
> +	char sbuf[12];
> +	const char *source = locp->source;
> +	if (!source) {
> +		source = sbuf;
> +		sprintf (sbuf, "%u", locp->source_id);
> +	}
> +
>   	parser->error = 1;
> -	ralloc_asprintf_append(&parser->info_log, "%u:%u(%u): "
> +	ralloc_asprintf_append(&parser->info_log, "%s:%u(%u): "
>   						  "preprocessor error: ",
> -						  locp->source,
> +						  source,
>   						  locp->first_line,
>   						  locp->first_column);
>   	va_start(ap, fmt);
> @@ -49,9 +56,15 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
>   {
>   	va_list ap;
>
> -	ralloc_asprintf_append(&parser->info_log, "%u:%u(%u): "
> +	char sbuf[12];
> +	const char *source = locp->source;
> +	if (!source) {
> +		source = sbuf;
> +		sprintf (sbuf, "%u", locp->source_id);
> +	}
> +	ralloc_asprintf_append(&parser->info_log, "%s:%u(%u): "
>   						  "preprocessor warning: ",
> -						  locp->source,
> +						  source,
>   						  locp->first_line,
>   						  locp->first_column);
>   	va_start(ap, fmt);
> @@ -60,6 +73,71 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
>   	ralloc_strcat(&parser->info_log, "\n");
>   }
>
> +char *
> +glcpp_canonicalize_path(void *ctx, const char *base_path, const char *file_name)
> +{
> +	if(file_name[0] == '/')
> +		base_path = "";
> +
> +	char *res = ralloc_size(ctx, strlen(base_path) + strlen(file_name) + 2);
> +	sprintf(res, "%s/%s", base_path, file_name);
> +
> +	// Cleanup //, . and .. and final file name
> +
> +	// base_path, and hence the buffer, will always start with '/'
> +
> +	// rp is the current read position, prp is the position of the
> +	// first character after the previous '/', wp is the (re)write
> +	// position
> +
> +	const char *rp = res+1;
> +	const char *prp = res+1;
> +	char *wp = res;
> +	while(*rp) {
> +		if(*rp == '/') {
> +			// Eliminate successions of '/'
> +			if(rp == prp) {
> +			}
> +			// Drop '.'
> +			else if(rp == prp+1&&  prp[0] == '.') {
> +			}
> +			// Rewind one level on '..', don't go past the beginning of buffer
> +			else if(rp == prp+2&&  prp[0] == '.'&&  prp[1] == '.') {
> +				while(wp != res&&  wp[-1] != '/')
> +					wp--;
> +			}
> +			// Copy path element
> +			else
> +			{
> +				*wp++ = '/';
> +				while(prp != rp)
> +					*wp++ = *prp++;
> +			}
> +			rp++;
> +			prp = rp;
> +		}
> +		else
> +			rp++;
> +	}
> +	*wp = 0;
> +
> +	return res;
> +}
> +
> +char *
> +glcpp_add_file_name(void *ctx, const char *base_path, const char *file_name)
> +{
> +	const char *slash_pos = strrchr(file_name, '/');
> +	if(slash_pos)
> +		slash_pos++;
> +	else
> +		slash_pos = file_name;
> +
> +	char *res = ralloc_size(ctx, strlen(base_path) + strlen(slash_pos) + 2);
> +	sprintf(res, "%s/%s", base_path, slash_pos);
> +	return res;
> +}
> +
>   /* Searches backwards for '^ *#' from a given starting point. */
>   static int
>   in_directive(const char *shader, const char *ptr)
> @@ -141,10 +219,12 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
>
>   int
>   preprocess(void *ralloc_ctx, const char **shader, char **info_log,
> -	   const struct gl_extensions *extensions, int api)
> +	   const struct gl_extensions *extensions, int api,
> +	   const char *base_path,
> +	   const char *(*get_string)(void *param, const char *), void *param)
>   {
>   	int errors;
> -	glcpp_parser_t *parser = glcpp_parser_create (extensions, api);
> +	glcpp_parser_t *parser = glcpp_parser_create (extensions, api, base_path, get_string, param);
>   	*shader = remove_line_continuations(parser, *shader);
>
>   	glcpp_lex_set_source_string (parser, *shader);
> diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
> index 936a907..b604ce6 100644
> --- a/src/glsl/glsl_lexer.ll
> +++ b/src/glsl/glsl_lexer.ll
> @@ -36,7 +36,8 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
>
>   #define YY_USER_ACTION						\
>      do {								\
> -      yylloc->source = 0;					\
> +      yylloc->source = yyextra->source;				\
> +      yylloc->source_id = yyextra->source_id;			\
>         yylloc->first_column = yycolumn + 1;			\
>         yylloc->first_line = yylineno + 1;			\
>         yycolumn += yyleng;					\
> @@ -142,6 +143,7 @@ INT		({DEC_INT}|{HEX_INT}|{OCT_INT})
>   SPC		[ \t]*
>   SPCP		[ \t]+
>   HASH		^{SPC}#{SPC}
> +STR		"\""[^"\n]+"\""
>   %%
>
>   [ \r\t]+		;
> @@ -163,7 +165,33 @@ HASH		^{SPC}#{SPC}
>   				    * one-based.
>   				    */
>   				   yylineno = strtol(ptr,&ptr, 0) - 1;
> -				   yylloc->source = strtol(ptr, NULL, 0);
> +				   yyextra->source_id = yylloc->source_id = strtol(ptr, NULL, 0);
> +				   yyextra->source = yylloc->source = 0;
> +				}
> +{HASH}line{SPCP}{INT}{SPCP}{STR}{SPC}$ {
> +				   /* Eat characters until the first digit is
> +				    * encountered
> +				    */
> +				   char *ptr = yytext;
> +				   while (!isdigit(*ptr))
> +				      ptr++;
> +
> +				   while (*ptr != '"')
> +				      ptr++;
> +				   ptr++;
> +				   char *eptr = ptr;
> +				   while (*eptr != '"')
> +				      eptr++;
> +				   *eptr = 0;
> +
> +				   yyextra->source_id = yylloc->source_id = 0;
> +				   yyextra->source = yylloc->source = strdup(ptr);
> +// must use ralloc_strdup
> +				   /* Subtract one from the line number because
> +				    * yylineno is zero-based instead of
> +				    * one-based.
> +				    */
> +				   yylineno = strtol(ptr,&ptr, 0) - 1;
>   				}
>   {HASH}line{SPCP}{INT}{SPC}$	{
>   				   /* Eat characters until the first digit is
> diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
> index 9a0af95..ac834eb 100644
> --- a/src/glsl/glsl_parser.yy
> +++ b/src/glsl/glsl_parser.yy
> @@ -50,6 +50,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
>      @$.last_line = 1;
>      @$.last_column = 1;
>      @$.source = 0;
> +   @$.source_id = 0;
>   }
>
>   %lex-param   {void *scanner}
> @@ -353,35 +354,35 @@ primary_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_identifier, NULL, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->primary_expression.identifier = $1;
>   	}
>   	| INTCONSTANT
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_int_constant, NULL, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->primary_expression.int_constant = $1;
>   	}
>   	| UINTCONSTANT
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_uint_constant, NULL, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->primary_expression.uint_constant = $1;
>   	}
>   	| FLOATCONSTANT
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_float_constant, NULL, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->primary_expression.float_constant = $1;
>   	}
>   	| BOOLCONSTANT
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_bool_constant, NULL, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->primary_expression.bool_constant = $1;
>   	}
>   	| '(' expression ')'
> @@ -396,7 +397,7 @@ postfix_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_array_index, $1, $3, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| function_call
>   	{
> @@ -406,20 +407,20 @@ postfix_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_field_selection, $1, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->primary_expression.identifier = $3;
>   	}
>   	| postfix_expression INC_OP
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_post_inc, $1, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| postfix_expression DEC_OP
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_post_dec, $1, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -437,7 +438,7 @@ function_call_or_method:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_field_selection, $1, $3, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -455,13 +456,13 @@ function_call_header_with_parameters:
>   	function_call_header assignment_expression
>   	{
>   	   $$ = $1;
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	   $$->expressions.push_tail(&  $2->link);
>   	}
>   	| function_call_header_with_parameters ',' assignment_expression
>   	{
>   	   $$ = $1;
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	   $$->expressions.push_tail(&  $3->link);
>   	}
>   	;
> @@ -478,21 +479,21 @@ function_identifier:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_function_expression($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>      	}
>   	| variable_identifier
>   	{
>   	   void *ctx = state;
>   	   ast_expression *callee = new(ctx) ast_expression($1);
>   	   $$ = new(ctx) ast_function_expression(callee);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>      	}
>   	| FIELD_SELECTION
>   	{
>   	   void *ctx = state;
>   	   ast_expression *callee = new(ctx) ast_expression($1);
>   	   $$ = new(ctx) ast_function_expression(callee);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>      	}
>   	;
>
> @@ -510,13 +511,13 @@ method_call_header_with_parameters:
>   	method_call_header assignment_expression
>   	{
>   	   $$ = $1;
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	   $$->expressions.push_tail(&  $2->link);
>   	}
>   	| method_call_header_with_parameters ',' assignment_expression
>   	{
>   	   $$ = $1;
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	   $$->expressions.push_tail(&  $3->link);
>   	}
>   	;
> @@ -530,7 +531,7 @@ method_call_header:
>   	   void *ctx = state;
>   	   ast_expression *callee = new(ctx) ast_expression($1);
>   	   $$ = new(ctx) ast_function_expression(callee);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>      	}
>   	;
>
> @@ -541,19 +542,19 @@ unary_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_pre_inc, $2, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| DEC_OP unary_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_pre_dec, $2, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| unary_operator unary_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression($1, $2, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -571,19 +572,19 @@ multiplicative_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_mul, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| multiplicative_expression '/' unary_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_div, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| multiplicative_expression '%' unary_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_mod, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -593,13 +594,13 @@ additive_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_add, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| additive_expression '-' multiplicative_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_sub, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -609,13 +610,13 @@ shift_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_lshift, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| shift_expression RIGHT_OP additive_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_rshift, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -625,25 +626,25 @@ relational_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_less, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| relational_expression '>' shift_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_greater, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| relational_expression LE_OP shift_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_lequal, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| relational_expression GE_OP shift_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_gequal, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -653,13 +654,13 @@ equality_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_equal, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| equality_expression NE_OP relational_expression
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_nequal, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -669,7 +670,7 @@ and_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_bit_and, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -679,7 +680,7 @@ exclusive_or_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_bit_xor, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -689,7 +690,7 @@ inclusive_or_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_bit_or, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -699,7 +700,7 @@ logical_and_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_logic_and, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -709,7 +710,7 @@ logical_xor_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_logic_xor, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -719,7 +720,7 @@ logical_or_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_bin(ast_logic_or, $1, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -729,7 +730,7 @@ conditional_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression(ast_conditional, $1, $3, $5);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -739,7 +740,7 @@ assignment_expression:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression($2, $1, $3, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -767,7 +768,7 @@ expression:
>   	   void *ctx = state;
>   	   if ($1->oper != ast_sequence) {
>   	      $$ = new(ctx) ast_expression(ast_sequence, NULL, NULL, NULL);
> -	      $$->set_location(yylloc);
> +	      $$->set_location(yylloc, ctx);
>   	      $$->expressions.push_tail(&  $1->link);
>   	   } else {
>   	      $$ = $1;
> @@ -826,7 +827,7 @@ function_header:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_function();
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->return_type = $1;
>   	   $$->identifier = $2;
>
> @@ -840,9 +841,9 @@ parameter_declarator:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_parameter_declarator();
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->type = new(ctx) ast_fully_specified_type();
> -	   $$->type->set_location(yylloc);
> +	   $$->type->set_location(yylloc, ctx);
>   	   $$->type->specifier = $1;
>   	   $$->identifier = $2;
>   	}
> @@ -850,9 +851,9 @@ parameter_declarator:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_parameter_declarator();
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->type = new(ctx) ast_fully_specified_type();
> -	   $$->type->set_location(yylloc);
> +	   $$->type->set_location(yylloc, ctx);
>   	   $$->type->specifier = $1;
>   	   $$->identifier = $2;
>   	   $$->is_array = true;
> @@ -879,7 +880,7 @@ parameter_declaration:
>   	   $1.flags.i |= $2.flags.i;
>
>   	   $$ = new(ctx) ast_parameter_declarator();
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->type = new(ctx) ast_fully_specified_type();
>   	   $$->type->qualifier = $1;
>   	   $$->type->specifier = $3;
> @@ -888,7 +889,7 @@ parameter_declaration:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_parameter_declarator();
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->type = new(ctx) ast_fully_specified_type();
>   	   $$->type->qualifier = $1;
>   	   $$->type->specifier = $2;
> @@ -928,7 +929,7 @@ init_declarator_list:
>   	{
>   	   void *ctx = state;
>   	   ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, NULL);
> -	   decl->set_location(yylloc);
> +	   decl->set_location(yylloc, ctx);
>
>   	   $$ = $1;
>   	   $$->declarations.push_tail(&decl->link);
> @@ -938,7 +939,7 @@ init_declarator_list:
>   	{
>   	   void *ctx = state;
>   	   ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, NULL);
> -	   decl->set_location(yylloc);
> +	   decl->set_location(yylloc, ctx);
>
>   	   $$ = $1;
>   	   $$->declarations.push_tail(&decl->link);
> @@ -948,7 +949,7 @@ init_declarator_list:
>   	{
>   	   void *ctx = state;
>   	   ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, NULL);
> -	   decl->set_location(yylloc);
> +	   decl->set_location(yylloc, ctx);
>
>   	   $$ = $1;
>   	   $$->declarations.push_tail(&decl->link);
> @@ -958,7 +959,7 @@ init_declarator_list:
>   	{
>   	   void *ctx = state;
>   	   ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, $7);
> -	   decl->set_location(yylloc);
> +	   decl->set_location(yylloc, ctx);
>
>   	   $$ = $1;
>   	   $$->declarations.push_tail(&decl->link);
> @@ -968,7 +969,7 @@ init_declarator_list:
>   	{
>   	   void *ctx = state;
>   	   ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, $8);
> -	   decl->set_location(yylloc);
> +	   decl->set_location(yylloc, ctx);
>
>   	   $$ = $1;
>   	   $$->declarations.push_tail(&decl->link);
> @@ -978,7 +979,7 @@ init_declarator_list:
>   	{
>   	   void *ctx = state;
>   	   ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, $5);
> -	   decl->set_location(yylloc);
> +	   decl->set_location(yylloc, ctx);
>
>   	   $$ = $1;
>   	   $$->declarations.push_tail(&decl->link);
> @@ -993,7 +994,7 @@ single_declaration:
>   	   void *ctx = state;
>   	   /* Empty declaration list is valid. */
>   	   $$ = new(ctx) ast_declarator_list($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| fully_specified_type any_identifier
>   	{
> @@ -1001,7 +1002,7 @@ single_declaration:
>   	   ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
>
>   	   $$ = new(ctx) ast_declarator_list($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->declarations.push_tail(&decl->link);
>   	}
>   	| fully_specified_type any_identifier '[' ']'
> @@ -1010,7 +1011,7 @@ single_declaration:
>   	   ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, NULL);
>
>   	   $$ = new(ctx) ast_declarator_list($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->declarations.push_tail(&decl->link);
>   	}
>   	| fully_specified_type any_identifier '[' constant_expression ']'
> @@ -1019,7 +1020,7 @@ single_declaration:
>   	   ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, NULL);
>
>   	   $$ = new(ctx) ast_declarator_list($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->declarations.push_tail(&decl->link);
>   	}
>   	| fully_specified_type any_identifier '[' ']' '=' initializer
> @@ -1028,7 +1029,7 @@ single_declaration:
>   	   ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, $6);
>
>   	   $$ = new(ctx) ast_declarator_list($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->declarations.push_tail(&decl->link);
>   	}
>   	| fully_specified_type any_identifier '[' constant_expression ']' '=' initializer
> @@ -1037,7 +1038,7 @@ single_declaration:
>   	   ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, $7);
>
>   	   $$ = new(ctx) ast_declarator_list($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->declarations.push_tail(&decl->link);
>   	}
>   	| fully_specified_type any_identifier '=' initializer
> @@ -1046,7 +1047,7 @@ single_declaration:
>   	   ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
>
>   	   $$ = new(ctx) ast_declarator_list($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->declarations.push_tail(&decl->link);
>   	}
>   	| INVARIANT variable_identifier // Vertex only.
> @@ -1055,7 +1056,7 @@ single_declaration:
>   	   ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
>
>   	   $$ = new(ctx) ast_declarator_list(NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->invariant = true;
>
>   	   $$->declarations.push_tail(&decl->link);
> @@ -1067,14 +1068,14 @@ fully_specified_type:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_fully_specified_type();
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->specifier = $1;
>   	}
>   	| type_qualifier type_specifier
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_fully_specified_type();
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->qualifier = $1;
>   	   $$->specifier = $2;
>   	}
> @@ -1347,19 +1348,19 @@ type_specifier_nonarray:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_type_specifier($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| struct_specifier
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_type_specifier($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| TYPE_IDENTIFIER
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_type_specifier($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -1456,14 +1457,14 @@ struct_specifier:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_struct_specifier($2, $4);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   state->symbols->add_type($2, glsl_type::void_type);
>   	}
>   	| STRUCT '{' struct_declaration_list '}'
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_struct_specifier(NULL, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -1485,11 +1486,11 @@ struct_declaration:
>   	{
>   	   void *ctx = state;
>   	   ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
> -	   type->set_location(yylloc);
> +	   type->set_location(yylloc, ctx);
>
>   	   type->specifier = $1;
>   	   $$ = new(ctx) ast_declarator_list(type);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>
>   	   $$->declarations.push_degenerate_list_at_head(&  $2->link);
>   	}
> @@ -1513,14 +1514,14 @@ struct_declarator:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   state->symbols->add_variable(new(state) ir_variable(NULL, $1, ir_var_auto));
>   	}
>   	| any_identifier '[' constant_expression ']'
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_declaration($1, true, $3, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -1553,7 +1554,7 @@ compound_statement:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_compound_statement(true, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| '{'
>   	{
> @@ -1563,7 +1564,7 @@ compound_statement:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_compound_statement(true, $3);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   state->symbols->pop_scope();
>   	}
>   	;
> @@ -1578,13 +1579,13 @@ compound_statement_no_new_scope:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_compound_statement(false, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| '{' statement_list '}'
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_compound_statement(false, $2);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -1615,13 +1616,13 @@ expression_statement:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_statement(NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| expression ';'
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_expression_statement($1);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -1630,7 +1631,7 @@ selection_statement:
>   	{
>   	   $$ = new(state) ast_selection_statement($3, $5.then_statement,
>   						   $5.else_statement);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	}
>   	;
>
> @@ -1657,8 +1658,8 @@ condition:
>   	   void *ctx = state;
>   	   ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
>   	   ast_declarator_list *declarator = new(ctx) ast_declarator_list($1);
> -	   decl->set_location(yylloc);
> -	   declarator->set_location(yylloc);
> +	   decl->set_location(yylloc, ctx);
> +	   declarator->set_location(yylloc, ctx);
>
>   	   declarator->declarations.push_tail(&decl->link);
>   	   $$ = declarator;
> @@ -1673,7 +1674,7 @@ switch_statement:
>   	SWITCH '(' expression ')' switch_body
>   	{
>   	   $$ = new(state) ast_switch_statement($3, $5);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	}
>   	;
>
> @@ -1681,12 +1682,12 @@ switch_body:
>   	'{' '}'
>   	{
>   	   $$ = new(state) ast_switch_body(NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	}
>   	| '{' case_statement_list '}'
>   	{
>   	   $$ = new(state) ast_switch_body($2);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	}
>   	;
>
> @@ -1694,12 +1695,12 @@ case_label:
>   	CASE expression ':'
>   	{
>   	   $$ = new(state) ast_case_label($2);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	}
>   	| DEFAULT ':'
>   	{
>   	   $$ = new(state) ast_case_label(NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	}
>   	;
>
> @@ -1710,7 +1711,7 @@ case_label_list:
>
>   	   labels->labels.push_tail(&  $1->link);
>   	   $$ = labels;
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, state);
>   	}
>   	| case_label_list case_label
>   	{
> @@ -1723,7 +1724,7 @@ case_statement:
>   	case_label_list statement
>   	{
>   	   ast_case_statement *stmts = new(state) ast_case_statement($1);
> -	   stmts->set_location(yylloc);
> +	   stmts->set_location(yylloc, state);
>
>   	   stmts->stmts.push_tail(&  $2->link);
>   	   $$ = stmts;
> @@ -1739,7 +1740,7 @@ case_statement_list:
>   	case_statement
>   	{
>   	   ast_case_statement_list *cases= new(state) ast_case_statement_list();
> -	   cases->set_location(yylloc);
> +	   cases->set_location(yylloc, state);
>
>   	   cases->cases.push_tail(&  $1->link);
>   	   $$ = cases;
> @@ -1757,21 +1758,21 @@ iteration_statement:
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_while,
>   	   					    NULL, $3, NULL, $5);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| DO statement WHILE '(' expression ')' ';'
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_do_while,
>   						    NULL, $5, NULL, $2);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| FOR '(' for_init_statement for_rest_statement ')' statement_no_new_scope
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_iteration_statement(ast_iteration_statement::ast_for,
>   						    $3, $4.cond, $4.rest, $6);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -1807,31 +1808,31 @@ jump_statement:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_continue, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| BREAK ';'
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_break, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| RETURN ';'
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| RETURN expression ';'
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_return, $2);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	| DISCARD ';' // Fragment shader only.
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_jump_statement(ast_jump_statement::ast_discard, NULL);
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	}
>   	;
>
> @@ -1846,7 +1847,7 @@ function_definition:
>   	{
>   	   void *ctx = state;
>   	   $$ = new(ctx) ast_function_definition();
> -	   $$->set_location(yylloc);
> +	   $$->set_location(yylloc, ctx);
>   	   $$->prototype = $1;
>   	   $$->body = $2;
>
> diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
> index 21c3c6e..9954952 100644
> --- a/src/glsl/glsl_parser_extras.cpp
> +++ b/src/glsl/glsl_parser_extras.cpp
> @@ -141,11 +141,18 @@ _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
>   {
>      va_list ap;
>
> +   char sbuf[12];
> +   const char *source = locp->source;
> +   if (!source) {
> +      source = sbuf;
> +      sprintf (sbuf, "%u", locp->source_id);
> +   }
> +
>      state->error = true;
>
>      assert(state->info_log != NULL);
> -   ralloc_asprintf_append(&state->info_log, "%u:%u(%u): error: ",
> -					    locp->source,
> +   ralloc_asprintf_append(&state->info_log, "%s:%u(%u): error: ",
> +					    source,
>   					    locp->first_line,
>   					    locp->first_column);
>      va_start(ap, fmt);
> @@ -161,9 +168,16 @@ _mesa_glsl_warning(const YYLTYPE *locp, _mesa_glsl_parse_state *state,
>   {
>      va_list ap;
>
> +   char sbuf[12];
> +   const char *source = locp->source;
> +   if (!source) {
> +      source = sbuf;
> +      sprintf (sbuf, "%u", locp->source_id);
> +   }
> +
>      assert(state->info_log != NULL);
> -   ralloc_asprintf_append(&state->info_log, "%u:%u(%u): warning: ",
> -					    locp->source,
> +   ralloc_asprintf_append(&state->info_log, "%s:%u(%u): warning: ",
> +					    source,
>   					    locp->first_line,
>   					    locp->first_column);
>      va_start(ap, fmt);
> @@ -464,6 +478,7 @@ ast_node::print(void) const
>
>   ast_node::ast_node(void)
>   {
> +   this->location.source_id = 0;
>      this->location.source = 0;
>      this->location.line = 0;
>      this->location.column = 0;
> diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h
> index 55676f5..8c8ab8e 100644
> --- a/src/glsl/glsl_parser_extras.h
> +++ b/src/glsl/glsl_parser_extras.h
> @@ -212,6 +212,10 @@ struct _mesa_glsl_parse_state {
>      /** Shaders containing built-in functions that are used for linking. */
>      struct gl_shader *builtins_to_link[16];
>      unsigned num_builtins_to_link;
> +
> +   /** Source currently being parsed */
> +   unsigned source_id;
> +   char *source;
>   };
>
>   typedef struct YYLTYPE {
> @@ -219,7 +223,8 @@ typedef struct YYLTYPE {
>      int first_column;
>      int last_line;
>      int last_column;
> -   unsigned source;
> +   unsigned source_id;
> +   char *source;
>   } YYLTYPE;
>   # define YYLTYPE_IS_DECLARED 1
>   # define YYLTYPE_IS_TRIVIAL 1
> @@ -232,6 +237,8 @@ do {								\
>         (Current).first_column = YYRHSLOC(Rhs, 1).first_column;	\
>         (Current).last_line    = YYRHSLOC(Rhs, N).last_line;	\
>         (Current).last_column  = YYRHSLOC(Rhs, N).last_column;	\
> +      (Current).source       = YYRHSLOC(Rhs, 1).source;		\
> +      (Current).source_id    = YYRHSLOC(Rhs, 1).source_id;	\
>      }								\
>      else								\
>      {								\
> @@ -239,8 +246,9 @@ do {								\
>   	 YYRHSLOC(Rhs, 0).last_line;				\
>         (Current).first_column = (Current).last_column =		\
>   	 YYRHSLOC(Rhs, 0).last_column;				\
> +      (Current).source       = YYRHSLOC(Rhs, 0).source;		\
> +      (Current).source_id    = YYRHSLOC(Rhs, 0).source_id;	\
>      }								\
> -   (Current).source = 0;					\
>   } while (0)
>
>   extern void _mesa_glsl_error(YYLTYPE *locp, _mesa_glsl_parse_state *state,
> @@ -296,7 +304,9 @@ extern "C" {
>   #endif
>
>   extern int preprocess(void *ctx, const char **shader, char **info_log,
> -                      const struct gl_extensions *extensions, int api);
> +                      const struct gl_extensions *extensions, int api,
> +		      const char *base_path,
> +		      const char *(*get_string)(void *param, const char *), void *param);
>
>   extern void _mesa_destroy_shader_compiler(void);
>   extern void _mesa_destroy_shader_compiler_caches(void);
> diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp
> index d43bf1a..5a005a3 100644
> --- a/src/glsl/main.cpp
> +++ b/src/glsl/main.cpp
> @@ -21,6 +21,7 @@
>    * DEALINGS IN THE SOFTWARE.
>    */
>   #include<getopt.h>
> +#include<unistd.h>
>
>   #include "ast.h"
>   #include "glsl_parser_extras.h"
> @@ -129,14 +130,17 @@ usage_fail(const char *name)
>
>
>   void
> -compile_shader(struct gl_context *ctx, struct gl_shader *shader)
> +compile_shader(struct gl_context *ctx, struct gl_shader *shader,
> +	       const char *base_path,
> +	       const char *(*get_string)(void *param, const char *), void *param)
>   {
>      struct _mesa_glsl_parse_state *state =
>         new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
>
>      const char *source = shader->Source;
>      state->error = preprocess(state,&source,&state->info_log,
> -			     state->extensions, ctx->API) != 0;
> +			     state->extensions, ctx->API,
> +			     base_path, get_string, param) != 0;
>
>      if (!state->error) {
>         _mesa_glsl_lexer_ctor(state, source);
> @@ -198,6 +202,14 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader)
>      return;
>   }
>
> +static const char *
> +get_string(void *ctx, const char *name)
> +{
> +   return load_text_file(ctx, name);
> +}
> +
> +extern "C" char *glcpp_canonicalize_path(void *ctx, const char *base_path, const char *file_name);
> +
>   int
>   main(int argc, char **argv)
>   {
> @@ -222,6 +234,8 @@ main(int argc, char **argv)
>      assert(whole_program != NULL);
>      whole_program->InfoLog = ralloc_strdup(whole_program, "");
>
> +   char *cur_dir = get_current_dir_name();
> +
>      for (/* empty */; argc>  optind; optind++) {
>         whole_program->Shaders =
>   	 reralloc(whole_program, whole_program->Shaders,
> @@ -247,13 +261,15 @@ main(int argc, char **argv)
>         else
>   	 usage_fail(argv[0]);
>
> +
>         shader->Source = load_text_file(whole_program, argv[optind]);
>         if (shader->Source == NULL) {
>   	 printf("File \"%s\" does not exist.\n", argv[optind]);
>   	 exit(EXIT_FAILURE);
>         }
>
> -      compile_shader(ctx, shader);
> +      char *base_path = glcpp_canonicalize_path(whole_program, cur_dir, argv[optind]);
> +      compile_shader(ctx, shader, base_path, get_string, whole_program);
>
>         if (!shader->CompileStatus) {
>   	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
> @@ -262,6 +278,8 @@ main(int argc, char **argv)
>         }
>      }
>
> +   free(cur_dir);
> +
>      if ((status == EXIT_SUCCESS)&&  do_link)  {
>         link_shaders(ctx, whole_program);
>         status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
> diff --git a/src/glsl/test_optpass.cpp b/src/glsl/test_optpass.cpp
> index 6abafb5..e3c7e1c 100644
> --- a/src/glsl/test_optpass.cpp
> +++ b/src/glsl/test_optpass.cpp
> @@ -219,7 +219,7 @@ int test_optpass(int argc, char **argv)
>         shader->Source = input.c_str();
>         const char *source = shader->Source;
>         state->error = preprocess(state,&source,&state->info_log,
> -                                state->extensions, ctx->API) != 0;
> +                                state->extensions, ctx->API, 0, 0, 0) != 0;
>
>         if (!state->error) {
>            _mesa_glsl_lexer_ctor(state, source);
> diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
> index 697313f..dd0e0e9 100644
> --- a/src/mesa/program/ir_to_mesa.cpp
> +++ b/src/mesa/program/ir_to_mesa.cpp
> @@ -3322,7 +3322,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader)
>      }
>
>      state->error = preprocess(state,&source,&state->info_log,
> -			&ctx->Extensions, ctx->API);
> +			&ctx->Extensions, ctx->API, 0, 0, 0);
>
>      if (ctx->Shader.Flags&  GLSL_DUMP) {
>         printf("GLSL source for %s shader %d:\n",



More information about the mesa-dev mailing list