| 
									
										
										
										
											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>
 | 
					
						
							| 
									
										
										
										
											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"
 | 
					
						
							| 
									
										
										
										
											2013-05-24 23:34:34 +01:00
										 |  |  | #include "version.h"
 | 
					
						
							| 
									
										
										
										
											2012-08-16 01:00:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-05 22:53:45 +01:00
										 |  |  | int jq_testsuite(int argc, char* argv[]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void usage(int code) { | 
					
						
							| 
									
										
										
										
											2013-05-24 23:34:34 +01:00
										 |  |  |   fprintf(stderr, "\njq - commandline JSON processor [version %s]\n", JQ_VERSION); | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  |   fprintf(stderr, "Usage: %s [options] <jq filter> [file...]\n\n", progname); | 
					
						
							| 
									
										
										
										
											2014-06-17 16:47:12 -05:00
										 |  |  |   fprintf(stderr, "\tjq is a tool for processing JSON inputs, applying the\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\tgiven filter to its JSON text inputs and producing the\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\tfilter's results as JSON on standard output.\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\tThe simplest filter is ., which is the identity filter,\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\tcopying jq's input to its output.\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\tFor more advanced filters see the jq(1) manpage (\"man jq\")\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\tand/or http://stedolan.github.com/jq\n\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\tSome of the options include:\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\t -h\t\tthis message;\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\t -c\t\tcompact instead of pretty-printed output;\n"); | 
					
						
							| 
									
										
										
										
											2014-07-20 00:04:24 -05:00
										 |  |  |   fprintf(stderr, "\t -n\t\tuse `null` as the single input value;\n"); | 
					
						
							| 
									
										
										
										
											2014-07-20 00:11:23 -05:00
										 |  |  |   fprintf(stderr, "\t -i\t\tedit the [first] file in-place;\n"); | 
					
						
							| 
									
										
										
										
											2014-07-20 00:04:24 -05:00
										 |  |  |   fprintf(stderr, "\t -s\t\tread (slurp) all inputs into an array; apply filter to it;\n"); | 
					
						
							| 
									
										
										
										
											2014-06-17 16:47:12 -05:00
										 |  |  |   fprintf(stderr, "\t -r\t\toutput raw strings, not JSON texts;\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\t -R\t\tread raw strings, not JSON texts;\n"); | 
					
						
							| 
									
										
										
										
											2014-07-20 00:04:24 -05:00
										 |  |  |   fprintf(stderr, "\t --arg a v\tset variable $a to value <v>;\n"); | 
					
						
							|  |  |  |   fprintf(stderr, "\t --argfile a f\tset variable $a to JSON texts read from <f>;\n"); | 
					
						
							| 
									
										
										
										
											2014-06-17 16:47:12 -05:00
										 |  |  |   fprintf(stderr, "\tSee the manpage for more options.\n"); | 
					
						
							|  |  |  |   exit(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); | 
					
						
							| 
									
										
										
										
											2014-06-17 16:47:12 -05:00
										 |  |  |   fprintf(stderr, "or see the jq manpage, or online docs  at http://stedolan.github.com/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) { | 
					
						
							|  |  |  |   return text[0] == '-' && (text[1] == '-' || isalpha(text[1])); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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, | 
					
						
							|  |  |  |   COMPACT_OUTPUT        = 16, | 
					
						
							|  |  |  |   ASCII_OUTPUT          = 32, | 
					
						
							|  |  |  |   COLOUR_OUTPUT         = 64, | 
					
						
							|  |  |  |   NO_COLOUR_OUTPUT      = 128, | 
					
						
							|  |  |  |   SORTED_OUTPUT         = 256, | 
					
						
							|  |  |  |   FROM_FILE             = 512, | 
					
						
							|  |  |  |   RAW_NO_LF             = 1024, | 
					
						
							|  |  |  |   UNBUFFERED_OUTPUT     = 2048, | 
					
						
							|  |  |  |   EXIT_STATUS           = 4096, | 
					
						
							| 
									
										
										
										
											2014-07-20 00:11:23 -05:00
										 |  |  |   IN_PLACE              = 8192, | 
					
						
							| 
									
										
										
										
											2013-05-05 22:59:46 +01:00
										 |  |  |   /* debugging only */ | 
					
						
							| 
									
										
										
										
											2014-07-20 00:11:23 -05:00
										 |  |  |   DUMP_DISASM           = 16384, | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | static int options = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-29 16:36:15 -06:00
										 |  |  | static int process(jq_state *jq, jv value, int flags) { | 
					
						
							| 
									
										
										
										
											2013-12-26 12:54:03 -06:00
										 |  |  |   int ret = 14; // 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) { | 
					
						
							| 
									
										
										
										
											2013-05-15 00:37:38 +01:00
										 |  |  |       fwrite(jv_string_value(result), 1, jv_string_length_bytes(jv_copy(result)), stdout); | 
					
						
							| 
									
										
										
										
											2013-12-26 12:54:03 -06:00
										 |  |  |       ret = 0; | 
					
						
							| 
									
										
										
										
											2012-12-23 15:41:20 +00:00
										 |  |  |       jv_free(result); | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2012-12-20 12:16:22 +00:00
										 |  |  |       int dumpopts; | 
					
						
							| 
									
										
										
										
											2013-05-08 19:36:52 +01:00
										 |  |  |       /* Disable colour by default on Windows builds as Windows
 | 
					
						
							|  |  |  |          terminals tend not to display it correctly */ | 
					
						
							|  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |       dumpopts = 0; | 
					
						
							| 
									
										
										
										
											2012-12-20 12:16:22 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |       dumpopts = isatty(fileno(stdout)) ? JV_PRINT_COLOUR : 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-05-29 11:43:55 +01:00
										 |  |  |       if (options & SORTED_OUTPUT) dumpopts |= JV_PRINT_SORTED; | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |       if (!(options & COMPACT_OUTPUT)) dumpopts |= JV_PRINT_PRETTY; | 
					
						
							|  |  |  |       if (options & ASCII_OUTPUT) dumpopts |= JV_PRINT_ASCII; | 
					
						
							| 
									
										
										
										
											2012-12-03 01:21:07 +00:00
										 |  |  |       if (options & COLOUR_OUTPUT) dumpopts |= JV_PRINT_COLOUR; | 
					
						
							|  |  |  |       if (options & NO_COLOUR_OUTPUT) dumpopts &= ~JV_PRINT_COLOUR; | 
					
						
							| 
									
										
										
										
											2013-12-26 12:54:03 -06:00
										 |  |  |       if (jv_get_kind(result) == JV_KIND_FALSE || jv_get_kind(result) == JV_KIND_NULL) | 
					
						
							| 
									
										
										
										
											2013-11-29 16:36:15 -06:00
										 |  |  |         ret = 11; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         ret = 0; | 
					
						
							| 
									
										
										
										
											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)) | 
					
						
							|  |  |  |         printf("\n"); | 
					
						
							| 
									
										
										
										
											2014-02-26 01:38:46 -06:00
										 |  |  |     if (options & UNBUFFERED_OUTPUT) | 
					
						
							|  |  |  |       fflush(stdout); | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-07-05 20:54:42 -05:00
										 |  |  |   if (jv_invalid_has_msg(jv_copy(result))) { | 
					
						
							|  |  |  |     // Uncaught jq exception
 | 
					
						
							|  |  |  |     jv msg = jv_invalid_get_msg(jv_copy(result)); | 
					
						
							| 
									
										
										
										
											2014-07-07 22:26:53 -05:00
										 |  |  |     if (jv_get_kind(msg) == JV_KIND_STRING) { | 
					
						
							|  |  |  |       fprintf(stderr, "jq: error: %s\n", jv_string_value(msg)); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       msg = jv_dump_string(msg, 0); | 
					
						
							|  |  |  |       fprintf(stderr, "jq: error (not a string): %s\n", jv_string_value(msg)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  | FILE* current_input; | 
					
						
							| 
									
										
										
										
											2013-12-08 19:22:18 +00:00
										 |  |  | const char** input_filenames = NULL; | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  | int ninput_files; | 
					
						
							|  |  |  | int next_input_idx; | 
					
						
							|  |  |  | static int read_more(char* buf, size_t size) { | 
					
						
							|  |  |  |   while (!current_input || feof(current_input)) { | 
					
						
							|  |  |  |     if (current_input) { | 
					
						
							|  |  |  |       fclose(current_input); | 
					
						
							|  |  |  |       current_input = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (next_input_idx == ninput_files) { | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!strcmp(input_filenames[next_input_idx], "-")) { | 
					
						
							|  |  |  |       current_input = stdin; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       current_input = fopen(input_filenames[next_input_idx], "r"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!current_input) { | 
					
						
							|  |  |  |       fprintf(stderr, "%s: %s: %s\n", progname, input_filenames[next_input_idx], strerror(errno)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     next_input_idx++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-27 01:57:09 +00:00
										 |  |  |   if (!fgets(buf, size, current_input)) buf[0] = 0; | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  |   return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-16 01:00:30 +01:00
										 |  |  | int main(int argc, char* argv[]) { | 
					
						
							| 
									
										
										
										
											2013-12-08 19:22:18 +00:00
										 |  |  |   jq_state *jq = NULL; | 
					
						
							| 
									
										
										
										
											2013-05-04 17:03:01 -05:00
										 |  |  |   int ret = 0; | 
					
						
							| 
									
										
										
										
											2013-06-06 17:26:15 -05:00
										 |  |  |   int compiled = 0; | 
					
						
							| 
									
										
										
										
											2014-07-20 00:11:23 -05:00
										 |  |  |   char *t = NULL; | 
					
						
							| 
									
										
										
										
											2013-06-06 17:26:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-18 23:37:46 +01:00
										 |  |  |   if (argc) progname = argv[0]; | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-05 22:53:45 +01:00
										 |  |  |   if (argc > 1 && !strcmp(argv[1], "--run-tests")) { | 
					
						
							| 
									
										
										
										
											2013-06-15 01:55:47 -05:00
										 |  |  |     return jq_testsuite(argc, argv); | 
					
						
							| 
									
										
										
										
											2013-05-05 22:53:45 +01:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-06 17:26:15 -05:00
										 |  |  |   jq = jq_init(); | 
					
						
							|  |  |  |   if (jq == NULL) { | 
					
						
							|  |  |  |     perror("malloc"); | 
					
						
							| 
									
										
										
										
											2013-12-26 12:54:03 -06:00
										 |  |  |     ret = 2; | 
					
						
							| 
									
										
										
										
											2013-12-08 19:22:18 +00:00
										 |  |  |     goto out; | 
					
						
							| 
									
										
										
										
											2013-06-06 17:26:15 -05:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |   const char* program = 0; | 
					
						
							| 
									
										
										
										
											2012-12-18 16:52:47 +00:00
										 |  |  |   input_filenames = jv_mem_alloc(sizeof(const char*) * argc); | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  |   ninput_files = 0; | 
					
						
							|  |  |  |   int further_args_are_files = 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; | 
					
						
							| 
									
										
										
										
											2013-05-06 14:21:00 +01:00
										 |  |  |   jv program_arguments = jv_array(); | 
					
						
							| 
									
										
										
										
											2014-07-09 00:55:20 -04:00
										 |  |  |   jv lib_search_paths = jv_array(); | 
					
						
							| 
									
										
										
										
											2014-06-20 23:26:54 -05:00
										 |  |  |   for (int i=1; i<argc; i++, short_opts = 0) { | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  |     if (further_args_are_files) { | 
					
						
							|  |  |  |       input_filenames[ninput_files++] = argv[i]; | 
					
						
							|  |  |  |     } else if (!strcmp(argv[i], "--")) { | 
					
						
							| 
									
										
										
										
											2014-06-17 16:47:12 -05:00
										 |  |  |       if (!program) usage(2); | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  |       further_args_are_files = 1; | 
					
						
							|  |  |  |     } else if (!isoptish(argv[i])) { | 
					
						
							|  |  |  |       if (program) { | 
					
						
							|  |  |  |         input_filenames[ninput_files++] = argv[i]; | 
					
						
							|  |  |  |       } 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') { | 
					
						
							|  |  |  |         if (argv[i][2] != 0) { // -Lname (faster check than strlen)
 | 
					
						
							|  |  |  |             lib_search_paths = jv_array_append(lib_search_paths, jv_string(argv[i]+2)); | 
					
						
							|  |  |  |         } else if (i >= argc - 1) { | 
					
						
							|  |  |  |           fprintf(stderr, "-L takes a parameter: (e.g. -L /search/path or -L/search/path)\n"); | 
					
						
							|  |  |  |           die(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           lib_search_paths = jv_array_append(lib_search_paths, jv_string(argv[i+1])); | 
					
						
							|  |  |  |           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; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i], 'c', "compact-output", &short_opts)) { | 
					
						
							|  |  |  |         options |= COMPACT_OUTPUT; | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i], 'C', "color-output", &short_opts)) { | 
					
						
							|  |  |  |         options |= COLOUR_OUTPUT; | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i], 'M', "monochrome-output", &short_opts)) { | 
					
						
							|  |  |  |         options |= NO_COLOUR_OUTPUT; | 
					
						
							|  |  |  |         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; | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       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; | 
					
						
							| 
									
										
										
										
											2013-05-06 17:25:19 -05:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-06-20 23:26:54 -05:00
										 |  |  |       if (isoption(argv[i], 'j', "join-output", &short_opts)) { | 
					
						
							|  |  |  |         options |= RAW_OUTPUT | RAW_NO_LF; | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-07-20 00:11:23 -05:00
										 |  |  |       if (isoption(argv[i], 'i', "in-place", &short_opts)) { | 
					
						
							|  |  |  |         options |= IN_PLACE; | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2014-06-20 23:26:54 -05:00
										 |  |  |       if (isoption(argv[i], 'e', "exit-status", &short_opts)) { | 
					
						
							|  |  |  |         options |= EXIT_STATUS; | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i], 0, "arg", &short_opts)) { | 
					
						
							|  |  |  |         if (i >= argc - 2) { | 
					
						
							|  |  |  |           fprintf(stderr, "%s: --arg takes two parameters (e.g. -a varname value)\n", progname); | 
					
						
							|  |  |  |           die(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         jv arg = jv_object(); | 
					
						
							|  |  |  |         arg = jv_object_set(arg, jv_string("name"), jv_string(argv[i+1])); | 
					
						
							|  |  |  |         arg = jv_object_set(arg, jv_string("value"), jv_string(argv[i+2])); | 
					
						
							|  |  |  |         program_arguments = jv_array_append(program_arguments, arg); | 
					
						
							|  |  |  |         i += 2; // skip the next two arguments
 | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i], 0, "argfile", &short_opts)) { | 
					
						
							|  |  |  |         if (i >= argc - 2) { | 
					
						
							|  |  |  |           fprintf(stderr, "%s: --argfile takes two parameters (e.g. -a varname filename)\n", progname); | 
					
						
							|  |  |  |           die(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         jv arg = jv_object(); | 
					
						
							|  |  |  |         arg = jv_object_set(arg, jv_string("name"), jv_string(argv[i+1])); | 
					
						
							|  |  |  |         jv data = jv_load_file(argv[i+2], 0); | 
					
						
							|  |  |  |         if (!jv_is_valid(data)) { | 
					
						
							|  |  |  |           data = jv_invalid_get_msg(data); | 
					
						
							|  |  |  |           fprintf(stderr, "%s: Bad JSON in --argfile %s %s: %s\n", progname, | 
					
						
							|  |  |  |                   argv[i+1], argv[i+2], jv_string_value(data)); | 
					
						
							|  |  |  |           jv_free(data); | 
					
						
							|  |  |  |           ret = 2; | 
					
						
							|  |  |  |           goto out; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (jv_get_kind(data) == JV_KIND_ARRAY && jv_array_length(jv_copy(data)) == 1) | 
					
						
							|  |  |  |             data = jv_array_get(data, 0); | 
					
						
							|  |  |  |         arg = jv_object_set(arg, jv_string("value"), data); | 
					
						
							|  |  |  |         program_arguments = jv_array_append(program_arguments, arg); | 
					
						
							|  |  |  |         i += 2; // skip the next two arguments
 | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i],  0,  "debug-dump-disasm", &short_opts)) { | 
					
						
							|  |  |  |         options |= DUMP_DISASM; | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i],  0,  "debug-trace", &short_opts)) { | 
					
						
							|  |  |  |         jq_flags |= JQ_DEBUG_TRACE; | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i], 'h', "help", &short_opts)) { | 
					
						
							|  |  |  |         usage(0); | 
					
						
							|  |  |  |         if (!short_opts) continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (isoption(argv[i], 'V', "version", &short_opts)) { | 
					
						
							|  |  |  |         printf("jq-%s\n", JQ_VERSION); | 
					
						
							|  |  |  |         ret = 0; | 
					
						
							| 
									
										
										
										
											2013-12-08 19:22:18 +00:00
										 |  |  |         goto out; | 
					
						
							| 
									
										
										
										
											2013-05-06 17:25:19 -05:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-09 00:55:20 -04:00
										 |  |  |   char *penv = getenv("JQ_LIBRARY_PATH"); | 
					
						
							|  |  |  |   if (penv) { | 
					
						
							|  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  | #define PATH_ENV_SEPARATOR ";"
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define PATH_ENV_SEPARATOR ":"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     lib_search_paths = jv_array_concat(lib_search_paths,jv_string_split(jv_string(penv),jv_string(PATH_ENV_SEPARATOR))); | 
					
						
							|  |  |  | #undef PATH_ENV_SEPARATOR
 | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-10 16:52:03 -05:00
										 |  |  |   jq_set_attr(jq, jv_string("LIB_DIRS"), lib_search_paths); | 
					
						
							| 
									
										
										
										
											2014-07-09 00:55:20 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   char *origin = strdup(argv[0]); | 
					
						
							|  |  |  |   if (origin == NULL) { | 
					
						
							|  |  |  |     fprintf(stderr, "Error: out of memory\n"); | 
					
						
							|  |  |  |     exit(1); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-08-10 16:52:03 -05:00
										 |  |  |   jq_set_attr(jq, jv_string("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 | 
					
						
							|  |  |  |     jq_set_attr(jq, jv_string("VERSION_DIR"), jv_string("next")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-16 21:28:30 -05:00
										 |  |  | #if (!defined(WIN32) && defined(HAVE_ISATTY)) || defined(HAVE__ISATTY)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(HAVE__ISATTY) && defined(isatty)
 | 
					
						
							|  |  |  | #undef isatty
 | 
					
						
							|  |  |  | #define isatty _isatty
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!program && isatty(STDOUT_FILENO) && !isatty(STDIN_FILENO)) | 
					
						
							|  |  |  |     program = "."; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-17 16:47:12 -05:00
										 |  |  |   if (!program) usage(2); | 
					
						
							| 
									
										
										
										
											2014-07-20 00:11:23 -05:00
										 |  |  |   if ((options & IN_PLACE)) { | 
					
						
							|  |  |  |     if (ninput_files == 0) usage(2); | 
					
						
							|  |  |  |     if (strcmp(input_filenames[0], "-") == 0) usage(2); | 
					
						
							|  |  |  |     size_t tlen = strlen(input_filenames[0]) + 7; | 
					
						
							|  |  |  |     t = jv_mem_alloc(tlen); | 
					
						
							|  |  |  |     int n = snprintf(t, tlen,"%sXXXXXX", input_filenames[0]); | 
					
						
							|  |  |  |     assert(n > 0 && (size_t)n < tlen); | 
					
						
							|  |  |  |     if (mkstemp(t) == -1) { | 
					
						
							|  |  |  |       fprintf(stderr, "Error: %s creating temporary file", strerror(errno)); | 
					
						
							|  |  |  |       exit(3); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (freopen(t, "w", stdout) == NULL) { | 
					
						
							|  |  |  |       fprintf(stderr, "Error: %s redirecting stdout to temporary file", strerror(errno)); | 
					
						
							|  |  |  |       exit(3); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  |   if (ninput_files == 0) current_input = stdin; | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if ((options & PROVIDE_NULL) && (options & (RAW_INPUT | SLURP))) { | 
					
						
							| 
									
										
										
										
											2012-10-22 19:16:27 +01:00
										 |  |  |     fprintf(stderr, "%s: --null-input cannot be used with --raw-input or --slurp\n", progname); | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |     die(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-10-22 19:16:27 +01:00
										 |  |  |    | 
					
						
							|  |  |  |   if (options & FROM_FILE) { | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2013-12-26 12:54:03 -06:00
										 |  |  |       ret = 2; | 
					
						
							| 
									
										
										
										
											2013-12-08 19:22:18 +00:00
										 |  |  |       goto out; | 
					
						
							| 
									
										
										
										
											2012-10-22 19:16:27 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-06-06 17:26:15 -05:00
										 |  |  |     compiled = jq_compile_args(jq, jv_string_value(data), program_arguments); | 
					
						
							| 
									
										
										
										
											2012-10-22 19:16:27 +01:00
										 |  |  |     jv_free(data); | 
					
						
							|  |  |  |   } else { | 
					
						
							| 
									
										
										
										
											2013-06-06 17:26:15 -05:00
										 |  |  |     compiled = jq_compile_args(jq, program, program_arguments); | 
					
						
							| 
									
										
										
										
											2012-10-22 19:16:27 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-12-08 19:22:18 +00:00
										 |  |  |   if (!compiled){ | 
					
						
							| 
									
										
										
										
											2013-12-26 12:54:03 -06:00
										 |  |  |     ret = 3; | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |   if (options & PROVIDE_NULL) { | 
					
						
							| 
									
										
										
										
											2013-11-29 16:36:15 -06:00
										 |  |  |     ret = process(jq, jv_null(), jq_flags); | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |   } else { | 
					
						
							|  |  |  |     jv slurped; | 
					
						
							| 
									
										
										
										
											2012-10-22 18:55:56 +01:00
										 |  |  |     if (options & SLURP) { | 
					
						
							|  |  |  |       if (options & RAW_INPUT) { | 
					
						
							|  |  |  |         slurped = jv_string(""); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         slurped = jv_array(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-06-04 18:17:27 -05:00
										 |  |  |     struct jv_parser* parser = jv_parser_new(0); | 
					
						
							| 
									
										
										
										
											2012-12-16 19:46:41 +00:00
										 |  |  |     char buf[4096]; | 
					
						
							|  |  |  |     while (read_more(buf, sizeof(buf))) { | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |       if (options & RAW_INPUT) { | 
					
						
							|  |  |  |         int len = strlen(buf); | 
					
						
							|  |  |  |         if (len > 0) { | 
					
						
							|  |  |  |           if (options & SLURP) { | 
					
						
							| 
									
										
										
										
											2012-10-22 18:55:56 +01:00
										 |  |  |             slurped = jv_string_concat(slurped, jv_string(buf)); | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |           } else { | 
					
						
							|  |  |  |             if (buf[len-1] == '\n') buf[len-1] = 0; | 
					
						
							| 
									
										
										
										
											2013-11-29 16:36:15 -06:00
										 |  |  |             ret = process(jq, jv_string(buf), jq_flags); | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2013-06-23 12:26:49 +01:00
										 |  |  |         jv_parser_set_buf(parser, buf, strlen(buf), !feof(stdin)); | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |         jv value; | 
					
						
							| 
									
										
										
										
											2013-06-23 12:26:49 +01:00
										 |  |  |         while (jv_is_valid((value = jv_parser_next(parser)))) { | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |           if (options & SLURP) { | 
					
						
							|  |  |  |             slurped = jv_array_append(slurped, value); | 
					
						
							|  |  |  |           } else { | 
					
						
							| 
									
										
										
										
											2013-11-29 16:36:15 -06:00
										 |  |  |             ret = process(jq, value, jq_flags); | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (jv_invalid_has_msg(jv_copy(value))) { | 
					
						
							|  |  |  |           jv msg = jv_invalid_get_msg(value); | 
					
						
							|  |  |  |           fprintf(stderr, "parse error: %s\n", jv_string_value(msg)); | 
					
						
							|  |  |  |           jv_free(msg); | 
					
						
							| 
									
										
										
										
											2013-12-26 12:54:03 -06:00
										 |  |  |           ret = 4; | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |           break; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           jv_free(value); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-09-11 14:52:10 +01:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-06-23 12:26:49 +01:00
										 |  |  |     jv_parser_free(parser); | 
					
						
							| 
									
										
										
										
											2013-05-04 17:03:01 -05:00
										 |  |  |     if (ret != 0) | 
					
						
							|  |  |  |       goto out; | 
					
						
							| 
									
										
										
										
											2012-09-20 19:31:14 +01:00
										 |  |  |     if (options & SLURP) { | 
					
						
							| 
									
										
										
										
											2013-11-29 16:36:15 -06:00
										 |  |  |       ret = process(jq, slurped, jq_flags); | 
					
						
							| 
									
										
										
										
											2012-09-11 14:52:10 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-07-20 00:11:23 -05:00
										 |  |  |   if ((options & IN_PLACE)) { | 
					
						
							|  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |     (void) freopen("NUL", "w+", stdout); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     (void) freopen("/dev/null", "w+", stdout); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     if (rename(t, input_filenames[0]) == -1) { | 
					
						
							|  |  |  |       fprintf(stderr, "Error: %s renaming temporary file", strerror(errno)); | 
					
						
							|  |  |  |       exit(3); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     jv_mem_free(t); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-05-04 17:03:01 -05:00
										 |  |  | out: | 
					
						
							| 
									
										
										
										
											2013-12-08 23:52:07 +00:00
										 |  |  |   jv_mem_free(input_filenames); | 
					
						
							|  |  |  |   jq_teardown(&jq); | 
					
						
							| 
									
										
										
										
											2013-12-26 12:54:03 -06:00
										 |  |  |   if (ret >= 10 && (options & EXIT_STATUS)) | 
					
						
							|  |  |  |     return ret - 10; | 
					
						
							|  |  |  |   if (ret >= 10) | 
					
						
							| 
									
										
										
										
											2013-11-29 16:36:15 -06:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2013-05-04 17:03:01 -05:00
										 |  |  |   return ret; | 
					
						
							| 
									
										
										
										
											2012-08-16 01:00:30 +01:00
										 |  |  | } |