*.o
*~
- # Test binaries
- jv_test
- jv_parse
- parsertest*~
-# Autogenerated
-*.gen.*
-
+ jq_test
+ build
+ jq
+ jq.1
# Something delightfully recursive happens otherwise
-docs/content/2.download/source/*
+docs/content/2.download/source/*
--- /dev/null
- Lee Thompson <thompson@dtosolutions.com> - autoconf stuff
+Created By:
+Stephen Dolan <mu@netsoc.tcd.ie>
+
+Contributions by
+Anthony Shortland <anthony@dtosolutions.com> - rpmbuild target
++Lee Thompson <stagr.lee@gmail.com> - autoconf stuff
--- /dev/null
- JQ_INCS = jq_parser.h builtin.h bytecode.h compile.h execute.h forkable_stack.h frame_layout.h jv.h jv_dtoa.h jv_parse.h jv_unicode.h locfile.h opcode.h opcode_list.h parser.y jv_utf8_tables.gen.h
+# Converted to automake by thompson@dtosolutions.com 26NOV12
+
+# setup is only used by distribution developers, not package developers.
+# Still, as a matter of allowing patching, its not a bad idea to distribute
+# the developer setup script in the tarball.
+EXTRA_DIST = setup.sh config.h.in ChangeLog VERSION lexer.l lexer.h gen_utf8_tables.py jq.spec testdata
+
+# README.md is expected in Github projects, good stuff in it, so we'll
+# distribute it and install it with the package in the doc directory.
+docdir = ${datadir}/doc/${PACKAGE}
+dist_doc_DATA = README.md INSTALL COPYING AUTHORS README NEWS
+
- JQ_SRC = opcode.c bytecode.c compile.c execute.c builtin.c jv.c jv_parse.c jv_print.c jv_dtoa.c jv_unicode.c lexer.c $(JQ_INCS)
++JQ_INCS = \
++ jq_parser.h \
++ builtin.h \
++ bytecode.h \
++ compile.h \
++ execute.h \
++ forkable_stack.h \
++ frame_layout.h \
++ jv.h \
++ jv_alloc.h \
++ jv_aux.h \
++ jv_dtoa.h \
++ jv_parse.h \
++ jv_unicode.h \
++ locfile.h \
++ opcode.h \
++ opcode_list.h \
++ parser.y \
++ jv_utf8_tables.gen.h
+
++JQ_SRC = \
++ opcode.c \
++ bytecode.c \
++ compile.c \
++ execute.c \
++ builtin.c \
++ jv.c \
++ jv_parse.c \
++ jv_print.c \
++ jv_dtoa.c \
++ jv_unicode.c \
++ jv_aux.c \
++ jv_alloc.c \
++ lexer.c \
++ $(JQ_INCS)
+
+if DEVCFLAGS_ENABLED
+DEVCFLAGS = -Wextra -Wall -Wno-missing-field-initializers -Wno-unused-parameter -std=gnu99 -ggdb -Wno-unused-function
+endif
+
+# Tell YACC (bison) autoconf macros that you want a header file created.
+# If the --warnings=all fails, you probably have an old version of bison
+# OSX ships an old bison, so update with homebrew or macports
+AM_YFLAGS = --warnings=all -d
+
+bin_PROGRAMS = jq jq_test
+BUILT_SOURCES = jv_utf8_tables.gen.h lexer.h lexer.c
+jq_SOURCES = $(JQ_SRC) main.c
+jq_CPPFLAGS = $(DEVCFLAGS) -O -DJQ_DEBUG=0
+
+
+TESTS = jq_test
+jq_test_SOURCES = $(JQ_SRC) jq_test.c
+jq_test_CPPFLAGS = $(DEVCFLAGS) -DJQ_DEBUG=1
+LOG_COMPILER = valgrind
+AM_LOG_FLAGS = --error-exitcode=1 -q --leak-check=full
+
+# nasty circular dependency on header files between the generated C files
+parser.o: lexer.c
+
+lexer.o: parcer.c
+
+lexer.c: parser.h
+
+# While there is some autoconf macro support for lex/flex, it doesn't support
+# header file creation so we'll use good old make
+lexer.c: lexer.l
+ flex -o lexer.c --header-file=lexer.h lexer.l
+lexer.h: lexer.c
+
+jv_utf8_tables.gen.h: gen_utf8_tables.py
+ python $^ > $@
+
+jv_unicode.c: jv_utf8_tables.gen.h
+
+ChangeLog:
+ git log --name-status > $@ || echo "no changelog" > $@
+
+main.c: config.h
+
+releasetag:
+ git tag -s "jq-$$(cat VERSION)" -m "jq release $$(cat VERSION)"
+
+# can probably delete and have RPM created off autoconf generated tarball releases
+RELEASE ?= 1
+rpm: jq jq_test
+ @echo "Packaging jq as an RPM ..."
+ mkdir -p rpm/SOURCES rpm/BUILD rpm/BUILDROOT rpm/RPMS rpm/SPECS
+ cp jq-$$(cat VERSION).tar.gz rpm/SOURCES/
+ rpmbuild -tb --define "_topdir ${PWD}/rpm" --define "_prefix ${HOME}" --define "version $$(cat VERSION)" --define "release ${RELEASE}" rpm/SOURCES/jq-$$(cat VERSION).tar.gz
+ find rpm/RPMS/ -name "*.rpm" -exec mv {} ./ \;
+ rm -rf rpm
+
+dist-clean-local:
+ rm -f $(BUILT_SOURCES)
#include <string.h>
#include "builtin.h"
+ #include "bytecode.h"
#include "compile.h"
-#include "parser.h"
+#include "jq_parser.h"
#include "locfile.h"
+ #include "jv_aux.h"
+ #include "jv_unicode.h"
+
+
+
+ typedef jv (*func_1)(jv);
+ typedef jv (*func_2)(jv,jv);
+ typedef jv (*func_3)(jv,jv,jv);
+ typedef jv (*func_4)(jv,jv,jv,jv);
+ typedef jv (*func_5)(jv,jv,jv,jv,jv);
+ jv cfunction_invoke(struct cfunction* function, jv input[]) {
+ switch (function->nargs) {
+ case 1: return ((func_1)function->fptr)(input[0]);
+ case 2: return ((func_2)function->fptr)(input[0], input[1]);
+ case 3: return ((func_3)function->fptr)(input[0], input[1], input[2]);
+ case 4: return ((func_4)function->fptr)(input[0], input[1], input[2], input[3]);
+ case 5: return ((func_5)function->fptr)(input[0], input[1], input[2], input[3], input[4]);
+ default: return jv_invalid_with_msg(jv_string("Function takes too many arguments"));
+ }
+ }
- enum {
- CMP_OP_LESS,
- CMP_OP_GREATER,
- CMP_OP_LESSEQ,
- CMP_OP_GREATEREQ
- } _cmp_op;
+ static jv type_error(jv bad, const char* msg) {
+ jv err = jv_invalid_with_msg(jv_string_fmt("%s %s",
+ jv_kind_name(jv_get_kind(bad)),
+ msg));
+ jv_free(bad);
+ return err;
+ }
- static void f_plus(jv input[], jv output[]) {
- jv_free(input[0]);
- jv a = input[2];
- jv b = input[1];
- if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
- output[0] = jv_number(jv_number_value(a) +
- jv_number_value(b));
+ static jv type_error2(jv bad1, jv bad2, const char* msg) {
+ jv err = jv_invalid_with_msg(jv_string_fmt("%s and %s %s",
+ jv_kind_name(jv_get_kind(bad1)),
+ jv_kind_name(jv_get_kind(bad2)),
+ msg));
+ jv_free(bad1);
+ jv_free(bad2);
+ return err;
+ }
+
+ static jv f_plus(jv input, jv a, jv b) {
+ jv_free(input);
+ if (jv_get_kind(a) == JV_KIND_NULL) {
+ jv_free(a);
+ return b;
+ } else if (jv_get_kind(b) == JV_KIND_NULL) {
+ jv_free(b);
+ return a;
+ } else if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
+ return jv_number(jv_number_value(a) +
+ jv_number_value(b));
} else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) {
- output[0] = jv_string_concat(a, b);
+ return jv_string_concat(a, b);
} else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
- output[0] = jv_array_concat(a, b);
+ return jv_array_concat(a, b);
} else if (jv_get_kind(a) == JV_KIND_OBJECT && jv_get_kind(b) == JV_KIND_OBJECT) {
- output[0] = jv_object_merge(a, b);
+ return jv_object_merge(a, b);
} else {
- output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to add %s and %s",
- jv_kind_name(jv_get_kind(a)),
- jv_kind_name(jv_get_kind(b))));
- jv_free(a);
- jv_free(b);
+ return type_error2(a, b, "cannot be added");
+ }
+ }
+
+ static jv f_negate(jv input) {
+ if (jv_get_kind(input) != JV_KIND_NUMBER) {
+ return type_error(input, "cannot be negated");
}
+ jv ret = jv_number(-jv_number_value(input));
+ jv_free(input);
+ return ret;
}
- static void f_minus(jv input[], jv output[]) {
- jv_free(input[0]);
- jv a = input[2];
- jv b = input[1];
+ static jv f_minus(jv input, jv a, jv b) {
+ jv_free(input);
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
- output[0] = jv_number(jv_number_value(a) - jv_number_value(b));
+ return jv_number(jv_number_value(a) - jv_number_value(b));
} else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
jv out = jv_array();
- for (int i=0; i<jv_array_length(jv_copy(a)); i++) {
- jv x = jv_array_get(jv_copy(a), i);
+ jv_array_foreach(a, i, x) {
int include = 1;
- for (int j=0; j<jv_array_length(jv_copy(b)); j++) {
- if (jv_equal(jv_copy(x), jv_array_get(jv_copy(b), j))) {
+ jv_array_foreach(b, j, y) {
+ if (jv_equal(jv_copy(x), y)) {
include = 0;
break;
}
}
static void run_jq_tests() {
+ FILE* testdata = NULL;
char buf[4096];
- int tests = 0, passed = 0;
+ int tests = 0, passed = 0, invalid = 0;
+ testdata = fopen("testdata","r");
+ if ( NULL == testdata )
+ {
+ /* in an autoconf distcheck, the binary file will be in a _build subdirectory */
+ testdata = fopen("../testdata", "r");
+ if ( NULL == testdata )
+ {
+ fprintf(stderr, "Could not find testdata file\n");
+ exit(1);
+ }
+ }
while (1) {
if (!fgets(buf, sizeof(buf), testdata)) break;
if (skipline(buf)) continue;
#include "locfile.h"
#include "parser.h"
#include "execute.h"
-#include "version.gen.h"
+#include "config.h" /* Autoconf generated header file */
+ #include "jv_alloc.h"
static const char* progname;
static void usage() {
- fprintf(stderr, "\njq - commandline JSON processor [version %s]\n", JQ_VERSION);
+ fprintf(stderr, "\njq - commandline JSON processor [version %s]\n", PACKAGE_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);
}
--- /dev/null
+#!/usr/bin/env bash
+
+# RUN ME after pulling the code from git!
+if [ "clean" == "$1" ]; then
+ make distclean || echo "continuing..."
+ rm -rf tmp autom4te.cache config
+ rm -f INSTALL Makefile.in aclocal.m4 configure config.h.in ChangeLog
+ rm -f jv_utf8_tables.gen.h lexer.c lexer.h parser.c parser.h
+elif [ "superclean" == "$1" ]; then
+ ver=$(tr -d '\n' <VERSION)
+ if [ "x${ver}" != "x" ]; then
+ if [ -d jq-${ver} ]; then
+ chmod -R u+w jq-${ver}
+ rm -rf jq-${ver}
+ fi
+ rm -f jq-${ver}*
+ fi
+else
+ autoreconf --install
+ ./configure --prefix=/opt/junk
++ make check
+ mkdir tmp
+ make DESTDIR=./tmp install
+ make distcheck
+fi