2014-07-20 00:11:23 -05:00
|
|
|
#include <assert.h>
|
2014-07-09 00:55:20 -04:00
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <libgen.h>
|
2013-05-26 12:42:04 +10:00
|
|
|
#include <stdlib.h>
|
2012-08-16 01:00:30 +01:00
|
|
|
#include <stdio.h>
|
2012-09-11 12:24:54 +01:00
|
|
|
#include <string.h>
|
2012-12-03 01:21:07 +00:00
|
|
|
#include <unistd.h>
|
2015-06-19 17:10:45 -05:00
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
#include <windows.h>
|
2015-06-22 18:15:51 -05:00
|
|
|
#include <io.h>
|
|
|
|
|
#include <fcntl.h>
|
2015-06-19 17:10:45 -05:00
|
|
|
#include <processenv.h>
|
|
|
|
|
#include <shellapi.h>
|
|
|
|
|
#include <wchar.h>
|
|
|
|
|
#include <wtypes.h>
|
2021-09-06 18:26:14 -05:00
|
|
|
extern void jv_tsd_dtoa_ctx_init();
|
2015-06-19 17:10:45 -05:00
|
|
|
#endif
|
|
|
|
|
|
2015-12-01 22:16:03 -06:00
|
|
|
#if !defined(HAVE_ISATTY) && defined(HAVE__ISATTY)
|
|
|
|
|
#undef isatty
|
|
|
|
|
#define isatty _isatty
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_ISATTY) || defined(HAVE__ISATTY)
|
|
|
|
|
#define USE_ISATTY
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-08-16 01:00:30 +01:00
|
|
|
#include "compile.h"
|
2012-09-02 16:31:59 +01:00
|
|
|
#include "jv.h"
|
2013-06-16 08:25:12 -05:00
|
|
|
#include "jq.h"
|
2012-12-18 16:52:47 +00:00
|
|
|
#include "jv_alloc.h"
|
2014-11-24 17:58:34 -06:00
|
|
|
#include "util.h"
|
2016-01-15 16:21:16 -06:00
|
|
|
#include "src/version.h"
|
2012-08-16 01:00:30 +01:00
|
|
|
|
2015-06-27 23:31:44 -05:00
|
|
|
int jq_testsuite(jv lib_dirs, int verbose, int argc, char* argv[]);
|
2013-05-05 22:53:45 +01:00
|
|
|
|
2012-09-18 23:37:46 +01:00
|
|
|
static const char* progname;
|
|
|
|
|
|
2014-06-17 16:47:12 -05:00
|
|
|
/*
|
|
|
|
|
* For a longer help message we could use a better option parsing
|
|
|
|
|
* strategy, one that lets stack options.
|
|
|
|
|
*/
|
2017-02-19 18:11:18 -06:00
|
|
|
static void usage(int code, int keep_it_short) {
|
2015-01-26 18:51:15 -06:00
|
|
|
FILE *f = stderr;
|
2015-04-28 10:39:34 -05:00
|
|
|
|
2015-01-26 18:51:15 -06:00
|
|
|
if (code == 0)
|
|
|
|
|
f = stdout;
|
2015-04-28 10:39:34 -05:00
|
|
|
|
2015-05-29 15:35:30 -05:00
|
|
|
int ret = fprintf(f,
|
|
|
|
|
"jq - commandline JSON processor [version %s]\n"
|
2017-02-19 18:11:18 -06:00
|
|
|
"\nUsage:\t%s [options] <jq filter> [file...]\n"
|
|
|
|
|
"\t%s [options] --args <jq filter> [strings...]\n"
|
|
|
|
|
"\t%s [options] --jsonargs <jq filter> [JSON_TEXTS...]\n\n"
|
2015-12-11 14:35:57 -07:00
|
|
|
"jq is a tool for processing JSON inputs, applying the given filter to\n"
|
|
|
|
|
"its JSON text inputs and producing the filter's results as JSON on\n"
|
|
|
|
|
"standard output.\n\n"
|
|
|
|
|
"The simplest filter is ., which copies jq's input to its output\n"
|
2023-07-22 23:16:03 +09:00
|
|
|
"unmodified except for formatting. For more advanced filters see\n"
|
|
|
|
|
"the jq(1) manpage (\"man jq\") and/or https://jqlang.github.io/jq/.\n\n"
|
2023-07-25 14:49:45 +02:00
|
|
|
"Example:\n\n\t$ echo '{\"foo\": 0}' | jq .\n"
|
2023-07-22 23:16:03 +09:00
|
|
|
"\t{\n\t \"foo\": 0\n\t}\n\n",
|
2017-02-19 18:11:18 -06:00
|
|
|
JQ_VERSION, progname, progname, progname);
|
|
|
|
|
if (keep_it_short) {
|
|
|
|
|
fprintf(f,
|
2023-07-22 23:16:03 +09:00
|
|
|
"For listing the command options, use %s --help.\n",
|
2017-02-19 18:11:18 -06:00
|
|
|
progname);
|
|
|
|
|
} else {
|
|
|
|
|
(void) fprintf(f,
|
2023-07-22 23:16:03 +09:00
|
|
|
"Command options:\n"
|
|
|
|
|
" -n, --null-input use `null` as the single input value;\n"
|
|
|
|
|
" -R, --raw-input read each line as strings, not parsing as JSON;\n"
|
|
|
|
|
" -s, --slurp read all inputs into an array and use it as the single input value;\n"
|
|
|
|
|
" -c, --compact-output compact instead of pretty-printed output;\n"
|
|
|
|
|
" -r, --raw-output output strings directly without escapes and quotes;\n"
|
2023-07-10 07:30:50 +09:00
|
|
|
" --raw-output0 implies -r and output NUL after each output;\n"
|
2023-07-22 23:16:03 +09:00
|
|
|
" -j, --join-output implies -r and output without newline after each output;\n"
|
|
|
|
|
" -a, --ascii-output output strings by only ASCII characters using escape sequences;\n"
|
|
|
|
|
" -S, --sort-keys sort keys of each object on output;\n"
|
|
|
|
|
" -C, --color-output colorize JSON output;\n"
|
|
|
|
|
" -M, --monochrome-output disable colored output;\n"
|
|
|
|
|
" --tab use tabs for indentation;\n"
|
|
|
|
|
" --indent n use the given number of spaces (no more than 7) for indentation;\n"
|
2023-07-25 15:24:54 +09:00
|
|
|
" --unbuffered flush output stream after each output;\n"
|
2023-07-22 23:16:03 +09:00
|
|
|
" --stream parse the input value in streaming fashion;\n"
|
|
|
|
|
" --stream-errors implies --stream and report JSON parse error with an array;\n"
|
|
|
|
|
" --seq parse input and output in application/json-seq MIME type scheme;\n"
|
|
|
|
|
" -f, --from-file file load filter from the file;\n"
|
|
|
|
|
" -L directory search modules from the directory;\n"
|
|
|
|
|
" --arg name value set variable $name to the string value;\n"
|
|
|
|
|
" --argjson name value set variable $name to the JSON value;\n"
|
|
|
|
|
" --slurpfile name file set variable $name to an array of JSON values read from the file;\n"
|
|
|
|
|
" --rawfile name file set variable $name to a string consisting of the contents of the file;\n"
|
|
|
|
|
" --args consume remaining arguments as positional string values;\n"
|
|
|
|
|
" --jsonargs consume remaining arguments as positional JSON values;\n"
|
|
|
|
|
" -e, --exit-status set the exit status code based on the output;\n"
|
|
|
|
|
" -b, --binary open input and output streams in binary mode on Windows;\n"
|
|
|
|
|
" -V, --version show the version;\n"
|
|
|
|
|
" -h, --help show the help;\n"
|
|
|
|
|
" -- terminates argument processing;\n\n"
|
2017-02-19 18:11:18 -06:00
|
|
|
"Named arguments are also available as $ARGS.named[], while\n"
|
2023-07-22 23:16:03 +09:00
|
|
|
"positional arguments are available as $ARGS.positional[].\n");
|
2017-02-19 18:11:18 -06:00
|
|
|
}
|
2015-05-29 15:35:30 -05:00
|
|
|
exit((ret < 0 && code == 0) ? 2 : code);
|
2012-09-18 23:37:46 +01:00
|
|
|
}
|
|
|
|
|
|
2012-09-20 19:31:14 +01:00
|
|
|
static void die() {
|
|
|
|
|
fprintf(stderr, "Use %s --help for help with command-line options,\n", progname);
|
2023-05-28 17:06:31 +01:00
|
|
|
fprintf(stderr, "or see the jq manpage, or online docs at https://jqlang.github.io/jq\n");
|
2013-12-26 12:54:03 -06:00
|
|
|
exit(2);
|
2012-09-20 19:31:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int isoptish(const char* text) {
|
2023-07-10 07:30:50 +09:00
|
|
|
return text[0] == '-' && (text[1] == '-' || isalpha(text[1]));
|
2012-09-20 19:31:14 +01:00
|
|
|
}
|
|
|
|
|
|
2014-06-20 23:26:54 -05:00
|
|
|
static int isoption(const char* text, char shortopt, const char* longopt, size_t *short_opts) {
|
|
|
|
|
if (text[0] != '-' || text[1] == '-')
|
|
|
|
|
*short_opts = 0;
|
2012-09-20 19:31:14 +01:00
|
|
|
if (text[0] != '-') return 0;
|
2014-06-21 18:01:00 -05:00
|
|
|
|
|
|
|
|
// check long option
|
2012-09-20 19:31:14 +01:00
|
|
|
if (text[1] == '-' && !strcmp(text+2, longopt)) return 1;
|
2014-06-21 18:01:00 -05:00
|
|
|
else if (text[1] == '-') return 0;
|
|
|
|
|
|
|
|
|
|
// must be short option; check it and...
|
2014-06-20 23:26:54 -05:00
|
|
|
if (!shortopt) return 0;
|
|
|
|
|
if (strchr(text, shortopt) != NULL) {
|
2014-06-21 18:01:00 -05:00
|
|
|
(*short_opts)++; // ...count it (for option stacking)
|
2014-06-20 23:26:54 -05:00
|
|
|
return 1;
|
|
|
|
|
}
|
2012-09-20 19:31:14 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum {
|
2014-06-17 19:04:55 -05:00
|
|
|
SLURP = 1,
|
|
|
|
|
RAW_INPUT = 2,
|
|
|
|
|
PROVIDE_NULL = 4,
|
|
|
|
|
RAW_OUTPUT = 8,
|
2023-07-10 07:30:50 +09:00
|
|
|
RAW_OUTPUT0 = 16,
|
2014-06-17 19:04:55 -05:00
|
|
|
ASCII_OUTPUT = 32,
|
2015-08-16 19:19:01 -07:00
|
|
|
COLOR_OUTPUT = 64,
|
|
|
|
|
NO_COLOR_OUTPUT = 128,
|
2014-06-17 19:04:55 -05:00
|
|
|
SORTED_OUTPUT = 256,
|
|
|
|
|
FROM_FILE = 512,
|
|
|
|
|
RAW_NO_LF = 1024,
|
|
|
|
|
UNBUFFERED_OUTPUT = 2048,
|
|
|
|
|
EXIT_STATUS = 4096,
|
2017-02-22 23:01:56 -06:00
|
|
|
EXIT_STATUS_EXACT = 8192,
|
|
|
|
|
SEQ = 16384,
|
|
|
|
|
RUN_TESTS = 32768,
|
2013-05-05 22:59:46 +01:00
|
|
|
/* debugging only */
|
2017-02-22 23:01:56 -06:00
|
|
|
DUMP_DISASM = 65536,
|
2012-09-20 19:31:14 +01:00
|
|
|
};
|
|
|
|
|
|
2018-07-29 12:50:28 -07:00
|
|
|
enum {
|
|
|
|
|
JQ_OK = 0,
|
|
|
|
|
JQ_OK_NULL_KIND = -1, /* exit 0 if --exit-status is not set*/
|
|
|
|
|
JQ_ERROR_SYSTEM = 2,
|
|
|
|
|
JQ_ERROR_COMPILE = 3,
|
|
|
|
|
JQ_OK_NO_OUTPUT = -4, /* exit 0 if --exit-status is not set*/
|
|
|
|
|
JQ_ERROR_UNKNOWN = 5,
|
|
|
|
|
};
|
|
|
|
|
#define jq_exit_with_status(r) exit(abs(r))
|
|
|
|
|
#define jq_exit(r) exit( r > 0 ? r : 0 )
|
|
|
|
|
|
2015-12-14 23:43:22 -06:00
|
|
|
static const char *skip_shebang(const char *p) {
|
|
|
|
|
if (strncmp(p, "#!", sizeof("#!") - 1) != 0)
|
|
|
|
|
return p;
|
|
|
|
|
const char *n = strchr(p, '\n');
|
|
|
|
|
if (n == NULL || n[1] != '#')
|
|
|
|
|
return p;
|
|
|
|
|
n = strchr(n + 1, '\n');
|
|
|
|
|
if (n == NULL || n[1] == '#' || n[1] == '\0' || n[-1] != '\\' || n[-2] == '\\')
|
|
|
|
|
return p;
|
|
|
|
|
n = strchr(n + 1, '\n');
|
|
|
|
|
if (n == NULL)
|
|
|
|
|
return p;
|
|
|
|
|
return n+1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-19 09:00:11 -07:00
|
|
|
static int process(jq_state *jq, jv value, int flags, int dumpopts, int options) {
|
2018-07-29 12:50:28 -07:00
|
|
|
int ret = JQ_OK_NO_OUTPUT; // No valid results && -e -> exit(4)
|
2013-06-06 17:26:15 -05:00
|
|
|
jq_start(jq, value, flags);
|
2012-09-20 19:31:14 +01:00
|
|
|
jv result;
|
2013-04-28 18:33:45 -05:00
|
|
|
while (jv_is_valid(result = jq_next(jq))) {
|
2012-09-20 19:31:14 +01:00
|
|
|
if ((options & RAW_OUTPUT) && jv_get_kind(result) == JV_KIND_STRING) {
|
2018-03-01 19:16:11 +00:00
|
|
|
if (options & ASCII_OUTPUT) {
|
2018-11-20 09:58:25 -05:00
|
|
|
jv_dumpf(jv_copy(result), stdout, JV_PRINT_ASCII);
|
2023-07-10 07:30:50 +09:00
|
|
|
} else if ((options & RAW_OUTPUT0) && strlen(jv_string_value(result)) != (unsigned long)jv_string_length_bytes(jv_copy(result))) {
|
|
|
|
|
jv_free(result);
|
|
|
|
|
result = jv_invalid_with_msg(jv_string(
|
|
|
|
|
"Cannot dump a string containing NUL with --raw-output0 option"));
|
|
|
|
|
break;
|
2018-03-01 19:16:11 +00:00
|
|
|
} else {
|
2023-06-28 17:54:40 +09:00
|
|
|
priv_fwrite(jv_string_value(result), jv_string_length_bytes(jv_copy(result)),
|
|
|
|
|
stdout, dumpopts & JV_PRINT_ISATTY);
|
2018-03-01 19:16:11 +00:00
|
|
|
}
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_OK;
|
2012-12-23 15:41:20 +00:00
|
|
|
jv_free(result);
|
2012-09-20 19:31:14 +01:00
|
|
|
} else {
|
2013-12-26 12:54:03 -06:00
|
|
|
if (jv_get_kind(result) == JV_KIND_FALSE || jv_get_kind(result) == JV_KIND_NULL)
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_OK_NULL_KIND;
|
2013-11-29 16:36:15 -06:00
|
|
|
else
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_OK;
|
2014-10-10 22:19:38 -05:00
|
|
|
if (options & SEQ)
|
2015-06-22 18:15:51 -05:00
|
|
|
priv_fwrite("\036", 1, stdout, dumpopts & JV_PRINT_ISATTY);
|
2012-09-20 19:31:14 +01:00
|
|
|
jv_dump(result, dumpopts);
|
|
|
|
|
}
|
2014-06-17 18:59:35 -05:00
|
|
|
if (!(options & RAW_NO_LF))
|
2015-06-22 18:15:51 -05:00
|
|
|
priv_fwrite("\n", 1, stdout, dumpopts & JV_PRINT_ISATTY);
|
2023-07-10 07:30:50 +09:00
|
|
|
if (options & RAW_OUTPUT0)
|
2019-10-14 12:55:30 +08:00
|
|
|
priv_fwrite("\0", 1, stdout, dumpopts & JV_PRINT_ISATTY);
|
2014-02-26 01:38:46 -06:00
|
|
|
if (options & UNBUFFERED_OUTPUT)
|
|
|
|
|
fflush(stdout);
|
2012-09-20 19:31:14 +01:00
|
|
|
}
|
2017-02-22 23:01:56 -06:00
|
|
|
if (jq_halted(jq)) {
|
|
|
|
|
// jq program invoked `halt` or `halt_error`
|
|
|
|
|
options |= EXIT_STATUS_EXACT;
|
|
|
|
|
jv exit_code = jq_get_exit_code(jq);
|
|
|
|
|
if (!jv_is_valid(exit_code))
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_OK;
|
2017-02-22 23:01:56 -06:00
|
|
|
else if (jv_get_kind(exit_code) == JV_KIND_NUMBER)
|
|
|
|
|
ret = jv_number_value(exit_code);
|
|
|
|
|
else
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_ERROR_UNKNOWN;
|
2017-02-22 23:01:56 -06:00
|
|
|
jv_free(exit_code);
|
|
|
|
|
jv error_message = jq_get_error_message(jq);
|
|
|
|
|
if (jv_get_kind(error_message) == JV_KIND_STRING) {
|
2023-06-27 07:33:21 +09:00
|
|
|
// No prefix should be added to the output of `halt_error`.
|
2023-06-28 17:54:40 +09:00
|
|
|
priv_fwrite(jv_string_value(error_message), jv_string_length_bytes(jv_copy(error_message)),
|
|
|
|
|
stderr, dumpopts & JV_PRINT_ISATTY);
|
2017-02-22 23:01:56 -06:00
|
|
|
} else if (jv_get_kind(error_message) == JV_KIND_NULL) {
|
|
|
|
|
// Halt with no output
|
|
|
|
|
} else if (jv_is_valid(error_message)) {
|
2023-07-14 15:49:06 +09:00
|
|
|
error_message = jv_dump_string(error_message, 0);
|
2023-06-27 07:33:21 +09:00
|
|
|
fprintf(stderr, "%s\n", jv_string_value(error_message));
|
2017-02-22 23:01:56 -06:00
|
|
|
} // else no message on stderr; use --debug-trace to see a message
|
|
|
|
|
fflush(stderr);
|
|
|
|
|
jv_free(error_message);
|
|
|
|
|
} else if (jv_invalid_has_msg(jv_copy(result))) {
|
2014-07-05 20:54:42 -05:00
|
|
|
// Uncaught jq exception
|
|
|
|
|
jv msg = jv_invalid_get_msg(jv_copy(result));
|
2015-04-17 15:28:00 -04:00
|
|
|
jv input_pos = jq_util_input_get_position(jq);
|
2014-07-07 22:26:53 -05:00
|
|
|
if (jv_get_kind(msg) == JV_KIND_STRING) {
|
2015-04-17 15:28:00 -04:00
|
|
|
fprintf(stderr, "jq: error (at %s): %s\n",
|
|
|
|
|
jv_string_value(input_pos), jv_string_value(msg));
|
2014-07-07 22:26:53 -05:00
|
|
|
} else {
|
|
|
|
|
msg = jv_dump_string(msg, 0);
|
2015-04-17 15:28:00 -04:00
|
|
|
fprintf(stderr, "jq: error (at %s) (not a string): %s\n",
|
|
|
|
|
jv_string_value(input_pos), jv_string_value(msg));
|
2014-07-07 22:26:53 -05:00
|
|
|
}
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_ERROR_UNKNOWN;
|
2015-04-17 15:28:00 -04:00
|
|
|
jv_free(input_pos);
|
2014-07-05 20:54:42 -05:00
|
|
|
jv_free(msg);
|
|
|
|
|
}
|
2012-09-20 19:31:14 +01:00
|
|
|
jv_free(result);
|
2013-11-29 16:36:15 -06:00
|
|
|
return ret;
|
2012-09-20 19:31:14 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-13 15:28:30 -06:00
|
|
|
static void debug_cb(void *data, jv input) {
|
2014-12-27 17:15:56 -06:00
|
|
|
int dumpopts = *(int *)data;
|
|
|
|
|
jv_dumpf(JV_ARRAY(jv_string("DEBUG:"), input), stderr, dumpopts & ~(JV_PRINT_PRETTY));
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-23 11:47:20 +09:00
|
|
|
static void stderr_cb(void *data, jv input) {
|
|
|
|
|
if (jv_get_kind(input) == JV_KIND_STRING) {
|
|
|
|
|
int dumpopts = *(int *)data;
|
|
|
|
|
priv_fwrite(jv_string_value(input), jv_string_length_bytes(jv_copy(input)),
|
|
|
|
|
stderr, dumpopts & JV_PRINT_ISATTY);
|
|
|
|
|
} else {
|
|
|
|
|
input = jv_dump_string(input, 0);
|
|
|
|
|
fprintf(stderr, "%s", jv_string_value(input));
|
|
|
|
|
}
|
|
|
|
|
jv_free(input);
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-12 21:33:46 +10:00
|
|
|
#ifdef WIN32
|
|
|
|
|
int umain(int argc, char* argv[]);
|
|
|
|
|
|
|
|
|
|
int wmain(int argc, wchar_t* wargv[]) {
|
|
|
|
|
size_t arg_sz;
|
|
|
|
|
char **argv = alloca(argc * sizeof(wchar_t*));
|
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
|
|
|
argv[i] = alloca((arg_sz = WideCharToMultiByte(CP_UTF8,
|
|
|
|
|
0,
|
|
|
|
|
wargv[i],
|
|
|
|
|
-1, 0, 0, 0, 0)));
|
|
|
|
|
WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], arg_sz, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
return umain(argc, argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int umain(int argc, char* argv[]) {
|
|
|
|
|
#else /*}*/
|
2012-08-16 01:00:30 +01:00
|
|
|
int main(int argc, char* argv[]) {
|
2019-02-12 21:33:46 +10:00
|
|
|
#endif
|
2013-12-08 19:22:18 +00:00
|
|
|
jq_state *jq = NULL;
|
2018-07-29 12:50:28 -07:00
|
|
|
int ret = JQ_OK_NO_OUTPUT;
|
2013-06-06 17:26:15 -05:00
|
|
|
int compiled = 0;
|
2014-12-22 23:06:27 -06:00
|
|
|
int parser_flags = 0;
|
2015-03-05 21:52:02 -06:00
|
|
|
int nfiles = 0;
|
2018-07-29 12:50:28 -07:00
|
|
|
int last_result = -1; /* -1 = no result, 0=null or false, 1=true */
|
2015-05-29 11:50:08 -05:00
|
|
|
int badwrite;
|
2023-07-19 09:00:11 -07:00
|
|
|
int options = 0;
|
2017-02-19 18:11:18 -06:00
|
|
|
jv ARGS = jv_array(); /* positional arguments */
|
|
|
|
|
jv program_arguments = jv_object(); /* named arguments */
|
2013-06-06 17:26:15 -05:00
|
|
|
|
2015-06-19 17:10:45 -05:00
|
|
|
#ifdef WIN32
|
2021-09-06 18:26:14 -05:00
|
|
|
jv_tsd_dtoa_ctx_init();
|
2015-06-22 18:15:51 -05:00
|
|
|
fflush(stdout);
|
|
|
|
|
fflush(stderr);
|
|
|
|
|
_setmode(fileno(stdout), _O_TEXT | _O_U8TEXT);
|
|
|
|
|
_setmode(fileno(stderr), _O_TEXT | _O_U8TEXT);
|
2015-06-19 17:10:45 -05:00
|
|
|
#endif
|
|
|
|
|
|
2012-09-18 23:37:46 +01:00
|
|
|
if (argc) progname = argv[0];
|
2012-09-20 19:31:14 +01:00
|
|
|
|
2013-06-06 17:26:15 -05:00
|
|
|
jq = jq_init();
|
|
|
|
|
if (jq == NULL) {
|
|
|
|
|
perror("malloc");
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_ERROR_SYSTEM;
|
2013-12-08 19:22:18 +00:00
|
|
|
goto out;
|
2013-06-06 17:26:15 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-03 20:20:11 -05:00
|
|
|
int dumpopts = JV_PRINT_INDENT_FLAGS(2);
|
2012-09-20 19:31:14 +01:00
|
|
|
const char* program = 0;
|
2014-12-27 17:58:47 -06:00
|
|
|
|
2015-07-04 14:56:07 -07:00
|
|
|
jq_util_input_state *input_state = jq_util_input_init(NULL, NULL); // XXX add err_cb
|
2014-12-27 17:58:47 -06:00
|
|
|
|
2017-02-19 18:11:18 -06:00
|
|
|
int further_args_are_strings = 0;
|
|
|
|
|
int further_args_are_json = 0;
|
|
|
|
|
int args_done = 0;
|
2013-05-05 23:12:10 +01:00
|
|
|
int jq_flags = 0;
|
2014-06-20 23:26:54 -05:00
|
|
|
size_t short_opts = 0;
|
2014-11-24 17:58:34 -06:00
|
|
|
jv lib_search_paths = jv_null();
|
2014-06-20 23:26:54 -05:00
|
|
|
for (int i=1; i<argc; i++, short_opts = 0) {
|
2017-02-19 18:11:18 -06:00
|
|
|
if (args_done) {
|
|
|
|
|
if (further_args_are_strings) {
|
|
|
|
|
ARGS = jv_array_append(ARGS, jv_string(argv[i]));
|
|
|
|
|
} else if (further_args_are_json) {
|
2023-07-05 18:26:06 +02:00
|
|
|
jv v = jv_parse(argv[i]);
|
|
|
|
|
if (!jv_is_valid(v)) {
|
|
|
|
|
fprintf(stderr, "%s: invalid JSON text passed to --jsonargs\n", progname);
|
|
|
|
|
die();
|
|
|
|
|
}
|
|
|
|
|
ARGS = jv_array_append(ARGS, v);
|
2017-02-19 18:11:18 -06:00
|
|
|
} else {
|
2015-06-18 21:24:41 -05:00
|
|
|
jq_util_input_add_input(input_state, argv[i]);
|
2015-03-05 21:52:02 -06:00
|
|
|
nfiles++;
|
2017-02-19 18:11:18 -06:00
|
|
|
}
|
|
|
|
|
} else if (!strcmp(argv[i], "--")) {
|
|
|
|
|
if (!program) usage(2, 1);
|
|
|
|
|
args_done = 1;
|
|
|
|
|
} else if (!isoptish(argv[i])) {
|
|
|
|
|
if (program) {
|
|
|
|
|
if (further_args_are_strings) {
|
|
|
|
|
ARGS = jv_array_append(ARGS, jv_string(argv[i]));
|
|
|
|
|
} else if (further_args_are_json) {
|
2023-07-05 18:26:06 +02:00
|
|
|
jv v = jv_parse(argv[i]);
|
|
|
|
|
if (!jv_is_valid(v)) {
|
|
|
|
|
fprintf(stderr, "%s: invalid JSON text passed to --jsonargs\n", progname);
|
|
|
|
|
die();
|
|
|
|
|
}
|
|
|
|
|
ARGS = jv_array_append(ARGS, v);
|
2017-02-19 18:11:18 -06:00
|
|
|
} else {
|
|
|
|
|
jq_util_input_add_input(input_state, argv[i]);
|
|
|
|
|
nfiles++;
|
|
|
|
|
}
|
2012-12-16 19:46:41 +00:00
|
|
|
} else {
|
|
|
|
|
program = argv[i];
|
|
|
|
|
}
|
2014-06-20 23:26:54 -05:00
|
|
|
} else {
|
2014-07-09 00:55:20 -04:00
|
|
|
if (argv[i][1] == 'L') {
|
2014-11-24 17:58:34 -06:00
|
|
|
if (jv_get_kind(lib_search_paths) == JV_KIND_NULL)
|
|
|
|
|
lib_search_paths = jv_array();
|
2014-07-09 00:55:20 -04:00
|
|
|
if (argv[i][2] != 0) { // -Lname (faster check than strlen)
|
2015-08-11 00:33:21 -05:00
|
|
|
lib_search_paths = jv_array_append(lib_search_paths, jq_realpath(jv_string(argv[i]+2)));
|
2014-07-09 00:55:20 -04:00
|
|
|
} else if (i >= argc - 1) {
|
|
|
|
|
fprintf(stderr, "-L takes a parameter: (e.g. -L /search/path or -L/search/path)\n");
|
|
|
|
|
die();
|
|
|
|
|
} else {
|
2015-08-11 00:33:21 -05:00
|
|
|
lib_search_paths = jv_array_append(lib_search_paths, jq_realpath(jv_string(argv[i+1])));
|
2014-07-09 00:55:20 -04:00
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-20 23:26:54 -05:00
|
|
|
if (isoption(argv[i], 's', "slurp", &short_opts)) {
|
|
|
|
|
options |= SLURP;
|
|
|
|
|
if (!short_opts) continue;
|
2013-05-06 14:21:00 +01:00
|
|
|
}
|
2014-06-20 23:26:54 -05:00
|
|
|
if (isoption(argv[i], 'r', "raw-output", &short_opts)) {
|
|
|
|
|
options |= RAW_OUTPUT;
|
|
|
|
|
if (!short_opts) continue;
|
2013-05-06 17:25:19 -05:00
|
|
|
}
|
2023-07-10 07:30:50 +09:00
|
|
|
if (isoption(argv[i], 0, "raw-output0", &short_opts)) {
|
|
|
|
|
options |= RAW_OUTPUT | RAW_NO_LF | RAW_OUTPUT0;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'j', "join-output", &short_opts)) {
|
|
|
|
|
options |= RAW_OUTPUT | RAW_NO_LF;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
2014-06-20 23:26:54 -05:00
|
|
|
if (isoption(argv[i], 'c', "compact-output", &short_opts)) {
|
2015-06-03 20:20:11 -05:00
|
|
|
dumpopts &= ~(JV_PRINT_TAB | JV_PRINT_INDENT_FLAGS(7));
|
2014-06-20 23:26:54 -05:00
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'C', "color-output", &short_opts)) {
|
2015-08-16 19:19:01 -07:00
|
|
|
options |= COLOR_OUTPUT;
|
2014-06-20 23:26:54 -05:00
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'M', "monochrome-output", &short_opts)) {
|
2015-08-16 19:19:01 -07:00
|
|
|
options |= NO_COLOR_OUTPUT;
|
2014-06-20 23:26:54 -05:00
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'a', "ascii-output", &short_opts)) {
|
|
|
|
|
options |= ASCII_OUTPUT;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 0, "unbuffered", &short_opts)) {
|
|
|
|
|
options |= UNBUFFERED_OUTPUT;
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-06-20 23:26:54 -05:00
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'S', "sort-keys", &short_opts)) {
|
|
|
|
|
options |= SORTED_OUTPUT;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'R', "raw-input", &short_opts)) {
|
|
|
|
|
options |= RAW_INPUT;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'n', "null-input", &short_opts)) {
|
|
|
|
|
options |= PROVIDE_NULL;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'f', "from-file", &short_opts)) {
|
|
|
|
|
options |= FROM_FILE;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
2019-03-24 14:39:58 -05:00
|
|
|
if (isoption(argv[i], 'b', "binary", &short_opts)) {
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
fflush(stderr);
|
|
|
|
|
_setmode(fileno(stdin), _O_BINARY);
|
|
|
|
|
_setmode(fileno(stdout), _O_BINARY);
|
|
|
|
|
_setmode(fileno(stderr), _O_BINARY);
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2015-06-03 20:20:11 -05:00
|
|
|
if (isoption(argv[i], 0, "tab", &short_opts)) {
|
|
|
|
|
dumpopts &= ~JV_PRINT_INDENT_FLAGS(7);
|
|
|
|
|
dumpopts |= JV_PRINT_TAB | JV_PRINT_PRETTY;
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2015-06-03 20:20:11 -05:00
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 0, "indent", &short_opts)) {
|
|
|
|
|
if (i >= argc - 1) {
|
|
|
|
|
fprintf(stderr, "%s: --indent takes one parameter\n", progname);
|
|
|
|
|
die();
|
|
|
|
|
}
|
|
|
|
|
dumpopts &= ~(JV_PRINT_TAB | JV_PRINT_INDENT_FLAGS(7));
|
|
|
|
|
int indent = atoi(argv[i+1]);
|
|
|
|
|
if (indent < -1 || indent > 7) {
|
|
|
|
|
fprintf(stderr, "%s: --indent takes a number between -1 and 7\n", progname);
|
|
|
|
|
die();
|
|
|
|
|
}
|
|
|
|
|
dumpopts |= JV_PRINT_INDENT_FLAGS(indent);
|
|
|
|
|
i++;
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2015-06-03 20:20:11 -05:00
|
|
|
}
|
2014-10-10 22:19:38 -05:00
|
|
|
if (isoption(argv[i], 0, "seq", &short_opts)) {
|
|
|
|
|
options |= SEQ;
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-10-10 22:19:38 -05:00
|
|
|
}
|
2014-12-22 23:06:27 -06:00
|
|
|
if (isoption(argv[i], 0, "stream", &short_opts)) {
|
|
|
|
|
parser_flags |= JV_PARSE_STREAMING;
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-12-22 23:06:27 -06:00
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 0, "stream-errors", &short_opts)) {
|
2023-07-23 00:01:52 -05:00
|
|
|
parser_flags |= JV_PARSE_STREAMING | JV_PARSE_STREAM_ERRORS;
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-12-22 23:06:27 -06:00
|
|
|
}
|
2014-06-20 23:26:54 -05:00
|
|
|
if (isoption(argv[i], 'e', "exit-status", &short_opts)) {
|
|
|
|
|
options |= EXIT_STATUS;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
2014-12-28 00:32:06 -06:00
|
|
|
// FIXME: For --arg* we should check that the varname is acceptable
|
2017-02-19 18:11:18 -06:00
|
|
|
if (isoption(argv[i], 0, "args", &short_opts)) {
|
|
|
|
|
further_args_are_strings = 1;
|
|
|
|
|
further_args_are_json = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 0, "jsonargs", &short_opts)) {
|
|
|
|
|
further_args_are_strings = 0;
|
|
|
|
|
further_args_are_json = 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2014-06-20 23:26:54 -05:00
|
|
|
if (isoption(argv[i], 0, "arg", &short_opts)) {
|
|
|
|
|
if (i >= argc - 2) {
|
2015-06-03 20:20:11 -05:00
|
|
|
fprintf(stderr, "%s: --arg takes two parameters (e.g. --arg varname value)\n", progname);
|
2014-06-20 23:26:54 -05:00
|
|
|
die();
|
|
|
|
|
}
|
2017-02-19 18:11:18 -06:00
|
|
|
if (!jv_object_has(jv_copy(program_arguments), jv_string(argv[i+1])))
|
|
|
|
|
program_arguments = jv_object_set(program_arguments, jv_string(argv[i+1]), jv_string(argv[i+2]));
|
2014-06-20 23:26:54 -05:00
|
|
|
i += 2; // skip the next two arguments
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-06-20 23:26:54 -05:00
|
|
|
}
|
2014-12-12 16:40:07 -06:00
|
|
|
if (isoption(argv[i], 0, "argjson", &short_opts)) {
|
|
|
|
|
if (i >= argc - 2) {
|
2015-06-03 20:20:11 -05:00
|
|
|
fprintf(stderr, "%s: --argjson takes two parameters (e.g. --argjson varname text)\n", progname);
|
2014-12-12 16:40:07 -06:00
|
|
|
die();
|
|
|
|
|
}
|
2017-02-19 18:11:18 -06:00
|
|
|
if (!jv_object_has(jv_copy(program_arguments), jv_string(argv[i+1]))) {
|
|
|
|
|
jv v = jv_parse(argv[i+2]);
|
|
|
|
|
if (!jv_is_valid(v)) {
|
|
|
|
|
fprintf(stderr, "%s: invalid JSON text passed to --argjson\n", progname);
|
|
|
|
|
die();
|
|
|
|
|
}
|
|
|
|
|
program_arguments = jv_object_set(program_arguments, jv_string(argv[i+1]), v);
|
2014-12-12 16:40:07 -06:00
|
|
|
}
|
|
|
|
|
i += 2; // skip the next two arguments
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-12-12 16:40:07 -06:00
|
|
|
}
|
2023-07-25 21:23:40 +09:00
|
|
|
if (isoption(argv[i], 0, "rawfile", &short_opts) ||
|
2015-05-29 14:19:23 -05:00
|
|
|
isoption(argv[i], 0, "slurpfile", &short_opts)) {
|
2017-10-27 18:46:57 -04:00
|
|
|
int raw = isoption(argv[i], 0, "rawfile", &short_opts);
|
2015-05-29 14:19:23 -05:00
|
|
|
const char *which;
|
2023-07-25 21:23:40 +09:00
|
|
|
if (raw)
|
2017-10-27 18:46:57 -04:00
|
|
|
which = "rawfile";
|
2015-05-29 14:19:23 -05:00
|
|
|
else
|
|
|
|
|
which = "slurpfile";
|
2014-06-20 23:26:54 -05:00
|
|
|
if (i >= argc - 2) {
|
2015-06-03 20:20:11 -05:00
|
|
|
fprintf(stderr, "%s: --%s takes two parameters (e.g. --%s varname filename)\n", progname, which, which);
|
2014-06-20 23:26:54 -05:00
|
|
|
die();
|
|
|
|
|
}
|
2017-02-19 18:11:18 -06:00
|
|
|
if (!jv_object_has(jv_copy(program_arguments), jv_string(argv[i+1]))) {
|
2017-10-27 18:46:57 -04:00
|
|
|
jv data = jv_load_file(argv[i+2], raw);
|
2017-02-19 18:11:18 -06:00
|
|
|
if (!jv_is_valid(data)) {
|
|
|
|
|
data = jv_invalid_get_msg(data);
|
|
|
|
|
fprintf(stderr, "%s: Bad JSON in --%s %s %s: %s\n", progname, which,
|
|
|
|
|
argv[i+1], argv[i+2], jv_string_value(data));
|
|
|
|
|
jv_free(data);
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_ERROR_SYSTEM;
|
2017-02-19 18:11:18 -06:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
program_arguments = jv_object_set(program_arguments, jv_string(argv[i+1]), data);
|
2014-06-20 23:26:54 -05:00
|
|
|
}
|
|
|
|
|
i += 2; // skip the next two arguments
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-06-20 23:26:54 -05:00
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 0, "debug-dump-disasm", &short_opts)) {
|
|
|
|
|
options |= DUMP_DISASM;
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-06-20 23:26:54 -05:00
|
|
|
}
|
2017-02-20 00:49:28 -05:00
|
|
|
if (isoption(argv[i], 0, "debug-trace=all", &short_opts)) {
|
|
|
|
|
jq_flags |= JQ_DEBUG_TRACE_ALL;
|
|
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
2014-06-20 23:26:54 -05:00
|
|
|
if (isoption(argv[i], 0, "debug-trace", &short_opts)) {
|
|
|
|
|
jq_flags |= JQ_DEBUG_TRACE;
|
2017-02-19 18:11:18 -06:00
|
|
|
continue;
|
2014-06-20 23:26:54 -05:00
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'h', "help", &short_opts)) {
|
2017-02-19 18:11:18 -06:00
|
|
|
usage(0, 0);
|
2014-06-20 23:26:54 -05:00
|
|
|
if (!short_opts) continue;
|
|
|
|
|
}
|
|
|
|
|
if (isoption(argv[i], 'V', "version", &short_opts)) {
|
|
|
|
|
printf("jq-%s\n", JQ_VERSION);
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_OK;
|
2013-12-08 19:22:18 +00:00
|
|
|
goto out;
|
2013-05-06 17:25:19 -05:00
|
|
|
}
|
2014-12-31 19:21:45 -06:00
|
|
|
if (isoption(argv[i], 0, "run-tests", &short_opts)) {
|
2015-01-12 10:43:06 -06:00
|
|
|
i++;
|
|
|
|
|
// XXX Pass program_arguments, even a whole jq_state *, through;
|
|
|
|
|
// could be useful for testing
|
2015-06-27 23:31:44 -05:00
|
|
|
ret = jq_testsuite(lib_search_paths,
|
|
|
|
|
(options & DUMP_DISASM) || (jq_flags & JQ_DEBUG_TRACE),
|
|
|
|
|
argc - i, argv + i);
|
2014-12-31 19:21:45 -06:00
|
|
|
goto out;
|
|
|
|
|
}
|
2014-07-09 00:55:20 -04:00
|
|
|
|
2014-06-21 18:01:00 -05:00
|
|
|
// check for unknown options... if this argument was a short option
|
2014-06-20 23:26:54 -05:00
|
|
|
if (strlen(argv[i]) != short_opts + 1) {
|
|
|
|
|
fprintf(stderr, "%s: Unknown option %s\n", progname, argv[i]);
|
|
|
|
|
die();
|
|
|
|
|
}
|
2012-09-20 19:31:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
2014-06-16 21:28:30 -05:00
|
|
|
|
2015-12-01 22:16:03 -06:00
|
|
|
#ifdef USE_ISATTY
|
|
|
|
|
if (isatty(STDOUT_FILENO)) {
|
2015-03-05 21:52:02 -06:00
|
|
|
#ifndef WIN32
|
2019-02-12 23:18:47 +10:00
|
|
|
dumpopts |= JV_PRINT_ISATTY | JV_PRINT_COLOR;
|
2019-02-12 18:34:37 +10:00
|
|
|
#else
|
2019-02-12 23:18:47 +10:00
|
|
|
/* Verify we actually have the console, as the NUL device is also regarded as
|
|
|
|
|
tty. Windows can handle color if ANSICON (or ConEmu) is installed, or
|
|
|
|
|
Windows 10 supports the virtual terminal */
|
|
|
|
|
DWORD mode;
|
|
|
|
|
HANDLE con = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
|
if (GetConsoleMode(con, &mode)) {
|
|
|
|
|
dumpopts |= JV_PRINT_ISATTY;
|
|
|
|
|
if (getenv("ANSICON") != NULL ||
|
|
|
|
|
SetConsoleMode(con, mode | 4/*ENABLE_VIRTUAL_TERMINAL_PROCESSING*/))
|
|
|
|
|
dumpopts |= JV_PRINT_COLOR;
|
2019-02-12 18:34:37 +10:00
|
|
|
}
|
2014-12-27 17:15:56 -06:00
|
|
|
#endif
|
2023-07-19 09:21:16 +09:00
|
|
|
if (dumpopts & JV_PRINT_COLOR) {
|
|
|
|
|
char *no_color = getenv("NO_COLOR");
|
|
|
|
|
if (no_color != NULL && no_color[0] != '\0')
|
|
|
|
|
dumpopts &= ~JV_PRINT_COLOR;
|
|
|
|
|
}
|
2015-06-22 18:15:51 -05:00
|
|
|
}
|
2015-12-01 22:16:03 -06:00
|
|
|
#endif
|
2014-12-27 17:15:56 -06:00
|
|
|
if (options & SORTED_OUTPUT) dumpopts |= JV_PRINT_SORTED;
|
|
|
|
|
if (options & ASCII_OUTPUT) dumpopts |= JV_PRINT_ASCII;
|
2015-08-16 19:19:01 -07:00
|
|
|
if (options & COLOR_OUTPUT) dumpopts |= JV_PRINT_COLOR;
|
|
|
|
|
if (options & NO_COLOR_OUTPUT) dumpopts &= ~JV_PRINT_COLOR;
|
2014-12-27 17:15:56 -06:00
|
|
|
|
2017-04-29 13:00:52 -05:00
|
|
|
if (getenv("JQ_COLORS") != NULL && !jq_set_colors(getenv("JQ_COLORS")))
|
|
|
|
|
fprintf(stderr, "Failed to set $JQ_COLORS\n");
|
|
|
|
|
|
2014-12-30 13:13:30 -06:00
|
|
|
if (jv_get_kind(lib_search_paths) == JV_KIND_NULL) {
|
|
|
|
|
// Default search path list
|
|
|
|
|
lib_search_paths = JV_ARRAY(jv_string("~/.jq"),
|
|
|
|
|
jv_string("$ORIGIN/../lib/jq"),
|
2023-07-03 09:12:22 +09:00
|
|
|
jv_string("$ORIGIN/../lib"));
|
2014-07-09 00:55:20 -04:00
|
|
|
}
|
2014-11-24 17:58:34 -06:00
|
|
|
jq_set_attr(jq, jv_string("JQ_LIBRARY_PATH"), lib_search_paths);
|
2014-07-09 00:55:20 -04:00
|
|
|
|
|
|
|
|
char *origin = strdup(argv[0]);
|
|
|
|
|
if (origin == NULL) {
|
2019-03-24 23:32:42 -05:00
|
|
|
fprintf(stderr, "jq: error: out of memory\n");
|
2014-07-09 00:55:20 -04:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2014-11-24 17:58:34 -06:00
|
|
|
jq_set_attr(jq, jv_string("JQ_ORIGIN"), jv_string(dirname(origin)));
|
2014-07-09 00:55:20 -04:00
|
|
|
free(origin);
|
|
|
|
|
|
2014-08-10 16:52:03 -05:00
|
|
|
if (strchr(JQ_VERSION, '-') == NULL)
|
|
|
|
|
jq_set_attr(jq, jv_string("VERSION_DIR"), jv_string(JQ_VERSION));
|
|
|
|
|
else
|
2014-12-23 21:52:03 -06:00
|
|
|
jq_set_attr(jq, jv_string("VERSION_DIR"), jv_string_fmt("%.*s-master", (int)(strchr(JQ_VERSION, '-') - JQ_VERSION), JQ_VERSION));
|
2014-08-10 16:52:03 -05:00
|
|
|
|
2015-12-01 22:16:03 -06:00
|
|
|
#ifdef USE_ISATTY
|
|
|
|
|
if (!program && (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO)))
|
2014-06-16 21:28:30 -05:00
|
|
|
program = ".";
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-02-19 18:11:18 -06:00
|
|
|
if (!program) usage(2, 1);
|
2012-09-20 19:31:14 +01:00
|
|
|
|
2012-10-22 19:16:27 +01:00
|
|
|
if (options & FROM_FILE) {
|
2014-11-24 17:58:34 -06:00
|
|
|
char *program_origin = strdup(program);
|
|
|
|
|
if (program_origin == NULL) {
|
|
|
|
|
perror("malloc");
|
|
|
|
|
exit(2);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-15 00:08:59 -05:00
|
|
|
jv data = jv_load_file(program, 1);
|
2012-10-22 19:16:27 +01:00
|
|
|
if (!jv_is_valid(data)) {
|
|
|
|
|
data = jv_invalid_get_msg(data);
|
|
|
|
|
fprintf(stderr, "%s: %s\n", progname, jv_string_value(data));
|
|
|
|
|
jv_free(data);
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_ERROR_SYSTEM;
|
2013-12-08 19:22:18 +00:00
|
|
|
goto out;
|
2012-10-22 19:16:27 +01:00
|
|
|
}
|
2014-11-24 17:58:34 -06:00
|
|
|
jq_set_attr(jq, jv_string("PROGRAM_ORIGIN"), jq_realpath(jv_string(dirname(program_origin))));
|
2017-02-19 18:11:18 -06:00
|
|
|
ARGS = JV_OBJECT(jv_string("positional"), ARGS,
|
|
|
|
|
jv_string("named"), jv_copy(program_arguments));
|
|
|
|
|
program_arguments = jv_object_set(program_arguments, jv_string("ARGS"), jv_copy(ARGS));
|
2015-12-14 23:43:22 -06:00
|
|
|
compiled = jq_compile_args(jq, skip_shebang(jv_string_value(data)), jv_copy(program_arguments));
|
2014-11-24 17:58:34 -06:00
|
|
|
free(program_origin);
|
2012-10-22 19:16:27 +01:00
|
|
|
jv_free(data);
|
|
|
|
|
} else {
|
2014-11-24 17:58:34 -06:00
|
|
|
jq_set_attr(jq, jv_string("PROGRAM_ORIGIN"), jq_realpath(jv_string("."))); // XXX is this good?
|
2017-02-19 18:11:18 -06:00
|
|
|
ARGS = JV_OBJECT(jv_string("positional"), ARGS,
|
|
|
|
|
jv_string("named"), jv_copy(program_arguments));
|
|
|
|
|
program_arguments = jv_object_set(program_arguments, jv_string("ARGS"), jv_copy(ARGS));
|
2015-05-29 11:49:45 -05:00
|
|
|
compiled = jq_compile_args(jq, program, jv_copy(program_arguments));
|
2012-10-22 19:16:27 +01:00
|
|
|
}
|
2013-12-08 19:22:18 +00:00
|
|
|
if (!compiled){
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_ERROR_COMPILE;
|
2013-12-08 19:22:18 +00:00
|
|
|
goto out;
|
|
|
|
|
}
|
2012-09-11 14:52:10 +01:00
|
|
|
|
2013-05-05 22:59:46 +01:00
|
|
|
if (options & DUMP_DISASM) {
|
2013-06-06 17:26:15 -05:00
|
|
|
jq_dump_disassembly(jq, 0);
|
2013-05-05 22:59:46 +01:00
|
|
|
printf("\n");
|
|
|
|
|
}
|
2012-09-11 14:52:10 +01:00
|
|
|
|
2014-12-22 23:06:27 -06:00
|
|
|
if ((options & SEQ))
|
|
|
|
|
parser_flags |= JV_PARSE_SEQ;
|
|
|
|
|
|
2015-04-23 18:26:57 -05:00
|
|
|
if ((options & RAW_INPUT))
|
|
|
|
|
jq_util_input_set_parser(input_state, NULL, (options & SLURP) ? 1 : 0);
|
|
|
|
|
else
|
2015-02-01 18:35:42 -06:00
|
|
|
jq_util_input_set_parser(input_state, jv_parser_new(parser_flags), (options & SLURP) ? 1 : 0);
|
2014-12-22 23:06:27 -06:00
|
|
|
|
|
|
|
|
// Let jq program read from inputs
|
2015-02-01 18:35:42 -06:00
|
|
|
jq_set_input_cb(jq, jq_util_input_next_input_cb, input_state);
|
2014-12-22 23:06:27 -06:00
|
|
|
|
2015-02-01 18:35:42 -06:00
|
|
|
// Let jq program call `debug` builtin and have that go somewhere
|
2014-12-27 17:15:56 -06:00
|
|
|
jq_set_debug_cb(jq, debug_cb, &dumpopts);
|
|
|
|
|
|
2023-07-23 11:47:20 +09:00
|
|
|
// Let jq program call `stderr` builtin and have that go somewhere
|
|
|
|
|
jq_set_stderr_cb(jq, stderr_cb, &dumpopts);
|
|
|
|
|
|
2015-03-05 21:52:02 -06:00
|
|
|
if (nfiles == 0)
|
2015-06-18 21:24:41 -05:00
|
|
|
jq_util_input_add_input(input_state, "-");
|
2015-03-05 21:52:02 -06:00
|
|
|
|
2012-09-20 19:31:14 +01:00
|
|
|
if (options & PROVIDE_NULL) {
|
2023-07-19 09:00:11 -07:00
|
|
|
ret = process(jq, jv_null(), jq_flags, dumpopts, options);
|
2012-09-20 19:31:14 +01:00
|
|
|
} else {
|
2014-12-22 23:06:27 -06:00
|
|
|
jv value;
|
2015-04-28 17:27:12 -05:00
|
|
|
while (jq_util_input_errors(input_state) == 0 &&
|
2015-02-01 18:35:42 -06:00
|
|
|
(jv_is_valid((value = jq_util_input_next_input(input_state))) || jv_invalid_has_msg(jv_copy(value)))) {
|
2014-12-22 23:06:27 -06:00
|
|
|
if (jv_is_valid(value)) {
|
2023-07-19 09:00:11 -07:00
|
|
|
ret = process(jq, value, jq_flags, dumpopts, options);
|
2018-07-29 12:50:28 -07:00
|
|
|
if (ret <= 0 && ret != JQ_OK_NO_OUTPUT)
|
|
|
|
|
last_result = (ret != JQ_OK_NULL_KIND);
|
2023-07-07 18:06:58 +02:00
|
|
|
if (jq_halted(jq))
|
|
|
|
|
break;
|
2014-12-22 23:06:27 -06:00
|
|
|
continue;
|
2012-10-22 18:55:56 +01:00
|
|
|
}
|
2014-12-22 23:06:27 -06:00
|
|
|
|
|
|
|
|
// Parse error
|
|
|
|
|
jv msg = jv_invalid_get_msg(value);
|
|
|
|
|
if (!(options & SEQ)) {
|
2023-07-06 10:01:59 +09:00
|
|
|
ret = JQ_ERROR_UNKNOWN;
|
2019-03-24 23:32:42 -05:00
|
|
|
fprintf(stderr, "jq: parse error: %s\n", jv_string_value(msg));
|
2014-12-22 23:06:27 -06:00
|
|
|
jv_free(msg);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-07-06 10:01:59 +09:00
|
|
|
// --seq -> errors are not fatal
|
2019-03-24 23:32:42 -05:00
|
|
|
fprintf(stderr, "jq: ignoring parse error: %s\n", jv_string_value(msg));
|
2014-12-22 23:06:27 -06:00
|
|
|
jv_free(msg);
|
2012-10-22 18:55:56 +01:00
|
|
|
}
|
2012-09-11 14:52:10 +01:00
|
|
|
}
|
2014-12-22 23:06:27 -06:00
|
|
|
|
2015-04-28 17:27:12 -05:00
|
|
|
if (jq_util_input_errors(input_state) != 0)
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_ERROR_SYSTEM;
|
2014-12-22 23:06:27 -06:00
|
|
|
|
2015-03-24 15:05:06 -05:00
|
|
|
out:
|
2015-05-29 11:50:08 -05:00
|
|
|
badwrite = ferror(stdout);
|
|
|
|
|
if (fclose(stdout)!=0 || badwrite) {
|
2019-03-24 23:32:42 -05:00
|
|
|
fprintf(stderr,"jq: error: writing output failed: %s\n", strerror(errno));
|
2018-07-29 12:50:28 -07:00
|
|
|
ret = JQ_ERROR_SYSTEM;
|
2015-03-06 13:54:53 -05:00
|
|
|
}
|
|
|
|
|
|
2017-02-19 18:11:18 -06:00
|
|
|
jv_free(ARGS);
|
2015-05-29 11:49:45 -05:00
|
|
|
jv_free(program_arguments);
|
2015-02-01 18:35:42 -06:00
|
|
|
jq_util_input_free(&input_state);
|
2013-12-08 23:52:07 +00:00
|
|
|
jq_teardown(&jq);
|
2018-07-29 12:50:28 -07:00
|
|
|
|
|
|
|
|
if (options & (EXIT_STATUS|EXIT_STATUS_EXACT)) {
|
|
|
|
|
if (ret != JQ_OK_NO_OUTPUT)
|
|
|
|
|
jq_exit_with_status(ret);
|
|
|
|
|
else
|
|
|
|
|
switch (last_result) {
|
|
|
|
|
case -1: jq_exit_with_status(JQ_OK_NO_OUTPUT);
|
|
|
|
|
case 0: jq_exit_with_status(JQ_OK_NULL_KIND);
|
|
|
|
|
default: jq_exit_with_status(JQ_OK);
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
jq_exit(ret);
|
2012-08-16 01:00:30 +01:00
|
|
|
}
|