[Mesa-dev] [PATCH 01/10] glcpp: Add support to #line for a filnename, not just a source string number
Carl Worth
cworth at cworth.org
Sat Dec 8 13:43:36 PST 2012
Such as:
#line 23 "foo.c"
Having a filename here is quite useful and many other OpenGL implementations
allow this.
Note that for GLES we take the hard line and insist on a numeric source string
number as per the specification and which glcpp has always supported:
#line 23 3
---
src/glsl/glcpp/glcpp-lex.l | 28 ++++++++++++++----
src/glsl/glcpp/glcpp-parse.y | 64 ++++++++++++++++++++++++++++++++++--------
src/glsl/glcpp/glcpp.h | 8 +++---
src/glsl/glcpp/pp.c | 4 +--
4 files changed, 81 insertions(+), 23 deletions(-)
diff --git a/src/glsl/glcpp/glcpp-lex.l b/src/glsl/glcpp/glcpp-lex.l
index fd28711..a6171cc 100644
--- a/src/glsl/glcpp/glcpp-lex.l
+++ b/src/glsl/glcpp/glcpp-lex.l
@@ -44,20 +44,20 @@ void glcpp_set_column (int column_no , yyscan_t yyscanner);
do { \
if (parser->has_new_line_number) \
yylineno = parser->new_line_number; \
- if (parser->has_new_source_number) \
- yylloc->source = parser->new_source_number; \
+ if (parser->has_new_source) \
+ yylloc->source = parser->new_source; \
yylloc->first_column = yycolumn + 1; \
yylloc->first_line = yylineno; \
yycolumn += yyleng; \
parser->has_new_line_number = 0; \
- parser->has_new_source_number = 0; \
+ parser->has_new_source = 0; \
} while(0);
#define YY_USER_INIT \
do { \
yylineno = 1; \
yycolumn = 1; \
- yylloc->source = 0; \
+ yylloc->source = "0"; \
} while(0)
%}
@@ -84,7 +84,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,6 +120,24 @@ HEXADECIMAL_INTEGER 0[xX][0-9a-fA-F]+[uU]?
return SPACE;
}
+\"(\\.|[^\\"\n])*\" {
+ /* Drop the quotation marks when returning a string's literal value.
+ *
+ * Note: A truly *correct* solution would also interpret any
+ * escape sequences within the string. We intentionally don't
+ * do this. The rationale is for code savings and the
+ * justification is that strings aren't actually part of the
+ * GLSL language. We're only parsing them as a convenience for
+ * use in '#line XX "foo.c"' and even that isn't part of the
+ * specification. So, for this limited use case of filenames,
+ * escape sequences shouldn't be common, and when they are,
+ * users can deal with the un-interpreted escape sequence
+ * appearing in the filename in error messages.
+ */
+ yylval->str = ralloc_strndup (yyextra, yytext + 1, strlen(yytext) - 2);
+ return STRING_LITERAL;
+}
+
{HASH}version{HSPACE}+ {
yylval->str = ralloc_strdup (yyextra, yytext);
yyextra->space_tokens = 0;
diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
index 380a1d9..eaf01cd 100644
--- a/src/glsl/glcpp/glcpp-parse.y
+++ b/src/glsl/glcpp/glcpp-parse.y
@@ -164,10 +164,10 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
%lex-param {glcpp_parser_t *parser}
%expect 0
-%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE FUNC_IDENTIFIER OBJ_IDENTIFIER HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_LINE HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE
+%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE FUNC_IDENTIFIER OBJ_IDENTIFIER HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_LINE HASH_UNDEF HASH_VERSION IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE STRING_LITERAL
%token PASTE
%type <ival> expression INTEGER operator SPACE integer_constant
-%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER
+%type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER STRING_LITERAL
%type <string_list> identifier_list
%type <token> preprocessing_token conditional_token
%type <token_list> pp_tokens replacement_list text_line conditional_tokens
@@ -229,13 +229,27 @@ expanded_line:
| LINE_EXPANDED integer_constant integer_constant NEWLINE {
parser->has_new_line_number = 1;
parser->new_line_number = $2;
- parser->has_new_source_number = 1;
- parser->new_source_number = $3;
+ parser->has_new_source = 1;
+ parser->new_source = ralloc_asprintf (parser, "%" PRIiMAX, $3);
ralloc_asprintf_rewrite_tail (&parser->output,
&parser->output_length,
"#line %" PRIiMAX " %" PRIiMAX "\n",
$2, $3);
}
+| LINE_EXPANDED integer_constant STRING_LITERAL NEWLINE {
+#if 0
+ if (parser->is_gles)
+ glcpp_error(& @1, parser, "#line with non-numeric source number (illegal in GLES)");
+#endif
+ parser->has_new_line_number = 1;
+ parser->new_line_number = $2;
+ parser->has_new_source = 1;
+ parser->new_source = $3;
+ ralloc_asprintf_rewrite_tail (&parser->output,
+ &parser->output_length,
+ "#line %" PRIiMAX " \"%s\"\n",
+ $2, $3);
+ }
;
control_line:
@@ -540,6 +554,10 @@ preprocessing_token:
$$ = _token_create_ival (parser, SPACE, SPACE);
$$->location = yylloc;
}
+| STRING_LITERAL {
+ $$ = _token_create_str (parser, STRING_LITERAL, $1);
+ $$->location = yylloc;
+ }
;
operator:
@@ -911,6 +929,7 @@ _token_list_equal_ignoring_space (token_list_t *a, token_list_t *b)
case IDENTIFIER:
case INTEGER_STRING:
case OTHER:
+ case STRING_LITERAL:
if (strcmp (node_a->token->value.str,
node_b->token->value.str))
{
@@ -938,6 +957,9 @@ _token_print (char **out, size_t *len, token_t *token)
case INTEGER:
ralloc_asprintf_rewrite_tail (out, len, "%" PRIiMAX, token->value.ival);
break;
+ case STRING_LITERAL:
+ ralloc_asprintf_rewrite_tail (out, len, "\"%s\"", token->value.str);
+ break;
case IDENTIFIER:
case INTEGER_STRING:
case OTHER:
@@ -1052,8 +1074,8 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
* the second token must also be an integer or must be a
* string representing an integer that begins with a digit.
*/
- if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING || token->type == INTEGER) &&
- (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING || other->type == INTEGER))
+ if ((token->type == IDENTIFIER || token->type == OTHER || token->type == STRING_LITERAL || token->type == INTEGER_STRING || token->type == INTEGER) &&
+ (other->type == IDENTIFIER || other->type == OTHER || other->type == STRING_LITERAL || INTEGER_STRING || other->type == INTEGER))
{
char *str;
int combined_type;
@@ -1064,6 +1086,8 @@ _token_paste (glcpp_parser_t *parser, token_t *token, token_t *other)
if (token->type == INTEGER_STRING || token->type == INTEGER)
{
switch (other->type) {
+ case OTHER:
+ case STRING_LITERAL:
case INTEGER_STRING:
if (other->value.str[0] < '0' ||
other->value.str[0] > '9')
@@ -1176,8 +1200,8 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
parser->has_new_line_number = 0;
parser->new_line_number = 1;
- parser->has_new_source_number = 0;
- parser->new_source_number = 0;
+ parser->has_new_source = 0;
+ parser->new_source = "0";
/* Add pre-defined macros. */
if (extensions != NULL) {
@@ -1330,19 +1354,35 @@ _arguments_parse (argument_list_t *arguments,
}
static token_list_t *
-_token_list_create_with_one_ival (void *ctx, int type, int ival)
+_token_list_create_with_one_node (void *ctx, token_t *node)
{
token_list_t *list;
- token_t *node;
list = _token_list_create (ctx);
- node = _token_create_ival (list, type, ival);
_token_list_append (list, node);
return list;
}
static token_list_t *
+_token_list_create_with_one_ival (void *ctx, int type, int ival)
+{
+ token_t *node;
+
+ node = _token_create_ival (ctx, type, ival);
+ return _token_list_create_with_one_node (ctx, node);
+}
+
+static token_list_t *
+_token_list_create_with_one_string (void *ctx, int type, const char *str)
+{
+ token_t *node;
+
+ node = _token_create_str (ctx, type, ralloc_strdup (ctx, str));
+ return _token_list_create_with_one_node (ctx, node);
+}
+
+static token_list_t *
_token_list_create_with_one_space (void *ctx)
{
return _token_list_create_with_one_ival (ctx, SPACE, SPACE);
@@ -1579,7 +1619,7 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
return _token_list_create_with_one_integer (parser, node->token->location.first_line);
if (strcmp(identifier, "__FILE__") == 0)
- return _token_list_create_with_one_integer (parser, node->token->location.source);
+ return _token_list_create_with_one_string (parser, OTHER, node->token->location.source);
/* Look up this identifier in the hash table. */
macro = hash_table_find (parser->defines, identifier);
diff --git a/src/glsl/glcpp/glcpp.h b/src/glsl/glcpp/glcpp.h
index cdcbdfe..09f711c 100644
--- a/src/glsl/glcpp/glcpp.h
+++ b/src/glsl/glcpp/glcpp.h
@@ -67,7 +67,7 @@ typedef struct YYLTYPE {
int first_column;
int last_line;
int last_column;
- unsigned source;
+ const char *source;
} YYLTYPE;
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
@@ -88,7 +88,7 @@ do { \
(Current).first_column = (Current).last_column = \
YYRHSLOC(Rhs, 0).last_column; \
} \
- (Current).source = 0; \
+ (Current).source = "0"; \
} while (0)
struct token {
@@ -182,8 +182,8 @@ struct glcpp_parser {
int error;
bool has_new_line_number;
int new_line_number;
- bool has_new_source_number;
- int new_source_number;
+ bool has_new_source;
+ const char *new_source;
};
struct gl_extensions;
diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c
index 789f7f9..4a43a9c 100644
--- a/src/glsl/glcpp/pp.c
+++ b/src/glsl/glcpp/pp.c
@@ -35,7 +35,7 @@ glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
parser->error = 1;
ralloc_asprintf_rewrite_tail(&parser->info_log,
&parser->info_log_length,
- "%u:%u(%u): "
+ "%s:%u(%u): "
"preprocessor error: ",
locp->source,
locp->first_line,
@@ -56,7 +56,7 @@ glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
ralloc_asprintf_rewrite_tail(&parser->info_log,
&parser->info_log_length,
- "%u:%u(%u): "
+ "%s:%u(%u): "
"preprocessor warning: ",
locp->source,
locp->first_line,
--
1.7.10
More information about the mesa-dev
mailing list