diff --git a/libs/vkd3d-shader/preproc.h b/libs/vkd3d-shader/preproc.h index d653976af..21468f9ab 100644 --- a/libs/vkd3d-shader/preproc.h +++ b/libs/vkd3d-shader/preproc.h @@ -38,6 +38,7 @@ struct preproc_buffer { void *lexer_buffer; struct vkd3d_shader_location location; + bool eof; }; struct preproc_file @@ -125,7 +126,6 @@ struct preproc_ctx int lookahead_token; bool last_was_newline; - bool last_was_eof; bool last_was_defined; bool error; diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index c9c43bbbd..a8c0db358 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -258,8 +258,19 @@ static bool should_concat(struct preproc_ctx *ctx) return !macro || macro->arg_count; } +static struct preproc_buffer *preproc_get_top_buffer(struct preproc_ctx *ctx) +{ + if (ctx->expansion_count) + return &ctx->expansion_stack[ctx->expansion_count - 1].buffer; + if (ctx->file_count) + return &ctx->file_stack[ctx->file_count - 1].buffer; + return NULL; +} + static void preproc_pop_buffer(struct preproc_ctx *ctx) { + struct preproc_buffer *buffer; + if (ctx->expansion_count) { struct preproc_expansion *exp = &ctx->expansion_stack[ctx->expansion_count - 1]; @@ -298,10 +309,8 @@ static void preproc_pop_buffer(struct preproc_ctx *ctx) TRACE("File stack size is now %zu.\n", ctx->file_count); } - if (ctx->expansion_count) - yy_switch_to_buffer(ctx->expansion_stack[ctx->expansion_count - 1].buffer.lexer_buffer, ctx->scanner); - else if (ctx->file_count) - yy_switch_to_buffer(ctx->file_stack[ctx->file_count - 1].buffer.lexer_buffer, ctx->scanner); + if ((buffer = preproc_get_top_buffer(ctx))) + yy_switch_to_buffer(buffer->lexer_buffer, ctx->scanner); } static int return_token(int token, YYSTYPE *lval, const char *text) @@ -355,6 +364,7 @@ static bool preproc_push_expansion(struct preproc_ctx *ctx, exp->text = text; exp->buffer.lexer_buffer = yy_scan_bytes(text->text.buffer, text->text.content_size, ctx->scanner); exp->buffer.location = text->location; + exp->buffer.eof = false; exp->macro = macro; exp->arg_values = arg_values; TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count); @@ -415,18 +425,17 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) } else { - if (ctx->last_was_eof) + if (preproc_get_top_buffer(ctx)->eof) { preproc_pop_buffer(ctx); if (!ctx->file_count) return 0; } - ctx->last_was_eof = false; VKD3D_ASSERT(ctx->file_count); if (!(token = preproc_lexer_lex(lval, lloc, scanner))) { - ctx->last_was_eof = true; + preproc_get_top_buffer(ctx)->eof = true; /* If we have reached the end of an included file, inject a newline. */ if (ctx->expansion_count) @@ -789,6 +798,7 @@ bool preproc_push_include(struct preproc_ctx *ctx, char *filename, const struct file->buffer.location.source_name = file->filename; file->buffer.location.line = 1; file->buffer.location.column = 1; + file->buffer.eof = false; TRACE("File stack size is now %zu.\n", ctx->file_count); ctx->last_was_newline = true; return true; diff --git a/tests/hlsl_d3d12.c b/tests/hlsl_d3d12.c index 6d3569cf4..0d2ba6a5d 100644 --- a/tests/hlsl_d3d12.c +++ b/tests/hlsl_d3d12.c @@ -84,7 +84,15 @@ static const char test_include2_top[] = "#include \"file4\"\n" ",ss)"; +/* Test #include immediately followed by EOF. */ static const char test_include2_file4[] = + "#include \"file5\""; + +/* Test #include immediately followed by comment immediately followed by EOF. */ +static const char test_include2_file5[] = + "#include \"file6\"/*"; + +static const char test_include2_file6[] = "FUNC(pa"; static unsigned int refcount_file1, refcount_file2, refcount_file3, include_count_file2; @@ -128,6 +136,20 @@ static HRESULT WINAPI test_include_Open(ID3DInclude *iface, D3D_INCLUDE_TYPE typ *code = test_include2_file4; *size = strlen(test_include2_file4); } + else if (!strcmp(filename, "file5")) + { + ok(type == D3D_INCLUDE_LOCAL, "Got type %#x.\n", type); + ok(parent_data == test_include2_file4, "Got parent data %p.\n", parent_data); + *code = test_include2_file5; + *size = strlen(test_include2_file5); + } + else if (!strcmp(filename, "file6")) + { + ok(type == D3D_INCLUDE_LOCAL, "Got type %#x.\n", type); + ok(parent_data == test_include2_file5, "Got parent data %p.\n", parent_data); + *code = test_include2_file6; + *size = strlen(test_include2_file6); + } else { ok(0, "Unexpected filename \"%s\".\n", filename); @@ -392,7 +414,13 @@ static void test_preprocess(void) "pass", "fail", - } + }, + + /* Make sure we handle the empty-file case without breaking. */ + { + "", + "", + }, }; for (i = 0; i < ARRAY_SIZE(tests); ++i)