Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/preproc.h | 11 +++++++ libs/vkd3d-shader/preproc.l | 39 +++++++++++++++++++++++- libs/vkd3d-shader/preproc.y | 39 +++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_private.h | 2 ++ 4 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/preproc.h b/libs/vkd3d-shader/preproc.h index cbd93229..769b8c23 100644 --- a/libs/vkd3d-shader/preproc.h +++ b/libs/vkd3d-shader/preproc.h @@ -23,11 +23,22 @@
#include "vkd3d_shader_private.h"
+struct preproc_location +{ + const char *filename; + unsigned int first_line, first_column; +}; + struct preproc_ctx { void *scanner;
+ struct vkd3d_shader_message_context *message_context; struct vkd3d_string_buffer buffer; + unsigned int line, column; + const char *source_name; + + bool error; };
#endif diff --git a/libs/vkd3d-shader/preproc.l b/libs/vkd3d-shader/preproc.l index f931292b..c0c6b13a 100644 --- a/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d-shader/preproc.l @@ -27,6 +27,10 @@
#define YY_DECL static int preproc_lexer_lex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner)
+static void update_location(struct preproc_ctx *ctx); + +#define YY_USER_ACTION update_location(yyget_extra(yyscanner)); + %}
%option 8bit @@ -88,6 +92,28 @@ IDENTIFIER [A-Za-z_][A-Za-z0-9_]*
%%
+static void update_location(struct preproc_ctx *ctx) +{ + unsigned int i, leng = yyget_leng(ctx->scanner); + const char *text = yyget_text(ctx->scanner); + + /* We want to do this here, rather than before calling yylex(), because + * some tokens are skipped by the lexer. */ + + yyget_lloc(ctx->scanner)->first_line = ctx->line; + yyget_lloc(ctx->scanner)->first_column = ctx->column; + + for (i = 0; i < leng; ++i) + { + ++ctx->column; + if (text[i] == '\n') + { + ctx->column = 1; + ++ctx->line; + } + } +} + int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) { struct preproc_ctx *ctx = yyget_extra(scanner); @@ -101,7 +127,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) return PREPROC_YYEOF; text = yyget_text(scanner);
- TRACE("Parsing token %d, string %s.\n", token, debugstr_a(text)); + TRACE("Parsing token %d, line %d, string %s.\n", token, lloc->first_line, debugstr_a(text));
vkd3d_string_buffer_printf(&ctx->buffer, "%s ", text); } @@ -115,6 +141,10 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info, void *output_code;
vkd3d_string_buffer_init(&ctx.buffer); + ctx.message_context = message_context; + ctx.source_name = compile_info->source_name ? compile_info->source_name : "<anonymous>"; + ctx.line = 1; + ctx.column = 1;
yylex_init_extra(&ctx, &ctx.scanner); top_buffer = yy_scan_bytes(compile_info->source.code, compile_info->source.size, ctx.scanner); @@ -124,6 +154,13 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info, yy_delete_buffer(top_buffer, ctx.scanner); yylex_destroy(ctx.scanner);
+ if (ctx.error) + { + WARN("Failed to preprocess.\n"); + vkd3d_string_buffer_cleanup(&ctx.buffer); + return VKD3D_ERROR_INVALID_SHADER; + } + if (!(output_code = vkd3d_malloc(ctx.buffer.content_size))) { vkd3d_string_buffer_cleanup(&ctx.buffer); diff --git a/libs/vkd3d-shader/preproc.y b/libs/vkd3d-shader/preproc.y index 92448f24..88b855c6 100644 --- a/libs/vkd3d-shader/preproc.y +++ b/libs/vkd3d-shader/preproc.y @@ -36,13 +36,50 @@ int preproc_yylex(PREPROC_YYSTYPE *yylval_param, PREPROC_YYLTYPE *yylloc_param, %code {
+#define YYLLOC_DEFAULT(cur, rhs, n) \ + do \ + { \ + if (n) \ + { \ + (cur).filename = YYRHSLOC(rhs, 1).filename; \ + (cur).first_line = YYRHSLOC(rhs, 1).first_line; \ + (cur).first_column = YYRHSLOC(rhs, 1).first_column; \ + } \ + else \ + { \ + (cur).filename = YYRHSLOC(rhs, 0).filename; \ + (cur).first_line = YYRHSLOC(rhs, 0).first_line; \ + (cur).first_column = YYRHSLOC(rhs, 0).first_column; \ + } \ + } while (0) + +static void set_location(struct preproc_ctx *ctx, const struct preproc_location *loc) +{ + ctx->message_context->source_name = loc->filename; + ctx->message_context->line = loc->first_line; + ctx->message_context->column = loc->first_column; +} + +static void preproc_error(struct preproc_ctx *ctx, const struct preproc_location *loc, + enum vkd3d_shader_error error, const char *format, ...) +{ + va_list args; + + set_location(ctx, loc); + va_start(args, format); + vkd3d_shader_verror(ctx->message_context, error, format, args); + va_end(args); + ctx->error = true; +} + static void yyerror(const YYLTYPE *loc, void *scanner, struct preproc_ctx *ctx, const char *string) { - FIXME("Error reporting is not implemented.\n"); + preproc_error(ctx, loc, VKD3D_SHADER_ERROR_PP_INVALID_SYNTAX, "%s", string); }
}
+%define api.location.type {struct preproc_location} %define api.prefix {preproc_yy} %define api.pure full %define parse.error verbose diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 83038384..5a022708 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -79,6 +79,8 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_RS_INVALID_ROOT_PARAMETER_TYPE = 3002, VKD3D_SHADER_ERROR_RS_INVALID_DESCRIPTOR_RANGE_TYPE = 3003, VKD3D_SHADER_ERROR_RS_MIXED_DESCRIPTOR_RANGE_TYPES = 3004, + + VKD3D_SHADER_ERROR_PP_INVALID_SYNTAX = 4000, };
enum VKD3D_SHADER_INSTRUCTION_HANDLER