No hookup with GL yet.  Planned to be used to simplify profiles.

Signed-off-by: Olivier Galibert <galib...@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",
-- 
1.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to