From 33df515f103205c78a2e669ab8a8723c4c86ea90 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Tue, 12 Jan 2021 16:14:20 -0600 Subject: [PATCH] vkd3d-shader: Implement concatenation. Signed-off-by: Zebediah Figura Signed-off-by: Henri Verbeet Signed-off-by: Matteo Bruni Signed-off-by: Alexandre Julliard --- libs/vkd3d-shader/preproc.l | 22 ++++++++++++++++++++++ libs/vkd3d-shader/preproc.y | 6 ++++++ tests/hlsl_d3d12.c | 7 ++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index 9043adee..18a59b70 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -83,6 +83,8 @@ IDENTIFIER [A-Za-z_][A-Za-z0-9_]* 0[0-7]*[ul]{0,2} {return T_INTEGER;} [1-9][0-9]*[ul]{0,2} {return T_INTEGER;} +## {return T_CONCAT;} + "&&" {return T_TEXT;} "||" {return T_TEXT;} "++" {return T_TEXT;} @@ -189,6 +191,18 @@ static struct preproc_macro *preproc_get_top_macro(struct preproc_ctx *ctx) 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) +{ + struct preproc_macro *macro; + + if (!ctx->expansion_count) + return false; + macro = ctx->expansion_stack[ctx->expansion_count - 1].macro; + return !macro || macro->arg_count; +} + static void preproc_pop_buffer(struct preproc_ctx *ctx) { if (ctx->expansion_count) @@ -375,6 +389,14 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) switch (func_state->state) { case STATE_NONE: + if (token == T_CONCAT && should_concat(ctx)) + { + while (ctx->buffer.content_size + && strchr(" \t\r\n", ctx->buffer.buffer[ctx->buffer.content_size - 1])) + --ctx->buffer.content_size; + break; + } + if (token == T_IDENTIFIER || token == T_IDENTIFIER_PAREN) { const struct preproc_text *expansion; diff --git a/libs/vkd3d-shader/preproc.y b/libs/vkd3d-shader/preproc.y index 4173af0f..45577f23 100644 --- a/libs/vkd3d-shader/preproc.y +++ b/libs/vkd3d-shader/preproc.y @@ -327,6 +327,8 @@ static void free_parse_arg_names(struct parse_arg_names *args) %token T_INCLUDE "#include" %token T_UNDEF "#undef" +%token T_CONCAT "##" + %type expr %type body_token %type body_token_const @@ -419,6 +421,10 @@ body_token_const { $$ = ","; } + | T_CONCAT + { + $$ = "##"; + } directive : T_DEFINE T_IDENTIFIER body_text T_NEWLINE diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index 6980b998..e7267986 100644 --- a/tests/hlsl_d3d12.c +++ b/tests/hlsl_d3d12.c @@ -349,10 +349,8 @@ static void test_preprocess(void) for (i = 0; i < ARRAY_SIZE(tests); ++i) { - if (i == 10 || i == 11) - continue; vkd3d_test_set_context("Source \"%s\"", tests[i].source); - todo_if (i <= 4 || (i >= 9 && i <= 14)) + todo_if (i <= 4 || i == 9 || (i >= 12 && i <= 14)) check_preprocess(tests[i].source, NULL, NULL, tests[i].present, tests[i].absent); } vkd3d_test_set_context(NULL); @@ -407,8 +405,7 @@ static void test_preprocess(void) ok(include_count_file2 == 2, "file2 was included %u times.\n", include_count_file2); /* Macro invocation spread across multiple files. */ - if (0) - todo check_preprocess(test_include2_top, NULL, &test_include, "pass", NULL); + check_preprocess(test_include2_top, NULL, &test_include, "pass", NULL); blob = errors = (ID3D10Blob *)0xdeadbeef; hr = D3DPreprocess(test_include_top, strlen(test_include_top), NULL, NULL, &test_include_fail, &blob, &errors);