[Mesa-dev] [PATCH 4/5] glsl/glcpp: Fix line-continuation code to handle multiple newline flavors

Carl Worth cworth at cworth.org
Wed Jul 2 23:05:12 PDT 2014


Sometimes the newline separator is a single character, and sometimes it is two
characters. Before we can fold away and line-continuation backslashes, we
identify the flavor of line separator that is in use.

With this identified, we then correctly search for backslashes followed
immediately by the first character of the line separator.

Also, when re-inserting newlines to replace collapsed newlines, we carefully
insert newlines of the same flavor.

With this commit, almost all remaining test are fixed as tested by
glcpp-test-cr-lf:

	\r:	142/143 tests pass
	\r\n:	142/143 tests pass
	\n\r:	143/143 tests pass

(The only remaining failures have nothing to do with the actual pre-processor
code, but are due to a bug in the way the test suite uses grep to try to
extract test-specific command-line options from the source files.)
---
 src/glsl/glcpp/pp.c | 48 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 39 insertions(+), 9 deletions(-)

diff --git a/src/glsl/glcpp/pp.c b/src/glsl/glcpp/pp.c
index 4a623f8..6f448ab 100644
--- a/src/glsl/glcpp/pp.c
+++ b/src/glsl/glcpp/pp.c
@@ -78,10 +78,44 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
 {
 	char *clean = ralloc_strdup(ctx, "");
 	const char *backslash, *newline, *search_start;
+        const char *cr, *lf;
+        char newline_separator[3];
 	int collapsed_newlines = 0;
 
 	search_start = shader;
 
+	/* Determine what flavor of newlines this shader is using. GLSL
+	 * provides for 4 different possible ways to separate lines, (using
+	 * one or two characters):
+	 *
+	 *	"\n" (line-feed, like Linux, Unix, and new Mac OS)
+	 *	"\r" (carriage-return, like old Mac files)
+	 *	"\r\n" (carriage-return + line-feed, like DOS files)
+	 *	"\n\r" (line-feed + carriage-return, like nothing, really)
+	 *
+	 * In this code, we explicitly do not support a shader that mixes
+	 * different kinds of newlines. That might be possible by a strict
+	 * reading of the GLSL specification, but is totally insane.
+	 */
+	cr = strchr(search_start, '\r');
+	lf = strchr(search_start, '\n');
+
+	newline_separator[0] = '\n';
+	newline_separator[1] = '\0';
+	newline_separator[2] = '\0';
+
+	if (cr == NULL) {
+		/* Nothing to do. */
+	} else if (lf == NULL) {
+		newline_separator[0] = '\r';
+	} else if (lf == cr + 1) {
+		newline_separator[0] = '\r';
+		newline_separator[1] = '\n';
+	} else if (cr == lf + 1) {
+		newline_separator[0] = '\n';
+		newline_separator[1] = '\r';
+	}
+
 	while (true) {
 		backslash = strchr(search_start, '\\');
 
@@ -91,17 +125,17 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
 		 * line numbers.
 		 */
 		if (collapsed_newlines) {
-			newline = strchr(search_start, '\n');
+			newline = strchr(search_start, newline_separator[0]);
 			if (newline &&
 			    (backslash == NULL || newline < backslash))
 			{
 				ralloc_strncat(&clean, shader,
 					       newline - shader + 1);
 				while (collapsed_newlines) {
-					ralloc_strcat(&clean, "\n");
+					ralloc_strcat(&clean, newline_separator);
 					collapsed_newlines--;
 				}
-				shader = newline + 1;
+				shader = newline + strlen(newline_separator);
 				search_start = shader;
 			}
 		}
@@ -116,15 +150,11 @@ remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
 		 * advance the shader pointer to the character after the
 		 * newline.
 		 */
-		if (backslash[1] == '\n' ||
-		    (backslash[1] == '\r' && backslash[2] == '\n'))
+		if (backslash[1] == newline_separator[0])
 		{
 			collapsed_newlines++;
 			ralloc_strncat(&clean, shader, backslash - shader);
-			if (backslash[1] == '\n')
-				shader = backslash + 2;
-			else
-				shader = backslash + 3;
+			shader = backslash + 1 + strlen(newline_separator);
 			search_start = shader;
 		}
 	}
-- 
2.0.0



More information about the mesa-dev mailing list