Example #1
0
// [[Rcpp::export]]
std::vector<std::string> jqr(std::string json, std::string program) {
  jq_state_ptr state = make_jq_state();

  int compiled = jq_compile(state.get(), program.c_str());
  // This doesn't get here because it's picked up in the callback, but
  // serves as an extra check.
  if (!compiled) {
    Rcpp::stop("compile error [should never be seen]");
  }

  int is_partial = 0;
  jv_parser_ptr parser = make_jv_parser();
  jv_parser_set_buf(parser.get(), json.c_str(), json.size(), is_partial);

  return jqr_parse(state, parser);
}
Example #2
0
File: jv_parse.c Project: dfkoh/jq
jv jv_parse_sized(const char* string, int length) {
  struct jv_parser parser;
  parser_init(&parser);
  jv_parser_set_buf(&parser, string, length, 0);
  jv value = jv_parser_next(&parser);
  if (jv_is_valid(value)) {
    jv next = jv_parser_next(&parser);
    if (jv_is_valid(next)) {
      // multiple JSON values, we only wanted one
      jv_free(value);
      jv_free(next);
      value = jv_invalid_with_msg(jv_string("Unexpected extra JSON values"));
    } else if (jv_invalid_has_msg(jv_copy(next))) {
      // parser error after the first JSON value
      jv_free(value);
      value = next;
    } else {
      // a single valid JSON value
      jv_free(next);
    }
  } else if (jv_invalid_has_msg(jv_copy(value))) {
    // parse error, we'll return it
  } else {
    // no value at all
    jv_free(value);
    value = jv_invalid_with_msg(jv_string("Expected JSON value"));
  }
  parser_free(&parser);

  if (!jv_is_valid(value) && jv_invalid_has_msg(jv_copy(value))) {
    jv msg = jv_invalid_get_msg(value);
    value = jv_invalid_with_msg(jv_string_fmt("%s (while parsing '%s')",
                                              jv_string_value(msg),
                                              string));
    jv_free(msg);
  }
  return value;
}
Example #3
0
File: main.c Project: 4honor/jq
int main(int argc, char* argv[]) {
  jq_state *jq = NULL;
  int ret = 0;
  int compiled = 0;
  char *t = NULL;

  if (argc) progname = argv[0];

  if (argc > 1 && !strcmp(argv[1], "--run-tests")) {
    return jq_testsuite(argc, argv);
  }

  jq = jq_init();
  if (jq == NULL) {
    perror("malloc");
    ret = 2;
    goto out;
  }

  const char* program = 0;
  input_filenames = jv_mem_alloc(sizeof(const char*) * argc);
  ninput_files = 0;
  int further_args_are_files = 0;
  int jq_flags = 0;
  size_t short_opts = 0;
  jv program_arguments = jv_array();
  jv lib_search_paths = jv_array();
  for (int i=1; i<argc; i++, short_opts = 0) {
    if (further_args_are_files) {
      input_filenames[ninput_files++] = argv[i];
    } else if (!strcmp(argv[i], "--")) {
      if (!program) usage(2);
      further_args_are_files = 1;
    } else if (!isoptish(argv[i])) {
      if (program) {
        input_filenames[ninput_files++] = argv[i];
      } else {
        program = argv[i];
      }
    } else {
      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;
      }

      if (isoption(argv[i], 's', "slurp", &short_opts)) {
        options |= SLURP;
        if (!short_opts) continue;
      }
      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;
      }
      if (isoption(argv[i], 'j', "join-output", &short_opts)) {
        options |= RAW_OUTPUT | RAW_NO_LF;
        if (!short_opts) continue;
      }
      if (isoption(argv[i], 'i', "in-place", &short_opts)) {
        options |= IN_PLACE;
        if (!short_opts) continue;
      }
      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;
        goto out;
      }

      // check for unknown options... if this argument was a short option
      if (strlen(argv[i]) != short_opts + 1) {
        fprintf(stderr, "%s: Unknown option %s\n", progname, argv[i]);
        die();
      }
    }
  }

  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
  }
  jq_set_lib_dirs(jq,lib_search_paths);

  char *origin = strdup(argv[0]);
  if (origin == NULL) {
    fprintf(stderr, "Error: out of memory\n");
    exit(1);
  }
  jq_set_lib_origin(jq,jv_string(dirname(origin)));
  free(origin);

#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

  if (!program) usage(2);
  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);
    }
  }
  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);
    die();
  }
  
  if (options & FROM_FILE) {
    jv data = jv_load_file(program, 1);
    if (!jv_is_valid(data)) {
      data = jv_invalid_get_msg(data);
      fprintf(stderr, "%s: %s\n", progname, jv_string_value(data));
      jv_free(data);
      ret = 2;
      goto out;
    }
    compiled = jq_compile_args(jq, jv_string_value(data), program_arguments);
    jv_free(data);
  } else {
    compiled = jq_compile_args(jq, program, program_arguments);
  }
  if (!compiled){
    ret = 3;
    goto out;
  }

  if (options & DUMP_DISASM) {
    jq_dump_disassembly(jq, 0);
    printf("\n");
  }

  if (options & PROVIDE_NULL) {
    ret = process(jq, jv_null(), jq_flags);
  } else {
    jv slurped;
    if (options & SLURP) {
      if (options & RAW_INPUT) {
        slurped = jv_string("");
      } else {
        slurped = jv_array();
      }
    }
    struct jv_parser* parser = jv_parser_new(0);
    char buf[4096];
    while (read_more(buf, sizeof(buf))) {
      if (options & RAW_INPUT) {
        int len = strlen(buf);
        if (len > 0) {
          if (options & SLURP) {
            slurped = jv_string_concat(slurped, jv_string(buf));
          } else {
            if (buf[len-1] == '\n') buf[len-1] = 0;
            ret = process(jq, jv_string(buf), jq_flags);
          }
        }
      } else {
        jv_parser_set_buf(parser, buf, strlen(buf), !feof(stdin));
        jv value;
        while (jv_is_valid((value = jv_parser_next(parser)))) {
          if (options & SLURP) {
            slurped = jv_array_append(slurped, value);
          } else {
            ret = process(jq, value, jq_flags);
          }
        }
        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);
          ret = 4;
          break;
        } else {
          jv_free(value);
        }
      }
    }
    jv_parser_free(parser);
    if (ret != 0)
      goto out;
    if (options & SLURP) {
      ret = process(jq, slurped, jq_flags);
    }
  }
  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);
  }
out:
  jv_mem_free(input_filenames);
  jq_teardown(&jq);
  if (ret >= 10 && (options & EXIT_STATUS))
    return ret - 10;
  if (ret >= 10)
    return 0;
  return ret;
}
Example #4
0
int main(int argc, char* argv[]) {
  if (argc) progname = argv[0];

  const char* program = 0;
  for (int i=1; i<argc; i++) {
    if (!isoptish(argv[i])) {
      if (program) usage();
      program = argv[i];
    } else if (isoption(argv[i], 's', "slurp")) {
      options |= SLURP;
    } else if (isoption(argv[i], 'r', "raw-output")) {
      options |= RAW_OUTPUT;
    } else if (isoption(argv[i], 'c', "compact-output")) {
      options |= COMPACT_OUTPUT;
    } else if (isoption(argv[i], 'a', "ascii-output")) {
      options |= ASCII_OUTPUT;
    } else if (isoption(argv[i], 'R', "raw-input")) {
      options |= RAW_INPUT;
    } else if (isoption(argv[i], 'n', "null-input")) {
      options |= PROVIDE_NULL;
    } else if (isoption(argv[i], 'h', "help")) {
      usage();
    } else {
      fprintf(stderr, "%s: Unknown option %s\n", progname, argv[i]);
      die();
    }
  }
  if (!program) usage();

  if ((options & PROVIDE_NULL) && (options & (RAW_INPUT | SLURP))) {
    fprintf(stderr, "%s: --null-input cannot be used with --raw-input or --slurp\n", program);
    die();
  }

  bc = jq_compile(program);
  if (!bc) return 1;

#if JQ_DEBUG
  dump_disassembly(0, bc);
  printf("\n");
#endif

  if (options & PROVIDE_NULL) {
    process(jv_null());
  } else {
    jv slurped;
    if (options & SLURP) slurped = jv_invalid();
    int first = 1;
    struct jv_parser parser;
    jv_parser_init(&parser);
    while (!feof(stdin)) {
      char buf[4096];
      if (!fgets(buf, sizeof(buf), stdin)) buf[0] = 0;
      if (options & RAW_INPUT) {
        int len = strlen(buf);
        if (len > 0) {
          if (options & SLURP) {
            if (first) slurped = jv_string(buf);
            else slurped = jv_string_concat(slurped, jv_string(buf));
          } else {
            if (buf[len-1] == '\n') buf[len-1] = 0;
            process(jv_string(buf));
          }
        }
      } else {
        jv_parser_set_buf(&parser, buf, strlen(buf), !feof(stdin));
        jv value;
        while (jv_is_valid((value = jv_parser_next(&parser)))) {
          if (options & SLURP) {
            if (first) slurped = jv_array();
            slurped = jv_array_append(slurped, value);
          } else {
            process(value);
          }
        }
        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);
          break;
        } else {
          jv_free(value);
        }
      }
      first = 0;
    }
    jv_parser_free(&parser);
    if (options & SLURP) {
      if (jv_is_valid(slurped)) {
        process(slurped);
      } else {
        jv_free(slurped);
      }
    }
  }

  bytecode_free(bc);
  return 0;
}
Example #5
0
int main(int argc, char* argv[]) {
  int ret = 0;
  if (argc) progname = argv[0];

  if (argc > 1 && !strcmp(argv[1], "--run-tests")) {
    return jq_testsuite(argc - 1, argv + 1);
  }

  const char* program = 0;
  input_filenames = jv_mem_alloc(sizeof(const char*) * argc);
  ninput_files = 0;
  int further_args_are_files = 0;
  int jq_flags = 0;
  jv program_arguments = jv_array();
  for (int i=1; i<argc; 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")) {
      options |= RAW_OUTPUT;
    } else if (isoption(argv[i], 'c', "compact-output")) {
      options |= COMPACT_OUTPUT;
    } else if (isoption(argv[i], 'C', "color-output")) {
      options |= COLOUR_OUTPUT;
    } else if (isoption(argv[i], 'M', "monochrome-output")) {
      options |= NO_COLOUR_OUTPUT;
    } else if (isoption(argv[i], 'a', "ascii-output")) {
      options |= ASCII_OUTPUT;
    } else if (isoption(argv[i], 'R', "raw-input")) {
      options |= RAW_INPUT;
    } else if (isoption(argv[i], 'n', "null-input")) {
      options |= PROVIDE_NULL;
    } else if (isoption(argv[i], 'f', "from-file")) {
      options |= FROM_FILE;
    } else if (isoption(argv[i], 0, "arg")) {
      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
    } else if (isoption(argv[i],  0,  "debug-dump-disasm")) {
      options |= DUMP_DISASM;
    } else if (isoption(argv[i],  0,  "debug-trace")) {
      jq_flags |= JQ_DEBUG_TRACE;
    } else if (isoption(argv[i], 'h', "help")) {
      usage();
    } else if (isoption(argv[i], 'V', "version")) {
      fprintf(stderr, "jq version %s\n", PACKAGE_VERSION);
      return 0;
    } else {
      fprintf(stderr, "%s: Unknown option %s\n", progname, argv[i]);
      die();
    }
  }
  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);
    die();
  }
  
  if (options & FROM_FILE) {
    jv data = slurp_file(program);
    if (!jv_is_valid(data)) {
      data = jv_invalid_get_msg(data);
      fprintf(stderr, "%s: %s\n", progname, jv_string_value(data));
      jv_free(data);
      return 1;
    }
    bc = jq_compile_args(jv_string_value(data), program_arguments);
    jv_free(data);
  } else {
    bc = jq_compile_args(program, program_arguments);
  }
  if (!bc) return 1;

  if (options & DUMP_DISASM) {
    dump_disassembly(0, bc);
    printf("\n");
  }

  if (options & PROVIDE_NULL) {
    process(jv_null(), jq_flags);
  } else {
    jv slurped;
    if (options & SLURP) {
      if (options & RAW_INPUT) {
        slurped = jv_string("");
      } else {
        slurped = jv_array();
      }
    }
    struct jv_parser parser;
    jv_parser_init(&parser);
    char buf[4096];
    while (read_more(buf, sizeof(buf))) {
      if (options & RAW_INPUT) {
        int len = strlen(buf);
        if (len > 0) {
          if (options & SLURP) {
            slurped = jv_string_concat(slurped, jv_string(buf));
          } else {
            if (buf[len-1] == '\n') buf[len-1] = 0;
            process(jv_string(buf), jq_flags);
          }
        }
      } else {
        jv_parser_set_buf(&parser, buf, strlen(buf), !feof(stdin));
        jv value;
        while (jv_is_valid((value = jv_parser_next(&parser)))) {
          if (options & SLURP) {
            slurped = jv_array_append(slurped, value);
          } else {
            process(value, jq_flags);
          }
        }
        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);
          ret = 1;
          break;
        } else {
          jv_free(value);
        }
      }
    }
    jv_parser_free(&parser);
    if (ret != 0)
      goto out;
    if (options & SLURP) {
      process(slurped, jq_flags);
    }
  }
out:
  jv_mem_free(input_filenames);
  bytecode_free(bc);
  return ret;
}
Example #6
0
File: main.c Project: phihag/jq
int main(int argc, char* argv[]) {
  jq_state *jq = NULL;
  int ret = 0;
  int compiled = 0;

  if (argc) progname = argv[0];

  if (argc > 1 && !strcmp(argv[1], "--run-tests")) {
    return jq_testsuite(argc, argv);
  }

  jq = jq_init();
  if (jq == NULL) {
    perror("malloc");
    ret = 1;
    goto out;
  }

  const char* program = 0;
  input_filenames = jv_mem_alloc(sizeof(const char*) * argc);
  ninput_files = 0;
  int further_args_are_files = 0;
  int jq_flags = 0;
  jv_parser_flags parser_flags = 0;
  jv program_arguments = jv_array();
  for (int i=1; i<argc; 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")) {
      options |= RAW_OUTPUT;
    } else if (isoption(argv[i], 'c', "compact-output")) {
      options |= COMPACT_OUTPUT;
    } else if (isoption(argv[i], 'C', "color-output")) {
      options |= COLOUR_OUTPUT;
    } else if (isoption(argv[i], 'M', "monochrome-output")) {
      options |= NO_COLOUR_OUTPUT;
    } else if (isoption(argv[i], 'a', "ascii-output")) {
      options |= ASCII_OUTPUT;
    } else if (isoption(argv[i], 0, "unbuffered")) {
      options |= UNBUFFERED_OUTPUT;
    } else if (isoption(argv[i], 'S', "sort-keys")) {
      options |= SORTED_OUTPUT;
    } else if (isoption(argv[i], 'R', "raw-input")) {
      options |= RAW_INPUT;
    } else if (isoption(argv[i], 'n', "null-input")) {
      options |= PROVIDE_NULL;
    } else if (isoption(argv[i], 'f', "from-file")) {
      options |= FROM_FILE;
    } else if (isoption(argv[i], 'e', "exit-status")) {
      options |= EXIT_STATUS;
    } else if (isoption(argv[i], 'I', "online-input")) {
      parser_flags = JV_PARSE_EXPLODE_TOPLEVEL_ARRAY;
    } else if (isoption(argv[i], 0, "arg")) {
      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
    } else if (isoption(argv[i], 0, "argfile")) {
      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 = 1;
        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
    } else if (isoption(argv[i],  0,  "debug-dump-disasm")) {
      options |= DUMP_DISASM;
    } else if (isoption(argv[i],  0,  "debug-trace")) {
      jq_flags |= JQ_DEBUG_TRACE;
    } else if (isoption(argv[i], 'h', "help")) {
      usage();
    } else if (isoption(argv[i], 'V', "version")) {
      printf("jq-%s\n", JQ_VERSION);
      ret = 0;
      goto out;
    } else {
      fprintf(stderr, "%s: Unknown option %s\n", progname, argv[i]);
      die();
    }
  }
  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);
    die();
  }
  
  if (options & FROM_FILE) {
    jv data = jv_load_file(program, 1);
    if (!jv_is_valid(data)) {
      data = jv_invalid_get_msg(data);
      fprintf(stderr, "%s: %s\n", progname, jv_string_value(data));
      jv_free(data);
      ret = 1;
      goto out;
    }
    compiled = jq_compile_args(jq, jv_string_value(data), program_arguments);
    jv_free(data);
  } else {
    compiled = jq_compile_args(jq, program, program_arguments);
  }
  if (!compiled){
    ret = 1;
    goto out;
  }

  if (options & DUMP_DISASM) {
    jq_dump_disassembly(jq, 0);
    printf("\n");
  }

  if (options & PROVIDE_NULL) {
    ret = process(jq, jv_null(), jq_flags);
  } else {
    jv slurped;
    if (options & SLURP) {
      if (options & RAW_INPUT) {
        slurped = jv_string("");
      } else {
        slurped = jv_array();
      }
    }
    struct jv_parser* parser = jv_parser_new(parser_flags);
    char buf[4096];
    while (read_more(buf, sizeof(buf))) {
      if (options & RAW_INPUT) {
        int len = strlen(buf);
        if (len > 0) {
          if (options & SLURP) {
            slurped = jv_string_concat(slurped, jv_string(buf));
          } else {
            if (buf[len-1] == '\n') buf[len-1] = 0;
            ret = process(jq, jv_string(buf), jq_flags);
          }
        }
      } else {
        jv_parser_set_buf(parser, buf, strlen(buf), !feof(stdin));
        jv value;
        while (jv_is_valid((value = jv_parser_next(parser)))) {
          if (options & SLURP) {
            slurped = jv_array_append(slurped, value);
          } else {
            ret = process(jq, value, jq_flags);
          }
        }
        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);
          ret = 1;
          break;
        } else {
          jv_free(value);
        }
      }
    }
    jv_parser_free(parser);
    if (ret != 0)
      goto out;
    if (options & SLURP) {
      ret = process(jq, slurped, jq_flags);
    }
  }
out:
  jv_mem_free(input_filenames);
  jq_teardown(&jq);
  if (ret >= 10 && ret <= 11 && !(options & EXIT_STATUS))
    return 0;
  return ret;
}