]> granicus.if.org Git - jq/commitdiff
Add the ability to specify input files on the commandline.
authorStephen Dolan <mu@netsoc.tcd.ie>
Sun, 16 Dec 2012 19:46:41 +0000 (19:46 +0000)
committerStephen Dolan <mu@netsoc.tcd.ie>
Sun, 16 Dec 2012 19:46:41 +0000 (19:46 +0000)
See #21.

docs/content/3.manual/manual.yml
main.c

index 6e8065c61c0bbfb6fcd29671dbfabe9c66153b77..5acb212cd54b6e35a60e9ce522e7a9252a1b856f 100644 (file)
@@ -33,12 +33,16 @@ manpage_intro: |
 
   ## SYNOPSIS
 
-  `jq` [<options>...] <filter>
+  `jq` [<options>...] <filter> [<files>...]
 
   `jq` can transform JSON in various ways, by selecting, iterating,
   reducing and otherwise mangling JSON documents. For instance,
   running the command `jq 'map(.price) | add'` will take an array of
   JSON objects as input and return the sum of their "price" fields.
+
+  By default, `jq` reads a stream of JSON objects (whitespace
+  separated) from `stdin`. One or more <files> may be specified, in
+  which case `jq` will read input from those instead.
   
   The <options> are described in the [INVOKING JQ] section, they
   mostly concern input and output formatting. The <filter> is written
diff --git a/main.c b/main.c
index 64cb1fd42df91786154ebef73b2fb66353614bb6..252ebd5a13981054a1b7d63b898b6c722fc89ca1 100644 (file)
--- a/main.c
+++ b/main.c
@@ -16,10 +16,11 @@ static const char* progname;
 
 static void usage() {
   fprintf(stderr, "\njq - commandline JSON processor [version %s]\n", JQ_VERSION);
-  fprintf(stderr, "Usage: %s [options] <jq filter>\n\n", progname);
+  fprintf(stderr, "Usage: %s [options] <jq filter> [file...]\n\n", progname);
   fprintf(stderr, "For a description of the command line options and\n");
   fprintf(stderr, "how to write jq filters (and why you might want to)\n");
-  fprintf(stderr, "see the jq documentation at http://stedolan.github.com/jq\n\n");
+  fprintf(stderr, "see the jq manpage, or the online documentation at\n");
+  fprintf(stderr, "http://stedolan.github.com/jq\n\n");
   exit(1);
 }
 
@@ -102,14 +103,53 @@ static jv slurp_file(const char* filename) {
   return data;
 }
 
+FILE* current_input;
+const char** input_filenames;
+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++;
+  }
+
+  if (!fgets(buf, sizeof(buf), current_input)) buf[0] = 0;
+  return 1;
+}
+
 int main(int argc, char* argv[]) {
   if (argc) progname = argv[0];
 
   const char* program = 0;
+  input_filenames = malloc(sizeof(const char*) * argc);
+  ninput_files = 0;
+  int further_args_are_files = 0;
   for (int i=1; i<argc; i++) {
-    if (!isoptish(argv[i])) {
-      if (program) usage();
-      program = argv[i];
+    if (further_args_are_files) {
+      input_filenames[ninput_files++] = argv[i];
+    } else if (!strcmp(argv[i], "--")) {
+      if (!program) usage();
+      further_args_are_files = 1;
+    } else if (!isoptish(argv[i])) {
+      if (program) {
+        input_filenames[ninput_files++] = argv[i];
+      } else {
+        program = argv[i];
+      }
     } else if (isoption(argv[i], 's', "slurp")) {
       options |= SLURP;
     } else if (isoption(argv[i], 'r', "raw-output")) {
@@ -139,6 +179,7 @@ int main(int argc, char* argv[]) {
     }
   }
   if (!program) usage();
+  if (ninput_files == 0) current_input = stdin;
 
   if ((options & PROVIDE_NULL) && (options & (RAW_INPUT | SLURP))) {
     fprintf(stderr, "%s: --null-input cannot be used with --raw-input or --slurp\n", progname);
@@ -178,9 +219,8 @@ int main(int argc, char* argv[]) {
     }
     struct jv_parser parser;
     jv_parser_init(&parser);
-    while (!feof(stdin)) {
-      char buf[4096];
-      if (!fgets(buf, sizeof(buf), stdin)) buf[0] = 0;
+    char buf[4096];
+    while (read_more(buf, sizeof(buf))) {
       if (options & RAW_INPUT) {
         int len = strlen(buf);
         if (len > 0) {
@@ -216,7 +256,7 @@ int main(int argc, char* argv[]) {
       process(slurped);
     }
   }
-
+  free(input_filenames);
   bytecode_free(bc);
   return 0;
 }