[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