if (jv_invalid_has_msg(jv_copy(result))) {
// Uncaught jq exception
jv msg = jv_invalid_get_msg(jv_copy(result));
+ jv input_pos = jq_util_input_get_position(jq);
if (jv_get_kind(msg) == JV_KIND_STRING) {
- fprintf(stderr, "jq: error: %s\n", jv_string_value(msg));
+ fprintf(stderr, "jq: error (at %s): %s\n",
+ jv_string_value(input_pos), jv_string_value(msg));
} else {
msg = jv_dump_string(msg, 0);
- fprintf(stderr, "jq: error (not a string): %s\n", jv_string_value(msg));
+ fprintf(stderr, "jq: error (at %s) (not a string): %s\n",
+ jv_string_value(input_pos), jv_string_value(msg));
}
ret = 5;
+ jv_free(input_pos);
jv_free(msg);
}
jv_free(result);
jv slurped;
char buf[4096];
size_t buf_valid_len;
+ jv current_filename;
+ size_t current_line;
};
static void fprinter(void *data, jv fname) {
new_state->slurped = jv_invalid();
new_state->buf[0] = 0;
new_state->buf_valid_len = 0;
+ new_state->current_filename = jv_invalid();
+ new_state->current_line = 0;
return new_state;
}
jv_parser_free(old_state->parser);
jv_free(old_state->files);
jv_free(old_state->slurped);
+ jv_free(old_state->current_filename);
jv_mem_free(old_state);
}
fclose(state->current_input);
}
state->current_input = NULL;
+ jv_free(state->current_filename);
+ state->current_filename = jv_invalid();
+ state->current_line = 0 ;
}
jv f = next_file(state);
if (jv_is_valid(f)) {
if (!strcmp(jv_string_value(f), "-")) {
state->current_input = stdin;
+ state->current_filename = jv_string("<stdin>");
} else {
state->current_input = fopen(jv_string_value(f), "r");
+ state->current_filename = jv_copy(f);
if (!state->current_input) {
state->err_cb(state->err_cb_data, jv_copy(f));
state->failures++;
}
}
+ state->current_line = 0;
jv_free(f);
}
}
state->failures++;
} else {
const char *p = memchr(state->buf, '\n', sizeof(state->buf));
+
+ if (p != NULL)
+ state->current_line++;
if (p == NULL && state->parser != NULL) {
/*
return jq_util_input_next_input((jq_util_input_state)data);
}
+// Return the current_filename:current_line
+jv jq_util_input_get_position(jq_state *jq) {
+ jq_input_cb cb = NULL;
+ void *cb_data = NULL;
+ jq_get_input_cb(jq, &cb, &cb_data);
+ assert(cb == jq_util_input_next_input_cb);
+ if (cb != jq_util_input_next_input_cb)
+ return jv_invalid_with_msg(jv_string("Invalid jq_util_input API usage"));
+ jq_util_input_state s = (jq_util_input_state)cb_data;
+
+ // We can't assert that current_filename is a string because if
+ // the error was a JSON parser error then we may not have set
+ // current_filename yet.
+ if (jv_get_kind(s->current_filename) != JV_KIND_STRING)
+ return jv_string("<unknown>");
+
+ jv v = jv_string_fmt("%s:%zu", jv_string_value(s->current_filename), s->current_line);
+ return v;
+}
+
// Blocks to read one more input from stdin and/or given files
// When slurping, it returns just one value
jv jq_util_input_next_input(jq_util_input_state state) {