diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/prebuilt/wasm-bison-parser.c | 17 | ||||
-rw-r--r-- | src/sexpr-wasm.c | 14 | ||||
-rw-r--r-- | src/wasm-ast-checker.c | 62 | ||||
-rw-r--r-- | src/wasm-ast-checker.h | 12 | ||||
-rw-r--r-- | src/wasm-bison-parser.y | 17 | ||||
-rw-r--r-- | src/wasm-common.c | 49 | ||||
-rw-r--r-- | src/wasm-common.h | 32 | ||||
-rw-r--r-- | src/wasm-parser-lexer-shared.c | 126 | ||||
-rw-r--r-- | src/wasm-parser-lexer-shared.h | 11 | ||||
-rw-r--r-- | src/wasm-parser.h | 4 |
10 files changed, 234 insertions, 110 deletions
diff --git a/src/prebuilt/wasm-bison-parser.c b/src/prebuilt/wasm-bison-parser.c index 30371fa1..1c82ec92 100644 --- a/src/prebuilt/wasm-bison-parser.c +++ b/src/prebuilt/wasm-bison-parser.c @@ -3385,18 +3385,6 @@ yyreturn: #line 1064 "src/wasm-bison-parser.y" /* yacc.c:1906 */ -void wasm_parser_error(WasmLocation* loc, - WasmLexer lexer, - WasmParser* parser, - const char* fmt, - ...) { - parser->errors++; - va_list args; - va_start(args, fmt); - wasm_vfprint_error(stderr, loc, lexer, fmt, args); - va_end(args); -} - static WasmResult parse_const(WasmType type, WasmLiteralType literal_type, const char* s, @@ -3490,11 +3478,14 @@ static WasmResult dup_string_contents(WasmAllocator* allocator, return WASM_OK; } -WasmResult wasm_parse(WasmLexer lexer, struct WasmScript* out_script) { +WasmResult wasm_parse(WasmLexer lexer, + struct WasmScript* out_script, + WasmSourceErrorHandler* error_handler) { WasmParser parser; WASM_ZERO_MEMORY(parser); WasmAllocator* allocator = wasm_lexer_get_allocator(lexer); parser.allocator = allocator; + parser.error_handler = error_handler; out_script->allocator = allocator; int result = wasm_parser_parse(lexer, &parser); out_script->commands = parser.script.commands; diff --git a/src/sexpr-wasm.c b/src/sexpr-wasm.c index c981d6ba..268e8848 100644 --- a/src/sexpr-wasm.c +++ b/src/sexpr-wasm.c @@ -52,6 +52,11 @@ static WasmWriteBinarySpecOptions s_write_binary_spec_options = static WasmBool s_spec; static WasmBool s_use_libc_allocator; +static WasmSourceErrorHandler s_error_handler = + WASM_SOURCE_ERROR_HANDLER_DEFAULT; +static WasmSourceErrorHandler s_assert_invalid_error_handler = + WASM_ASSERT_INVALID_SOURCE_ERROR_HANDLER_DEFAULT; + #define NOPE WASM_OPTION_NO_ARGUMENT #define YEP WASM_OPTION_HAS_ARGUMENT @@ -380,10 +385,15 @@ int main(int argc, char** argv) { WASM_FATAL("unable to read %s\n", s_infile); WasmScript script; - WasmResult result = wasm_parse(lexer, &script); + WasmResult result = wasm_parse(lexer, &script, &s_error_handler); if (WASM_SUCCEEDED(result)) { - result = wasm_check_ast(lexer, &script); + result = wasm_check_ast(lexer, &script, &s_error_handler); + + if (WASM_SUCCEEDED(result)) { + result = wasm_check_assert_invalid( + lexer, &script, &s_assert_invalid_error_handler, &s_error_handler); + } if (WASM_SUCCEEDED(result)) { result = wasm_mark_used_blocks(allocator, &script); diff --git a/src/wasm-ast-checker.c b/src/wasm-ast-checker.c index 2b000680..9de27142 100644 --- a/src/wasm-ast-checker.c +++ b/src/wasm-ast-checker.c @@ -22,7 +22,6 @@ #include <stdarg.h> #include <stdio.h> -#include "wasm-allocator.h" #include "wasm-parser-lexer-shared.h" static const char* s_type_names[] = { @@ -88,11 +87,10 @@ typedef struct WasmLabelNode { } WasmLabelNode; typedef struct WasmContext { - WasmAllocator* allocator; + WasmSourceErrorHandler* error_handler; WasmLexer lexer; const WasmModule* last_module; WasmLabelNode* top_label; - WasmBool in_assert_invalid; int max_depth; WasmResult result; } WasmContext; @@ -101,16 +99,10 @@ static void print_error(WasmContext* ctx, const WasmLocation* loc, const char* fmt, ...) { - FILE* out = stderr; ctx->result = WASM_ERROR; - if (ctx->in_assert_invalid) { - out = stdout; - fprintf(out, "assert_invalid error:\n "); - } - va_list args; va_start(args, fmt); - wasm_vfprint_error(out, loc, ctx->lexer, fmt, args); + wasm_format_error(ctx->error_handler, loc, ctx->lexer, fmt, args); va_end(args); } @@ -929,18 +921,9 @@ static void check_command(WasmContext* ctx, const WasmCommand* command) { check_invoke(ctx, &command->invoke, WASM_TYPE_SET_VOID); break; - case WASM_COMMAND_TYPE_ASSERT_INVALID: { - WasmContext ctx2 = *ctx; - ctx2.result = WASM_OK; - ctx2.in_assert_invalid = WASM_TRUE; - check_module(&ctx2, &command->assert_invalid.module); - - if (WASM_SUCCEEDED(ctx2.result)) { - print_error(ctx, &command->assert_invalid.module.loc, - "expected module to be invalid"); - } + case WASM_COMMAND_TYPE_ASSERT_INVALID: + /* ignore */ break; - } case WASM_COMMAND_TYPE_ASSERT_RETURN: check_invoke(ctx, &command->assert_return.invoke, @@ -961,11 +944,13 @@ static void check_command(WasmContext* ctx, const WasmCommand* command) { } } -WasmResult wasm_check_ast(WasmLexer lexer, const WasmScript* script) { +WasmResult wasm_check_ast(WasmLexer lexer, + const struct WasmScript* script, + WasmSourceErrorHandler* error_handler) { WasmContext ctx; WASM_ZERO_MEMORY(ctx); ctx.lexer = lexer; - ctx.allocator = script->allocator; + ctx.error_handler = error_handler; ctx.result = WASM_OK; size_t i; for (i = 0; i < script->commands.size; ++i) @@ -973,3 +958,34 @@ WasmResult wasm_check_ast(WasmLexer lexer, const WasmScript* script) { return ctx.result; } +WasmResult wasm_check_assert_invalid( + WasmLexer lexer, + const struct WasmScript* script, + WasmSourceErrorHandler* assert_invalid_error_handler, + WasmSourceErrorHandler* error_handler) { + WasmContext ctx; + WASM_ZERO_MEMORY(ctx); + ctx.lexer = lexer; + ctx.error_handler = error_handler; + ctx.result = WASM_OK; + + size_t i; + for (i = 0; i < script->commands.size; ++i) { + WasmCommand* command = &script->commands.data[i]; + if (command->type != WASM_COMMAND_TYPE_ASSERT_INVALID) + continue; + + WasmContext ai_ctx; + WASM_ZERO_MEMORY(ai_ctx); + ai_ctx.lexer = lexer; + ai_ctx.error_handler = assert_invalid_error_handler; + ai_ctx.result = WASM_OK; + check_module(&ai_ctx, &command->assert_invalid.module); + + if (WASM_SUCCEEDED(ai_ctx.result)) { + print_error(&ctx, &command->assert_invalid.module.loc, + "expected module to be invalid"); + } + } + return ctx.result; +} diff --git a/src/wasm-ast-checker.h b/src/wasm-ast-checker.h index ed6b4c40..c52525fc 100644 --- a/src/wasm-ast-checker.h +++ b/src/wasm-ast-checker.h @@ -20,10 +20,20 @@ #include "wasm-common.h" #include "wasm-lexer.h" +struct WasmAllocator; +struct WasmModule; struct WasmScript; WASM_EXTERN_C_BEGIN -WasmResult wasm_check_ast(WasmLexer lexer, const struct WasmScript*); +WasmResult wasm_check_ast(WasmLexer, + const struct WasmScript*, + WasmSourceErrorHandler*); + +WasmResult wasm_check_assert_invalid( + WasmLexer, + const struct WasmScript*, + WasmSourceErrorHandler* assert_invalid_error_handler, + WasmSourceErrorHandler* error_handler); WASM_EXTERN_C_END #endif /* WASM_AST_CHECKER_H_ */ diff --git a/src/wasm-bison-parser.y b/src/wasm-bison-parser.y index dc5ad185..ad3a3067 100644 --- a/src/wasm-bison-parser.y +++ b/src/wasm-bison-parser.y @@ -1063,18 +1063,6 @@ script_start : %% -void wasm_parser_error(WasmLocation* loc, - WasmLexer lexer, - WasmParser* parser, - const char* fmt, - ...) { - parser->errors++; - va_list args; - va_start(args, fmt); - wasm_vfprint_error(stderr, loc, lexer, fmt, args); - va_end(args); -} - static WasmResult parse_const(WasmType type, WasmLiteralType literal_type, const char* s, @@ -1168,11 +1156,14 @@ static WasmResult dup_string_contents(WasmAllocator* allocator, return WASM_OK; } -WasmResult wasm_parse(WasmLexer lexer, struct WasmScript* out_script) { +WasmResult wasm_parse(WasmLexer lexer, + struct WasmScript* out_script, + WasmSourceErrorHandler* error_handler) { WasmParser parser; WASM_ZERO_MEMORY(parser); WasmAllocator* allocator = wasm_lexer_get_allocator(lexer); parser.allocator = allocator; + parser.error_handler = error_handler; out_script->allocator = allocator; int result = wasm_parser_parse(lexer, &parser); out_script->commands = parser.script.commands; diff --git a/src/wasm-common.c b/src/wasm-common.c index 44cde3eb..c311bcef 100644 --- a/src/wasm-common.c +++ b/src/wasm-common.c @@ -132,3 +132,52 @@ WasmResult wasm_read_file(WasmAllocator* allocator, fclose(infile); return WASM_OK; } + +static void print_carets(FILE* out, + size_t num_spaces, + size_t num_carets, + size_t max_line) { + /* print the caret */ + char* carets = alloca(max_line); + memset(carets, '^', max_line); + if (num_carets > max_line - num_spaces) + num_carets = max_line - num_spaces; + fprintf(out, "%*s%.*s\n", (int)num_spaces, "", (int)num_carets, carets); +} + +static void print_error(FILE* out, + const WasmLocation* loc, + const char* error, + const char* source_line, + size_t source_line_length, + size_t source_line_column_offset) { + fprintf(out, "%s:%d:%d: %s\n", loc->filename, loc->line, loc->first_column, + error); + if (source_line && source_line_length > 0) { + fprintf(out, "%s\n", source_line); + size_t num_spaces = (loc->first_column - 1) - source_line_column_offset; + size_t num_carets = loc->last_column - loc->first_column; + print_carets(out, num_spaces, num_carets, source_line_length); + } +} + +void wasm_default_error_callback(const WasmLocation* loc, + const char* error, + const char* source_line, + size_t source_line_length, + size_t source_line_column_offset, + void* user_data) { + print_error(stderr, loc, error, source_line, source_line_length, + source_line_column_offset); +} + +void wasm_default_assert_invalid_callback(const WasmLocation* loc, + const char* error, + const char* source_line, + size_t source_line_length, + size_t source_line_column_offset, + void* user_data) { + fprintf(stdout, "assert_invalid error:\n "); + print_error(stdout, loc, error, source_line, source_line_length, + source_line_column_offset); +} diff --git a/src/wasm-common.h b/src/wasm-common.h index deca31d4..22c04a30 100644 --- a/src/wasm-common.h +++ b/src/wasm-common.h @@ -92,6 +92,26 @@ typedef struct WasmLocation { int last_column; } WasmLocation; +typedef void (*WasmSourceErrorCallback)(const WasmLocation*, + const char* error, + const char* source_line, + size_t source_line_length, + size_t source_line_column_offset, + void* user_data); + +typedef struct WasmSourceErrorHandler { + WasmSourceErrorCallback on_error; + /* on_error will be called with with source_line trimmed to this length */ + size_t source_line_max_length; + void* user_data; +} WasmSourceErrorHandler; + +#define WASM_SOURCE_ERROR_HANDLER_DEFAULT \ + { wasm_default_error_callback, 80, NULL } + +#define WASM_ASSERT_INVALID_SOURCE_ERROR_HANDLER_DEFAULT \ + { wasm_default_assert_invalid_callback, 80, NULL } + /* matches binary format, do not change */ enum { WASM_TYPE_VOID, @@ -331,6 +351,18 @@ WasmResult wasm_read_file(struct WasmAllocator* allocator, const char* filename, void** out_data, size_t* out_size); +void wasm_default_error_callback(const WasmLocation*, + const char* error, + const char* source_line, + size_t source_line_length, + size_t source_line_column_offset, + void* user_data); +void wasm_default_assert_invalid_callback(const WasmLocation*, + const char* error, + const char* source_line, + size_t source_line_length, + size_t source_line_column_offset, + void* user_data); WASM_EXTERN_C_END #endif /* WASM_COMMON_H_ */ diff --git a/src/wasm-parser-lexer-shared.c b/src/wasm-parser-lexer-shared.c index 9a37ccab..7cc10057 100644 --- a/src/wasm-parser-lexer-shared.c +++ b/src/wasm-parser-lexer-shared.c @@ -20,21 +20,40 @@ #include <stdio.h> #include <string.h> -void wasm_vfprint_error(FILE* error_file, - const WasmLocation* loc, - WasmLexer lexer, - const char* fmt, - va_list args) { - if (loc) { - fprintf(error_file, "%s:%d:%d: ", loc->filename, loc->line, - loc->first_column); - } +void wasm_parser_error(WasmLocation* loc, + WasmLexer lexer, + WasmParser* parser, + const char* format, + ...) { + parser->errors++; + va_list args; + va_start(args, format); + wasm_format_error(parser->error_handler, loc, lexer, format, args); + va_end(args); +} - vfprintf(error_file, fmt, args); - fprintf(error_file, "\n"); +void wasm_format_error(WasmSourceErrorHandler* error_handler, + const struct WasmLocation* loc, + WasmLexer lexer, + const char* format, + va_list args) { + va_list args_copy; + va_copy(args_copy, args); + char fixed_buf[WASM_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE]; + char* buffer = fixed_buf; + size_t len = wasm_vsnprintf(fixed_buf, sizeof(fixed_buf), format, args); + if (len + 1 > sizeof(fixed_buf)) { + buffer = alloca(len + 1); + len = wasm_vsnprintf(buffer, len + 1, format, args_copy); + } + char* source_line = NULL; + size_t source_line_length = 0; + size_t source_line_column_offset = 0; + size_t source_line_max_length = error_handler->source_line_max_length; if (loc) { - /* print the line and a cute little caret, like clang */ + source_line = alloca(source_line_max_length + 1); + size_t line_offset = wasm_lexer_get_file_offset_from_line(lexer, loc->line); FILE* lexer_file = wasm_lexer_get_file(lexer); long old_offset = ftell(lexer_file); @@ -67,67 +86,70 @@ void wasm_vfprint_error(FILE* error_file, next_line_offset--; } -#define MAX_LINE 80 - size_t line_length = next_line_offset - line_offset; + source_line_length = next_line_offset - line_offset; size_t column_range = loc->last_column - loc->first_column; size_t start_offset = line_offset; - if (line_length > MAX_LINE) { - line_length = MAX_LINE; + if (source_line_length > source_line_max_length) { + source_line_length = source_line_max_length; size_t center_on; - if (column_range > MAX_LINE) { + if (column_range > source_line_max_length) { /* the column range doesn't fit, just center on first_column */ center_on = loc->first_column - 1; } else { /* the entire range fits, display it all in the center */ center_on = (loc->first_column + loc->last_column) / 2 - 1; } - if (center_on > MAX_LINE / 2) - start_offset = line_offset + center_on - MAX_LINE / 2; - if (start_offset > next_line_offset - MAX_LINE) - start_offset = next_line_offset - MAX_LINE; + if (center_on > source_line_max_length / 2) + start_offset = line_offset + center_on - source_line_max_length / 2; + if (start_offset > next_line_offset - source_line_max_length) + start_offset = next_line_offset - source_line_max_length; } - const char ellipsis[] = "..."; - size_t ellipsis_length = sizeof(ellipsis) - 1; - const char* line_prefix = ""; - const char* line_suffix = ""; - if (start_offset + line_length != next_line_offset) { - line_suffix = ellipsis; - line_length -= ellipsis_length; + source_line_column_offset = start_offset - line_offset; + + char* p = source_line; + size_t read_start = start_offset; + size_t read_length = source_line_length; + WasmBool has_start_ellipsis = start_offset != line_offset; + WasmBool has_end_ellipsis = + start_offset + source_line_length != next_line_offset; + + if (has_start_ellipsis) { + memcpy(p, "...", 3); + p += 3; + read_start += 3; + read_length -= 3; } - if (start_offset != line_offset) { - start_offset += ellipsis_length; - line_length -= ellipsis_length; - line_prefix = ellipsis; + if (has_end_ellipsis) { + read_length -= 3; } - if (fseek(lexer_file, start_offset, SEEK_SET) != -1) { - char buffer[MAX_LINE]; - size_t bytes_read = fread(buffer, 1, line_length, lexer_file); - if (bytes_read > 0) { - fprintf(error_file, "%s%.*s%s\n", line_prefix, (int)bytes_read, - buffer, line_suffix); - - /* print the caret */ - char carets[MAX_LINE]; - memset(carets, '^', sizeof(carets)); - size_t num_spaces = (loc->first_column - 1) - - (start_offset - line_offset) + - strlen(line_prefix); - size_t num_carets = column_range; - if (num_carets > MAX_LINE - num_spaces) - num_carets = MAX_LINE - num_spaces; - fprintf(error_file, "%*s%.*s\n", (int)num_spaces, "", (int)num_carets, - carets); - } + if (fseek(lexer_file, read_start, SEEK_SET) != -1) { + size_t bytes_read = fread(p, 1, read_length, lexer_file); + if (bytes_read > 0) + p += bytes_read; } + if (has_end_ellipsis) { + memcpy(p, "...", 3); + p += 3; + } + + source_line_length = p - source_line; + + *p = '\0'; + if (fseek(lexer_file, old_offset, SEEK_SET) == -1) { /* we're screwed now, blow up. */ WASM_FATAL("failed to seek."); } } } -} + if (error_handler->on_error) { + error_handler->on_error(loc, buffer, source_line, source_line_length, + source_line_column_offset, error_handler->user_data); + } + va_end(args_copy); +} diff --git a/src/wasm-parser-lexer-shared.h b/src/wasm-parser-lexer-shared.h index 12b0f885..3acd1222 100644 --- a/src/wasm-parser-lexer-shared.h +++ b/src/wasm-parser-lexer-shared.h @@ -71,6 +71,7 @@ typedef union WasmToken { typedef struct WasmParser { struct WasmAllocator* allocator; WasmScript script; + WasmSourceErrorHandler* error_handler; int errors; } WasmParser; @@ -87,11 +88,11 @@ void wasm_parser_error(struct WasmLocation*, struct WasmParser*, const char*, ...); -void wasm_vfprint_error(FILE*, - const struct WasmLocation*, - WasmLexer, - const char*, - va_list); +void wasm_format_error(WasmSourceErrorHandler*, + const struct WasmLocation*, + WasmLexer, + const char* format, + va_list); WASM_EXTERN_C_END #endif /* WASM_PARSER_LEXER_SHARED_H_ */ diff --git a/src/wasm-parser.h b/src/wasm-parser.h index abbdc662..b383da96 100644 --- a/src/wasm-parser.h +++ b/src/wasm-parser.h @@ -23,7 +23,9 @@ struct WasmScript; WASM_EXTERN_C_BEGIN -WasmResult wasm_parse(WasmLexer lexer, struct WasmScript* out_script); +WasmResult wasm_parse(WasmLexer lexer, + struct WasmScript* out_script, + WasmSourceErrorHandler*); WASM_EXTERN_C_END #endif /* WASM_PARSER_H_ */ |