mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
argv[] may not be UTF-8 (fix #811)
This commit is contained in:
@@ -2477,7 +2477,8 @@ sections:
|
|||||||
body: |
|
body: |
|
||||||
|
|
||||||
Returns the name of the file whose input is currently being
|
Returns the name of the file whose input is currently being
|
||||||
filtered.
|
filtered. Note that this will not work well unless jq is
|
||||||
|
running in a UTF-8 locale.
|
||||||
|
|
||||||
- title: "`input_line_number`"
|
- title: "`input_line_number`"
|
||||||
body: |
|
body: |
|
||||||
|
|||||||
11
jq.h
11
jq.h
@@ -37,12 +37,19 @@ jv jq_get_lib_dirs(jq_state *);
|
|||||||
void jq_set_attr(jq_state *, jv, jv);
|
void jq_set_attr(jq_state *, jv, jv);
|
||||||
jv jq_get_attr(jq_state *, jv);
|
jv jq_get_attr(jq_state *, jv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use char * instead of jf for filenames here because filenames
|
||||||
|
* should be in the process' locale's codeset, which may not be UTF-8,
|
||||||
|
* whereas jv string values must be in UTF-8. This way the caller
|
||||||
|
* doesn't have to perform any codeset conversions.
|
||||||
|
*/
|
||||||
typedef struct jq_util_input_state *jq_util_input_state;
|
typedef struct jq_util_input_state *jq_util_input_state;
|
||||||
|
typedef void (*jq_util_msg_cb)(void *, const char *);
|
||||||
|
|
||||||
jq_util_input_state jq_util_input_init(jq_msg_cb, void *);
|
jq_util_input_state jq_util_input_init(jq_util_msg_cb, void *);
|
||||||
void jq_util_input_set_parser(jq_util_input_state, jv_parser *, int);
|
void jq_util_input_set_parser(jq_util_input_state, jv_parser *, int);
|
||||||
void jq_util_input_free(jq_util_input_state *);
|
void jq_util_input_free(jq_util_input_state *);
|
||||||
void jq_util_input_add_input(jq_util_input_state, jv);
|
void jq_util_input_add_input(jq_util_input_state, const char *);
|
||||||
int jq_util_input_errors(jq_util_input_state);
|
int jq_util_input_errors(jq_util_input_state);
|
||||||
jv jq_util_input_next_input(jq_util_input_state);
|
jv jq_util_input_next_input(jq_util_input_state);
|
||||||
jv jq_util_input_next_input_cb(jq_state *, void *);
|
jv jq_util_input_next_input_cb(jq_state *, void *);
|
||||||
|
|||||||
6
main.c
6
main.c
@@ -185,14 +185,14 @@ int main(int argc, char* argv[]) {
|
|||||||
jv lib_search_paths = jv_null();
|
jv lib_search_paths = jv_null();
|
||||||
for (int i=1; i<argc; i++, short_opts = 0) {
|
for (int i=1; i<argc; i++, short_opts = 0) {
|
||||||
if (further_args_are_files) {
|
if (further_args_are_files) {
|
||||||
jq_util_input_add_input(input_state, jv_string(argv[i]));
|
jq_util_input_add_input(input_state, argv[i]);
|
||||||
nfiles++;
|
nfiles++;
|
||||||
} else if (!strcmp(argv[i], "--")) {
|
} else if (!strcmp(argv[i], "--")) {
|
||||||
if (!program) usage(2);
|
if (!program) usage(2);
|
||||||
further_args_are_files = 1;
|
further_args_are_files = 1;
|
||||||
} else if (!isoptish(argv[i])) {
|
} else if (!isoptish(argv[i])) {
|
||||||
if (program) {
|
if (program) {
|
||||||
jq_util_input_add_input(input_state, jv_string(argv[i]));
|
jq_util_input_add_input(input_state, argv[i]);
|
||||||
nfiles++;
|
nfiles++;
|
||||||
} else {
|
} else {
|
||||||
program = argv[i];
|
program = argv[i];
|
||||||
@@ -484,7 +484,7 @@ int main(int argc, char* argv[]) {
|
|||||||
jq_set_debug_cb(jq, debug_cb, &dumpopts);
|
jq_set_debug_cb(jq, debug_cb, &dumpopts);
|
||||||
|
|
||||||
if (nfiles == 0)
|
if (nfiles == 0)
|
||||||
jq_util_input_add_input(input_state, jv_string("-"));
|
jq_util_input_add_input(input_state, "-");
|
||||||
|
|
||||||
if (options & PROVIDE_NULL) {
|
if (options & PROVIDE_NULL) {
|
||||||
ret = process(jq, jv_null(), jq_flags, dumpopts);
|
ret = process(jq, jv_null(), jq_flags, dumpopts);
|
||||||
|
|||||||
51
util.c
51
util.c
@@ -162,11 +162,13 @@ not_this:
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct jq_util_input_state {
|
struct jq_util_input_state {
|
||||||
jq_msg_cb err_cb;
|
jq_util_msg_cb err_cb;
|
||||||
void *err_cb_data;
|
void *err_cb_data;
|
||||||
jv_parser *parser;
|
jv_parser *parser;
|
||||||
FILE* current_input;
|
FILE* current_input;
|
||||||
jv files;
|
char **files;
|
||||||
|
int nfiles;
|
||||||
|
int curr_file;
|
||||||
int failures;
|
int failures;
|
||||||
jv slurped;
|
jv slurped;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
@@ -175,13 +177,12 @@ struct jq_util_input_state {
|
|||||||
size_t current_line;
|
size_t current_line;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void fprinter(void *data, jv fname) {
|
static void fprinter(void *data, const char *fname) {
|
||||||
fprintf((FILE *)data, "jq: error: Could not open file %s: %s\n", jv_string_value(fname), strerror(errno));
|
fprintf((FILE *)data, "jq: error: Could not open file %s: %s\n", fname, strerror(errno));
|
||||||
jv_free(fname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If parser == NULL -> RAW
|
// If parser == NULL -> RAW
|
||||||
jq_util_input_state jq_util_input_init(jq_msg_cb err_cb, void *err_cb_data) {
|
jq_util_input_state jq_util_input_init(jq_util_msg_cb err_cb, void *err_cb_data) {
|
||||||
if (err_cb == NULL) {
|
if (err_cb == NULL) {
|
||||||
err_cb = fprinter;
|
err_cb = fprinter;
|
||||||
err_cb_data = stderr;
|
err_cb_data = stderr;
|
||||||
@@ -192,7 +193,9 @@ jq_util_input_state jq_util_input_init(jq_msg_cb err_cb, void *err_cb_data) {
|
|||||||
new_state->err_cb_data = err_cb_data;
|
new_state->err_cb_data = err_cb_data;
|
||||||
new_state->parser = NULL;
|
new_state->parser = NULL;
|
||||||
new_state->current_input = NULL;
|
new_state->current_input = NULL;
|
||||||
new_state->files = jv_array();
|
new_state->files = NULL;
|
||||||
|
new_state->nfiles = 0;
|
||||||
|
new_state->curr_file = 0;
|
||||||
new_state->slurped = jv_invalid();
|
new_state->slurped = jv_invalid();
|
||||||
new_state->buf[0] = 0;
|
new_state->buf[0] = 0;
|
||||||
new_state->buf_valid_len = 0;
|
new_state->buf_valid_len = 0;
|
||||||
@@ -222,25 +225,27 @@ void jq_util_input_free(jq_util_input_state *state) {
|
|||||||
|
|
||||||
if (old_state->parser != NULL)
|
if (old_state->parser != NULL)
|
||||||
jv_parser_free(old_state->parser);
|
jv_parser_free(old_state->parser);
|
||||||
jv_free(old_state->files);
|
for (int i = 0; i < old_state->nfiles; i++)
|
||||||
|
free(old_state->files[i]);
|
||||||
|
free(old_state->files);
|
||||||
jv_free(old_state->slurped);
|
jv_free(old_state->slurped);
|
||||||
jv_free(old_state->current_filename);
|
jv_free(old_state->current_filename);
|
||||||
jv_mem_free(old_state);
|
jv_mem_free(old_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void jq_util_input_add_input(jq_util_input_state state, jv fname) {
|
void jq_util_input_add_input(jq_util_input_state state, const char *fname) {
|
||||||
state->files = jv_array_append(state->files, fname);
|
state->files = jv_mem_realloc(state->files, (state->nfiles + 1) * sizeof(state->files[0]));
|
||||||
|
state->files[state->nfiles++] = jv_mem_strdup(fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
int jq_util_input_errors(jq_util_input_state state) {
|
int jq_util_input_errors(jq_util_input_state state) {
|
||||||
return state->failures;
|
return state->failures;
|
||||||
}
|
}
|
||||||
|
|
||||||
static jv next_file(jq_util_input_state state) {
|
static const char *next_file(jq_util_input_state state) {
|
||||||
jv next = jv_array_get(jv_copy(state->files), 0);
|
if (state->curr_file < state->nfiles)
|
||||||
if (jv_array_length(jv_copy(state->files)) > 0)
|
return state->files[state->curr_file++];
|
||||||
state->files = jv_array_slice(state->files, 1, jv_array_length(jv_copy(state->files)));
|
return NULL;
|
||||||
return next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jq_util_input_read_more(jq_util_input_state state) {
|
static int jq_util_input_read_more(jq_util_input_state state) {
|
||||||
@@ -262,21 +267,20 @@ static int jq_util_input_read_more(jq_util_input_state state) {
|
|||||||
state->current_filename = jv_invalid();
|
state->current_filename = jv_invalid();
|
||||||
state->current_line = 0 ;
|
state->current_line = 0 ;
|
||||||
}
|
}
|
||||||
jv f = next_file(state);
|
const char *f = next_file(state);
|
||||||
if (jv_is_valid(f)) {
|
if (f != NULL) {
|
||||||
if (!strcmp(jv_string_value(f), "-")) {
|
if (!strcmp(f, "-")) {
|
||||||
state->current_input = stdin;
|
state->current_input = stdin;
|
||||||
state->current_filename = jv_string("<stdin>");
|
state->current_filename = jv_string("<stdin>");
|
||||||
} else {
|
} else {
|
||||||
state->current_input = fopen(jv_string_value(f), "r");
|
state->current_input = fopen(f, "r");
|
||||||
state->current_filename = jv_copy(f);
|
state->current_filename = jv_string(f);
|
||||||
if (!state->current_input) {
|
if (!state->current_input) {
|
||||||
state->err_cb(state->err_cb_data, jv_copy(f));
|
state->err_cb(state->err_cb_data, f);
|
||||||
state->failures++;
|
state->failures++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state->current_line = 0;
|
state->current_line = 0;
|
||||||
jv_free(f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +334,8 @@ static int jq_util_input_read_more(jq_util_input_state state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return jv_array_length(jv_copy(state->files)) == 0 && (!state->current_input || feof(state->current_input));
|
return state->curr_file == state->nfiles &&
|
||||||
|
(!state->current_input || feof(state->current_input) || ferror(state->current_input));
|
||||||
}
|
}
|
||||||
|
|
||||||
jv jq_util_input_next_input_cb(jq_state *jq, void *data) {
|
jv jq_util_input_next_input_cb(jq_state *jq, void *data) {
|
||||||
|
|||||||
Reference in New Issue
Block a user