From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/preproc.l | 37 ++++++++++++++++++++------------- tests/preproc-macro.shader_test | 4 ++++ 2 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index 8e35e3555..20bf5cb57 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -29,6 +29,13 @@
#define YY_DECL static int preproc_lexer_lex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner)
+static struct preproc_macro *preproc_get_top_macro(struct preproc_ctx *ctx) +{ + if (!ctx->expansion_count) + return NULL; + return ctx->expansion_stack[ctx->expansion_count - 1].macro; +} + static void update_location(struct preproc_ctx *ctx);
#define YY_USER_ACTION update_location(yyget_extra(yyscanner)); @@ -124,7 +131,20 @@ INT_SUFFIX [uUlL]{0,2} const char *p;
if (!ctx->last_was_newline) - return T_HASHSTRING; + { + struct preproc_macro *macro; + + /* Stringification is only done for function-like macro bodies. + * Anywhere else, we need to parse it as two separate tokens. + * We could use a state for this, but yyless() is easier and cheap. + */ + + if ((macro = preproc_get_top_macro(ctx)) && macro->arg_count) + return T_HASHSTRING; + + yyless(1); + return T_TEXT; + }
for (p = yytext + 1; strchr(" \t", *p); ++p) ; @@ -218,13 +238,6 @@ static bool preproc_is_writing(struct preproc_ctx *ctx) return file->if_stack[file->if_count - 1].current_true; }
-static struct preproc_macro *preproc_get_top_macro(struct preproc_ctx *ctx) -{ - if (!ctx->expansion_count) - return NULL; - return ctx->expansion_stack[ctx->expansion_count - 1].macro; -} - /* Concatenation is not done for object-like macros, but is done for both * function-like macro bodies and their arguments. */ static bool should_concat(struct preproc_ctx *ctx) @@ -440,9 +453,6 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) switch (func_state->state) { case STATE_NONE: - { - struct preproc_macro *macro; - if (token == T_CONCAT && should_concat(ctx)) { while (ctx->buffer.content_size @@ -451,9 +461,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) break; }
- /* Stringification, however, is only done for function-like - * macro bodies. */ - if (token == T_HASHSTRING && (macro = preproc_get_top_macro(ctx)) && macro->arg_count) + if (token == T_HASHSTRING) { const struct preproc_text *expansion; const char *p = text + 1; @@ -585,7 +593,6 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) else vkd3d_string_buffer_printf(&ctx->buffer, "%s ", text); break; - }
case STATE_IDENTIFIER: if (token == '(') diff --git a/tests/preproc-macro.shader_test b/tests/preproc-macro.shader_test index 0fe73f7c3..b2f2530e7 100644 --- a/tests/preproc-macro.shader_test +++ b/tests/preproc-macro.shader_test @@ -301,3 +301,7 @@ fail [preproc] #define __LINE__ pass __LINE__ + +[preproc] +#define KEY pass +apple # KEY
From: Zebediah Figura zfigura@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55361 --- libs/vkd3d-shader/preproc.l | 20 ++++++++++++++++++++ tests/preproc-macro.shader_test | 6 ++++++ 2 files changed, 26 insertions(+)
diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index 20bf5cb57..faeb5d7a5 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -634,6 +634,26 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
switch (token) { + /* Most text gets left alone (e.g. if it contains macros, + * the macros should be evaluated later). + * Arguments are a special case, and are replaced with + * their values immediately. */ + case T_IDENTIFIER: + case T_IDENTIFIER_PAREN: + { + const struct preproc_text *expansion; + + if ((expansion = find_arg_expansion(ctx, text))) + { + preproc_push_expansion(ctx, expansion, NULL); + continue; + } + + if (current_arg) + preproc_text_add(current_arg, text); + break; + } + case T_NEWLINE: if (current_arg) preproc_text_add(current_arg, " "); diff --git a/tests/preproc-macro.shader_test b/tests/preproc-macro.shader_test index b2f2530e7..8f073965d 100644 --- a/tests/preproc-macro.shader_test +++ b/tests/preproc-macro.shader_test @@ -305,3 +305,9 @@ __LINE__ [preproc] #define KEY pass apple # KEY + +[preproc] +#define KEY2(x) x ## ss +#define KEY(a) KEY2(a) + +KEY(pa)
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/preproc.l | 56 ++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 23 deletions(-)
diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index faeb5d7a5..60cd662ec 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -346,6 +346,34 @@ static bool preproc_push_expansion(struct preproc_ctx *ctx, return true; }
+static void preproc_stringify(struct preproc_ctx *ctx, struct vkd3d_string_buffer *buffer, const char *text) +{ + const struct preproc_text *expansion; + const char *p = text + 1; + unsigned int i; + + while (*p == ' ' || *p == '\t') + ++p; + + vkd3d_string_buffer_printf(buffer, """); + if ((expansion = find_arg_expansion(ctx, p))) + { + for (i = 0; i < expansion->text.content_size; ++i) + { + char c = expansion->text.buffer[i]; + + if (c == '\' || c == '"') + vkd3d_string_buffer_printf(buffer, "\"); + vkd3d_string_buffer_printf(buffer, "%c", c); + } + } + else + { + vkd3d_string_buffer_printf(buffer, "%s", p); + } + vkd3d_string_buffer_printf(buffer, """); +} + int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) { struct preproc_ctx *ctx = yyget_extra(scanner); @@ -463,33 +491,15 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner)
if (token == T_HASHSTRING) { - const struct preproc_text *expansion; - const char *p = text + 1; - unsigned int i; + struct vkd3d_string_buffer buffer;
if (ctx->current_directive) return return_token(token, lval, text);
- while (*p == ' ' || *p == '\t') - ++p; - - vkd3d_string_buffer_printf(&ctx->buffer, """); - if ((expansion = find_arg_expansion(ctx, p))) - { - for (i = 0; i < expansion->text.content_size; ++i) - { - char c = expansion->text.buffer[i]; - - if (c == '\' || c == '"') - vkd3d_string_buffer_printf(&ctx->buffer, "\"); - vkd3d_string_buffer_printf(&ctx->buffer, "%c", c); - } - } - else - { - vkd3d_string_buffer_printf(&ctx->buffer, "%s", p); - } - vkd3d_string_buffer_printf(&ctx->buffer, """); + vkd3d_string_buffer_init(&buffer); + preproc_stringify(ctx, &buffer, text); + vkd3d_string_buffer_printf(&ctx->buffer, "%s", buffer.buffer); + vkd3d_string_buffer_cleanup(&buffer); break; }
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/preproc.l | 15 +++++++++++++++ tests/hlsl_d3d12.c | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+)
diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index 60cd662ec..5e8ed2eb1 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -664,6 +664,21 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) break; }
+ /* Stringification is another special case. Unsurprisingly, + * we need to stringify if this is an argument. More + * surprisingly, we need to stringify even if it's not. */ + case T_HASHSTRING: + { + struct vkd3d_string_buffer buffer; + + vkd3d_string_buffer_init(&buffer); + preproc_stringify(ctx, &buffer, text); + if (current_arg) + preproc_text_add(current_arg, buffer.buffer); + vkd3d_string_buffer_cleanup(&buffer); + break; + } + case T_NEWLINE: if (current_arg) preproc_text_add(current_arg, " "); diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index 85a1548f8..ef41235e3 100644 --- a/tests/hlsl_d3d12.c +++ b/tests/hlsl_d3d12.c @@ -236,6 +236,27 @@ static void test_preprocess(void)
"#", }, + { + "#define KEY2(x) x\n" + "#define KEY(a) KEY2(#a)\n" + "KEY(apple)", + + ""apple"", + }, + { + "#define KEY2(x) #x\n" + "#define KEY(a) KEY2(#a)\n" + "KEY(apple)", + + ""\"apple\""", + }, + { + "#define KEY2(x) #x\n" + "#define KEY(a) KEY2(#x)\n" + "KEY(apple)", + + ""\"x\""", + },
/* #pragma is preserved. */ {
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/preproc.l | 11 ++++++++++- tests/hlsl_d3d12.c | 6 ++++++ 2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index 5e8ed2eb1..728d61840 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -358,7 +358,16 @@ static void preproc_stringify(struct preproc_ctx *ctx, struct vkd3d_string_buffe vkd3d_string_buffer_printf(buffer, """); if ((expansion = find_arg_expansion(ctx, p))) { - for (i = 0; i < expansion->text.content_size; ++i) + size_t len = expansion->text.content_size; + size_t start = 0; + + while (len && strchr(" \t\r\n", expansion->text.buffer[len - 1])) + --len; + + while (start < len && strchr(" \t\r\n", expansion->text.buffer[start])) + ++start; + + for (i = start; i < len; ++i) { char c = expansion->text.buffer[i];
diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index ef41235e3..ff29f1f73 100644 --- a/tests/hlsl_d3d12.c +++ b/tests/hlsl_d3d12.c @@ -193,6 +193,12 @@ static void test_preprocess(void)
""apple"", }, + { + "#define KEY(a) #a\n" + "KEY( \t\r\n apple \t\r\n )", + + ""apple"", + }, { "#define KEY(if) #if\n" "KEY(apple)",
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/preproc.l | 3 +++ tests/preproc-macro.shader_test | 6 ++++++ 2 files changed, 9 insertions(+)
diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index 728d61840..d360f6ca3 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -746,6 +746,9 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) if (current_arg) preproc_text_add(current_arg, text); } + + if (current_arg) + preproc_text_add(current_arg, " "); break; } } diff --git a/tests/preproc-macro.shader_test b/tests/preproc-macro.shader_test index 8f073965d..96e4b8650 100644 --- a/tests/preproc-macro.shader_test +++ b/tests/preproc-macro.shader_test @@ -311,3 +311,9 @@ apple # KEY #define KEY(a) KEY2(a)
KEY(pa) + +[preproc] +#define KEY2(x) x +#define KEY KEY2(fa il) +KEY +pass
This merge request was approved by Henri Verbeet.