diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index 18a59b70..388b77f6 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -104,7 +104,7 @@ IDENTIFIER [A-Za-z_][A-Za-z0-9_]* const char *p; if (!ctx->last_was_newline) - return T_TEXT; + return T_HASHSTRING; for (p = yytext + 1; strchr(" \t", *p); ++p) ; @@ -247,6 +247,7 @@ static int return_token(int token, YYSTYPE *lval, const char *text) { switch (token) { + case T_HASHSTRING: case T_IDENTIFIER: case T_IDENTIFIER_PAREN: case T_INTEGER: @@ -389,6 +390,9 @@ 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 @@ -397,6 +401,40 @@ 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) + { + const struct preproc_text *expansion; + const char *p = text + 1; + unsigned int i; + + 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, "\""); + break; + } + if (token == T_IDENTIFIER || token == T_IDENTIFIER_PAREN) { const struct preproc_text *expansion; @@ -440,6 +478,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) vkd3d_string_buffer_printf(&ctx->buffer, "%s ", text); break; + } case STATE_IDENTIFIER: if (token == '(') diff --git a/libs/vkd3d-shader/preproc.y b/libs/vkd3d-shader/preproc.y index 45577f23..72d6486e 100644 --- a/libs/vkd3d-shader/preproc.y +++ b/libs/vkd3d-shader/preproc.y @@ -309,6 +309,7 @@ static void free_parse_arg_names(struct parse_arg_names *args) struct parse_arg_names arg_names; } +%token T_HASHSTRING %token T_IDENTIFIER %token T_IDENTIFIER_PAREN %token T_INTEGER @@ -387,7 +388,8 @@ body_text } body_token - : T_IDENTIFIER + : T_HASHSTRING + | T_IDENTIFIER | T_IDENTIFIER_PAREN | T_INTEGER | T_TEXT diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index e7267986..9d8d16d9 100644 --- a/tests/hlsl_d3d12.c +++ b/tests/hlsl_d3d12.c @@ -350,7 +350,7 @@ static void test_preprocess(void) for (i = 0; i < ARRAY_SIZE(tests); ++i) { vkd3d_test_set_context("Source \"%s\"", tests[i].source); - todo_if (i <= 4 || i == 9 || (i >= 12 && i <= 14)) + todo_if (i == 9 || (i >= 12 && i <= 14)) check_preprocess(tests[i].source, NULL, NULL, tests[i].present, tests[i].absent); } vkd3d_test_set_context(NULL);