diff --git a/builtin.c b/builtin.c index 462307dd..cef1d540 100644 --- a/builtin.c +++ b/builtin.c @@ -1441,7 +1441,7 @@ static const char* const jq_builtins[] = { static int builtins_bind_one(jq_state *jq, block* bb, const char* code) { struct locfile* src; - src = locfile_init(jq, code, strlen(code)); + src = locfile_init(jq, "", code, strlen(code)); block funcs; int nerrors = jq_parse_library(src, &funcs); if (nerrors == 0) { diff --git a/execute.c b/execute.c index 6c6c9b11..d5f243bd 100644 --- a/execute.c +++ b/execute.c @@ -1008,7 +1008,7 @@ int jq_compile_args(jq_state *jq, const char* str, jv args) { jv_nomem_handler(jq->nomem_handler, jq->nomem_handler_data); assert(jv_get_kind(args) == JV_KIND_ARRAY); struct locfile* locations; - locations = locfile_init(jq, str, strlen(str)); + locations = locfile_init(jq, "", str, strlen(str)); block program; jq_reset(jq); if (jq->bc) { diff --git a/jq_test.c b/jq_test.c index 6a00cab1..b68514b5 100644 --- a/jq_test.c +++ b/jq_test.c @@ -30,8 +30,12 @@ static int skipline(const char* buf) { return 0; } +static int checkerrormsg(const char* buf) { + return strcmp(buf, "%%FAIL\n") == 0; +} + static int checkfail(const char* buf) { - return !strcmp(buf, "%%FAIL\n"); + return strcmp(buf, "%%FAIL\n") == 0 || strcmp(buf, "%%FAIL IGNORE MSG\n") == 0; } struct err_data { @@ -56,6 +60,7 @@ static void run_jq_tests(jv lib_dirs, FILE *testdata) { int tests = 0, passed = 0, invalid = 0; unsigned int lineno = 0; int must_fail = 0; + int check_msg = 0; jq_state *jq = NULL; jq = jq_init(); @@ -70,6 +75,7 @@ static void run_jq_tests(jv lib_dirs, FILE *testdata) { if (skipline(prog)) continue; if (checkfail(prog)) { must_fail = 1; + check_msg = checkerrormsg(prog); jq_set_error_cb(jq, test_err_cb, &err_msg); continue; } @@ -82,6 +88,7 @@ static void run_jq_tests(jv lib_dirs, FILE *testdata) { if (must_fail) { jq_set_error_cb(jq, NULL, NULL); must_fail = 0; + check_msg = 0; if (!fgets(buf, sizeof(buf), testdata)) { invalid++; break; } lineno++; if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0; @@ -89,7 +96,7 @@ static void run_jq_tests(jv lib_dirs, FILE *testdata) { printf("*** Test program compiled that should not have at line %u: %s\n", lineno, prog); invalid++; continue; } - if (strcmp(buf, err_msg.buf)) { + if (check_msg && strcmp(buf, err_msg.buf) != 0) { printf("*** Erroneous test program failed with wrong message (%s) at line %u: %s\n", err_msg.buf, lineno, prog); invalid++; } else { diff --git a/linker.c b/linker.c index d07028f2..b83f00e8 100644 --- a/linker.c +++ b/linker.c @@ -276,7 +276,7 @@ static int load_library(jq_state *jq, jv lib_path, int is_data, int raw, const c program = gen_const_global(jv_copy(data), as); } else { // import "foo" as bar; - src = locfile_init(jq, jv_string_value(data), jv_string_length_bytes(jv_copy(data))); + src = locfile_init(jq, jv_string_value(lib_path), jv_string_value(data), jv_string_length_bytes(jv_copy(data))); nerrors += jq_parse_library(src, &program); if (nerrors == 0) { char *lib_origin = strdup(jv_string_value(lib_path)); @@ -311,7 +311,7 @@ jv load_module_meta(jq_state *jq, jv mod_relpath) { jv data = jv_load_file(jv_string_value(lib_path), 1); if (jv_is_valid(data)) { block program; - struct locfile* src = locfile_init(jq, jv_string_value(data), jv_string_length_bytes(jv_copy(data))); + struct locfile* src = locfile_init(jq, jv_string_value(lib_path), jv_string_value(data), jv_string_length_bytes(jv_copy(data))); int nerrors = jq_parse_library(src, &program); if (nerrors == 0) { meta = block_module_meta(program); diff --git a/locfile.c b/locfile.c index 1a60f42e..7753d901 100644 --- a/locfile.c +++ b/locfile.c @@ -9,9 +9,10 @@ #include "locfile.h" -struct locfile* locfile_init(jq_state *jq, const char* data, int length) { +struct locfile* locfile_init(jq_state *jq, const char *fname, const char* data, int length) { struct locfile* l = jv_mem_alloc(sizeof(struct locfile)); l->jq = jq; + l->fname = jv_string(fname); l->data = jv_mem_alloc(length); memcpy((char*)l->data,data,length); l->length = length; @@ -39,6 +40,7 @@ struct locfile* locfile_retain(struct locfile* l) { } void locfile_free(struct locfile* l) { if (--(l->refct) == 0) { + jv_free(l->fname); jv_mem_free(l->linemap); jv_mem_free((char*)l->data); jv_mem_free(l); @@ -79,7 +81,8 @@ void locfile_locate(struct locfile* l, location loc, const char* fmt, ...) { jv_free(m1); return; } - jv m2 = jv_string_fmt("%s\n%.*s%*s", jv_string_value(m1), + jv m2 = jv_string_fmt("%s at %s, line %d:\n%.*s%*s", jv_string_value(m1), + jv_string_value(l->fname), startline + 1, locfile_line_length(l, startline), l->data + offset, loc.start - offset, ""); jv_free(m1); diff --git a/locfile.h b/locfile.h index 48c460f4..8c141698 100644 --- a/locfile.h +++ b/locfile.h @@ -10,6 +10,7 @@ typedef struct { static const location UNKNOWN_LOCATION = {-1, -1}; struct locfile { + jv fname; const char* data; int length; int* linemap; @@ -19,11 +20,9 @@ struct locfile { int refct; }; -struct locfile* locfile_init(jq_state *jq, const char* data, int length); -struct locfile* locfile_retain(struct locfile* l); - -void locfile_free(struct locfile* l); - -void locfile_locate(struct locfile* l, location loc, const char* fmt, ...); +struct locfile* locfile_init(jq_state *, const char *, const char *, int); +struct locfile* locfile_retain(struct locfile *); +void locfile_free(struct locfile *); +void locfile_locate(struct locfile *, location, const char *, ...); #endif diff --git a/tests/all.test b/tests/all.test index ba3bb6ee..5b90420d 100644 --- a/tests/all.test +++ b/tests/all.test @@ -257,7 +257,7 @@ null %%FAIL . as $foo | break $foo -jq: error: *label-foo/0 is not defined +jq: error: *label-foo/0 is not defined at , line 1: [.[]|[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1]] [1,2,3,4,5] @@ -1153,13 +1153,13 @@ modulemeta "c" {"whatever":null,"deps":[{"as":"foo","is_data":false,"relpath":"a"},{"search":"./","as":"d","is_data":false,"relpath":"d"},{"search":"./","as":"d2","is_data":false,"relpath":"d"},{"search":"./../lib/jq","as":"e","is_data":false,"relpath":"e"},{"search":"./../lib/jq","as":"f","is_data":false,"relpath":"f"},{"as":"d","is_data":true,"relpath":"data"}]} -%%FAIL +%%FAIL IGNORE MSG import "syntaxerror" as e; . -jq: error: syntax error, unexpected ';', expecting $end (Unix shell quoting issues?) +jq: error: syntax error, unexpected ';', expecting $end (Unix shell quoting issues?) at /home/nico/ws/jq/tests/modules/syntaxerror/syntaxerror.jq, line 1: %%FAIL %::wat -jq: error: syntax error, unexpected '%', expecting $end (Unix shell quoting issues?) +jq: error: syntax error, unexpected '%', expecting $end (Unix shell quoting issues?) at , line 1: import "test_bind_order" as check; check::check null