summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/prebuilt/wasm-bison-parser.c17
-rw-r--r--src/sexpr-wasm.c14
-rw-r--r--src/wasm-ast-checker.c62
-rw-r--r--src/wasm-ast-checker.h12
-rw-r--r--src/wasm-bison-parser.y17
-rw-r--r--src/wasm-common.c49
-rw-r--r--src/wasm-common.h32
-rw-r--r--src/wasm-parser-lexer-shared.c126
-rw-r--r--src/wasm-parser-lexer-shared.h11
-rw-r--r--src/wasm-parser.h4
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_ */