[3/3] d3dcompiler: Correctly handle ';'-style comments.

Matteo Bruni matteo.mystral at gmail.com
Sun Feb 6 10:30:13 CST 2011


Time for a somewhat controversial patch. ;)

D3D assembler shader syntax allows for comments starting with the ';'
character. This obviously may cause much pain and dismay in a C
preprocessor, and that's what happens with wpp. The funny thing is,
this causes troubles even in the native d3dcompiler preprocessor...
That's because, in general, the same preprocessor has to process both
asm and HLSL sources (the D3DPreprocess function apparently accepts
both).
Native "solution" is to ignore some error conditions, reporting the
error message but returning S_OK nevertheless. This can be seen by
checking the tests I have included in this patch, which also does
essentially the same for our implementation. Notice that the
modifications to wpp should not cause harm to other users of the
library, as it still returns failure in the affected case (it just
returns a different error code).

This fixes http://bugs.winehq.org/show_bug.cgi?id=24614.
-------------- next part --------------
From 82b6222321a03c133f632832996abcec565d0b31 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <mbruni at codeweavers.com>
Date: Sun, 6 Feb 2011 16:48:47 +0100
Subject: d3dcompiler: Correctly handle ';'-style comments.

---
 dlls/d3dcompiler_43/compiler.c  |    7 +++-
 dlls/d3dcompiler_43/tests/asm.c |   63 +++++++++++++++++++++++++++++++++++++++
 libs/wpp/ppl.l                  |   21 ++++++++-----
 libs/wpp/preproc.c              |   11 +++++++
 libs/wpp/wpp_private.h          |    1 +
 5 files changed, 93 insertions(+), 10 deletions(-)

diff --git a/dlls/d3dcompiler_43/compiler.c b/dlls/d3dcompiler_43/compiler.c
index 3c964e2..edadaba 100644
--- a/dlls/d3dcompiler_43/compiler.c
+++ b/dlls/d3dcompiler_43/compiler.c
@@ -353,7 +353,7 @@ static HRESULT preprocess_shader(const void *data, SIZE_T data_size,
         ret = 1;
     if (ret)
     {
-        TRACE("Error during shader preprocessing\n");
+        WARN("Error during shader preprocessing\n");
         if (wpp_messages)
         {
             int size;
@@ -373,7 +373,10 @@ static HRESULT preprocess_shader(const void *data, SIZE_T data_size,
         }
         if (data)
             TRACE("Shader source:\n%s\n", debugstr_an(data, data_size));
-        hr = E_FAIL;
+
+        /* Don't return failure if the error was "Unexpected end of file" */
+        if (ret == 1)
+            hr = D3DXERR_INVALIDDATA;
     }
 
 cleanup:
diff --git a/dlls/d3dcompiler_43/tests/asm.c b/dlls/d3dcompiler_43/tests/asm.c
index 5c01983..0910995 100644
--- a/dlls/d3dcompiler_43/tests/asm.c
+++ b/dlls/d3dcompiler_43/tests/asm.c
@@ -108,6 +108,20 @@ static void preproc_test(void) {
             "mov r0, c0[ REG ]\n",
             {0xfffe0101, 0x00000001, 0x800f0000, 0xa0e4000a, 0x0000ffff}
         },
+        {   /* shader 3 */
+            "vs.1.1\n"
+            "add r1, c4, r2 ; a comment with ', a quotation mark\n"
+            "mov r0, r1\n",
+            {0xfffe0101, 0x00000002, 0x800f0001, 0xa0e40004, 0x80e40002, 0x00000001,
+	     0x800f0000, 0x80e40001, 0x0000ffff}
+        },
+        {   /* shader 4 */
+            "vs.1.1\n"
+            "add r1, c4, r2 ; a comment with \", a double quotation mark\n"
+            "mov r0, r1\n",
+            {0xfffe0101, 0x00000002, 0x800f0001, 0xa0e40004, 0x80e40002, 0x00000001,
+	     0x800f0000, 0x80e40001, 0x0000ffff}
+        },
     };
 
     exec_tests("preproc", tests, sizeof(tests) / sizeof(tests[0]));
@@ -1405,6 +1419,10 @@ static void failure_test(void) {
         /* shader 43: */
         "ps_2_0\n"
         "texm3x3vspec t3, t0\n",
+        /* shader 44: */
+        "#include \"notthere.vsh\"\n"
+        "vs.1.1\n"
+        "add r1, c4, r2 ; a comment with \", a double quotation mark\n",
     };
     HRESULT hr;
     unsigned int i;
@@ -1584,6 +1602,18 @@ static void d3dpreprocess_test(void)
         "#include \"incl2.vsh\"\n"
         "mov REGISTER, v0\n"
     };
+    const char testshader3[] =
+    {
+        "vs.1.1\n"
+        "mov REGISTER, v0 ; comment ' \n"
+        "add r1, r2, r3 // another comment \n"
+    };
+    const char testshader4[] =
+    {
+        "vs.1.1\n"
+        "mov REGISTER, v0 ; comment \" \n"
+        "add r1, r2, r3 // another comment \n"
+    };
     HRESULT hr;
     ID3DBlob *shader, *messages;
     D3D_SHADER_MACRO defines[] =
@@ -1658,6 +1688,39 @@ static void d3dpreprocess_test(void)
     }
     if (shader) ID3D10Blob_Release(shader);
 
+    /* Handling of ';' comments (actually, ignoring some errors...) */
+    shader = NULL;
+    messages = NULL;
+    hr = D3DPreprocess(testshader3, strlen(testshader3), NULL,
+            NULL, (ID3DInclude *)&include, &shader, &messages);
+    ok(hr == S_OK, "D3DPreprocess test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+    if (messages)
+    {
+        trace("D3DPreprocess messages:\n%s", (char *)ID3D10Blob_GetBufferPointer(messages));
+        ID3D10Blob_Release(messages);
+    }
+    if (shader)
+    {
+        trace("Preprocessed shader:\n%s", (char *)ID3D10Blob_GetBufferPointer(shader));
+        ID3D10Blob_Release(shader);
+    }
+
+    shader = NULL;
+    messages = NULL;
+    hr = D3DPreprocess(testshader4, strlen(testshader4), NULL,
+            NULL, (ID3DInclude *)&include, &shader, &messages);
+    ok(hr == S_OK, "D3DPreprocess test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+    if (messages)
+    {
+        trace("D3DPreprocess messages:\n%s", (char *)ID3D10Blob_GetBufferPointer(messages));
+        ID3D10Blob_Release(messages);
+    }
+    if (shader)
+    {
+        trace("Preprocessed shader:\n%s", (char *)ID3D10Blob_GetBufferPointer(shader));
+        ID3D10Blob_Release(shader);
+    }
+
     /* NULL shader tests */
     shader = NULL;
     messages = NULL;
diff --git a/libs/wpp/ppl.l b/libs/wpp/ppl.l
index 0588e5d..fc3ad2b 100644
--- a/libs/wpp/ppl.l
+++ b/libs/wpp/ppl.l
@@ -615,14 +615,13 @@ void pp_writestring(const char *format, ...)
 		yy_pop_state();
 		switch(yy_current_state())
 		{
+		case RCINCL:
+			yy_pop_state();
+			/* fall through */
 		case pp_pp:
 		case pp_define:
 		case pp_mbody:
 		case pp_inc:
-		case RCINCL:
-			if (yy_current_state()==RCINCL) yy_pop_state();
-			ppy_lval.cptr = get_string();
-			return tDQSTRING;
 		case pp_line:
 			ppy_lval.cptr = get_string();
 			return tDQSTRING;
@@ -678,9 +677,9 @@ void pp_writestring(const char *format, ...)
 	}
 <pp_iqs,pp_dqs,pp_sqs>\\.	add_string(ppy_text, ppy_leng);
 <pp_iqs,pp_dqs,pp_sqs>\n	{
-		newline(1);
+		newline(-1);
 		add_string(ppy_text, ppy_leng);
-		ppy_warning("Newline in string constant encounterd (started line %d)", string_start());
+		ppy_warning("Newline in string constant encountered (started line %d)", string_start());
 	}
 
 	/*
@@ -771,8 +770,14 @@ void pp_writestring(const char *format, ...)
 
 		if(!bep)
 		{
-			if(YY_START != INITIAL)
-				ppy_error("Unexpected end of file during preprocessing");
+			if(yy_current_state() != INITIAL)
+			{
+				ppy_nonfatal_error("Unexpected end of file during preprocessing");
+				if(yy_current_state() == pp_sqs || yy_current_state() == pp_dqs)
+					put_string();
+				while(yy_current_state() != INITIAL)
+					yy_pop_state();
+			}
 			yyterminate();
 		}
 		else if(bep->should_pop == 2)
diff --git a/libs/wpp/preproc.c b/libs/wpp/preproc.c
index 2eb3133..f7712ae 100644
--- a/libs/wpp/preproc.c
+++ b/libs/wpp/preproc.c
@@ -731,6 +731,17 @@ int ppy_error(const char *s, ...)
 	return 1;
 }
 
+int ppy_nonfatal_error(const char *s, ...)
+{
+	va_list ap;
+	va_start(ap, s);
+	wpp_callbacks->error(pp_status.input, pp_status.line_number, pp_status.char_number, ppy_text, s, ap);
+	va_end(ap);
+	if(!pp_status.state)
+		pp_status.state = 2;
+	return 1;
+}
+
 int ppy_warning(const char *s, ...)
 {
 	va_list ap;
diff --git a/libs/wpp/wpp_private.h b/libs/wpp/wpp_private.h
index 615a450..ec6b1b1 100644
--- a/libs/wpp/wpp_private.h
+++ b/libs/wpp/wpp_private.h
@@ -221,6 +221,7 @@ int pp_get_if_depth(void);
 extern const struct wpp_callbacks *wpp_callbacks;
 
 int ppy_error(const char *s, ...) __attribute__((format (printf, 1, 2)));
+int ppy_nonfatal_error(const char *s, ...) __attribute__((format (printf, 1, 2)));
 int ppy_warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
 void pp_internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4)));
 
-- 
1.7.3.4


More information about the wine-patches mailing list