Compare commits

...
628 Commits
Author SHA1 Message Date
Nicolas Williams a5b5cbefb8 Add autoconf outputs (fix #916) 2015-08-17 23:25:04 -05:00
Nicolas Williams 365c1000e7 Fix linker.c includes for win32 (fix #911) 2015-08-16 00:03:10 -05:00
David Tolnay f957a5d639 Update gems
I updated some of these gems for a different project, and
suddenly `rake build` was giving very different output
compared to the current gh-pages. This commit makes sure
everyone updating gh-pages is using reasonably similar
versions, so we avoid spurious diffs.
2015-08-15 23:32:24 -05:00
David Tolnay f98c2b375d Use https where possible
Conflicts:
	docs/content/2.download/default.yml
	docs/content/index/index.yml
	docs/default_manpage.md
	docs/templates/index.liquid
	docs/templates/shared/_header.liquid
2015-08-15 23:32:03 -05:00
Nicolas Williams 70335ccd4f Fix streaming docs errors (fix #904) 2015-08-15 23:25:08 -05:00
David Tolnay 4723a173f5 Update wording and json bodies in tutorial 2015-08-15 23:22:39 -05:00
pkoppstein c4ee746b16 spelling corrections; untabify
Conflicts:
	docs/content/3.manual/manual.yml
2015-08-15 23:22:26 -05:00
Nicolas Williams 5843bb350f Improve assignment docs (see #897) 2015-08-15 23:21:13 -05:00
Nicolas Williams b60c9eb3e8 Test main.c fix for #817 2015-08-13 09:18:44 -07:00
Nicolas Williams 068300229b Make search path expansion portable (fix #817)
This is part 2 of the fix to #817.  Part 1 is the previous commit.
2015-08-13 09:18:44 -07:00
Nicolas Williams 66f7ce5ac3 Make all global module paths absolute (fix #817)
This is part 1 of the fix for #817.  The next commit is part 2.
2015-08-13 09:18:44 -07:00
Nicolas Williams 3045979f6c Fix #896, double-free in setpath 2015-08-11 18:14:04 -05:00
pkoppstein d66fbd218b Clarify documentation of STRING * INTEGER 2015-08-04 21:40:16 -04:00
Nicolas Williams b5edbf7ffa OS X's mktemp -d requires template (fix #876) 2015-07-28 00:28:54 -05:00
Nicolas Williams 6b55baa00f Add missing files (fix #875) 2015-07-28 00:09:46 -05:00
Nicolas Williams 7f251344b7 Fix make dist (fix #870) 2015-07-26 23:26:30 -05:00
David Tolnay 21309bc6d7 Error on bytecodes longer than 0xFFFF (fix #269)
This lets us use uint16_t for the program counter. JVM
languages have the same limit on method size so it is a
reasonable limit.
2015-07-26 16:19:20 -07:00
David Tolnay 8295baf284 Drop plus from "jq 1.5+" on download page
See https://github.com/stedolan/jq/issues/488#issuecomment-124998113
2015-07-26 09:37:34 -07:00
David Tolnay ec84f28630 News is not THIS important 2015-07-26 01:27:14 -07:00
David Tolnay 701a47c82e Add 1.4 and 1.3 manuals to website (fix #866) 2015-07-26 01:26:13 -07:00
David Tolnay 616f365e5a Suggest --disable-maintainer-mode on download page 2015-07-25 23:44:52 -07:00
David Tolnay ceb2684f2f Update setup.sh script
Adjust what gets cleaned up now that ChangeLog and
config/.gitignore are checked into the repo, and skip
install and distcheck steps.
2015-07-24 23:26:47 -07:00
David Tolnay b9c340a211 Change homepage .com -> .io
The .com redirects to .io, but might as well have the
correct one to begin with.
2015-07-24 22:55:58 -07:00
David Tolnay 3a964e2025 Change AC bug-report parameter to point to GitHub
This affects where `make check` tells you to report failures.
2015-07-24 22:48:03 -07:00
Santiago Lapresta 3d49fc59dd Implement flatten/0 in terms of flatten/1 2015-07-24 21:55:43 -07:00
David Tolnay 16e8d0b1ab detect invalid path expression (fix #862) 2015-07-24 20:23:07 -07:00
pkoppstein 5856a2d2c0 simplify implementation of bsearch to use "until" and avoid "last"; tested 2015-07-24 12:29:20 -07:00
David Tolnay 227f62e013 Rebuild jq.1.prebuilt 2015-07-24 09:01:21 -07:00
Evan Zacks 89244cc3ea fix references to --color-output 2015-07-24 10:18:12 -04:00
Thomas R. Hall 3a43e2ff07 Updated v1.3 filenames
The jq 1.3 filenames for Windows are jq-1.3.exe instead of jq.exe. Updated these so they no longer return a 404.
2015-07-23 22:24:39 -07:00
David Tolnay 81f328f1aa Copy over changes made to gh-pages directly
This includes the following commits from the gh-pages branch:

 - 63e80b8
 - d24a397
 - 9796cd6
 - ee21707
 - ccb0f1d
 - 200e6b3
 - 64134c0
 - 57152d2
 - 8ffbfa3
2015-07-23 21:51:30 -07:00
David Tolnay f5a7bba986 Resolve remaining shift/reduce conflicts involving '?'
By lowering the precedence of rules that should never use
the generic Exp '?' rule.
2015-07-19 09:43:10 -07:00
David Tolnay 66ef8e2c24 Resolve shift/reduce conflict of 'def' vs '|'
This was an important conflict. In the following expression:

    def a: 0; . | a

Bison needs to decide between these two equally valid
parses:

    (def a: 0; .) | a
    def a: 0; (. | a)

For jq we want the second one, because the first results in
"a/0 is not defined". In the current parser the first parse
is a reduce and the second parse is a shift. Since Bison
prefers to shift in shift/reduce conflicts, we accidentally
got the correct behavior.

This commit adds a precedence level FUNCDEF which is lower
precedence than '|', meaning we explicitly choose the
correct parse.

Of course many unit tests already cover this case, but I
added one specifically for it.
2015-07-19 09:42:01 -07:00
David Tolnay 1628bbf95f Clean up trailing whitespace 2015-07-19 09:38:50 -07:00
Nicolas Williams 812703139c Use =, not ==, for shell tests 2015-07-18 21:12:08 -05:00
David Tolnay 54add5ac9a travis has whitelisted libonig-dev
https://github.com/travis-ci/travis-ci/issues/4123
2015-07-10 13:21:00 -07:00
Nicolas Williams f183b57ed5 input_filename should never empty 2015-07-10 12:32:11 -05:00
Nicolas Williams dc4dfdff17 Update AUTHORS 2015-07-10 12:28:21 -05:00
Nicolas Williams f55034d314 Update NEWS 2015-07-10 11:26:29 -05:00
Nicolas Williams 930899e12d Update ChangeLog 2015-07-10 11:12:24 -05:00
Nicolas Williams 579518c78d Use include for import into namespace 2015-07-10 10:19:33 -05:00
Nicolas Williams fa45a5121c Simplify import docs 2015-07-10 10:11:30 -05:00
Nicolas Williams 862566a48f Fix typo in docs 2015-07-10 10:10:28 -05:00
James Andariese f9f4d2d1e5 Dockerfile reorganized
* Remove excess layer creation
  This is an antipattern in Docker.
* Remove build tools once build is complete
  Leaving them around is not necessary and expands the image size 5x
* Make check works with libonig installed
* Compiles statically (needs libonig to be built rather than installed)
* Valgrind doesn't work with the use of TLS in jq so it's disabled -- this
  might be a FIXME situation; I'm not familiar enough with valgrind to
  say whether this is expected
* Make entrypoint be the jq binary so that the image can also be used
  to run jq in environments where you don't want to or can't install
  jq (such as CoreOS).
2015-07-10 07:15:44 -07:00
Mike Fletcher b74379532d Fixing missing D in LIBM_DDD_NO macro name 2015-07-09 14:59:37 -04:00
David Tolnay 1e5e0c9fe2 Make jq.h usable from C++
Previously, with clang++:
jq.h:46:37: error: typedef redefinition with different
      types ('struct jq_util_input_state *' vs 'jq_util_input_state')

With g++:
jq.h:46:37: error: conflicting declaration
      ‘typedef struct jq_util_input_state* jq_util_input_state’

This typedef was added to libjq by commit 0d41447 which was
after the 1.4 release, so although it is a public API, this
is not a backcompat break because it has never been in a
release.

Specifying the "*" at all uses of jq_util_input_state is
slightly tedious, but jq_state already works that way, so at
least it will be consistent.
2015-07-04 15:08:01 -07:00
Nicolas Williams 05899f8b3e Fix Windows build 2015-07-04 13:45:24 -05:00
Nicolas Williams a2a6f2d896 Document math support 2015-07-03 21:19:01 -05:00
Nicolas Williams 1c350c67d7 Remove pow10 for now; CHECK_MATH_FUNC needs work
The CHECK_MATH_FUNC() m4 macro needs work.  It should use
AC_RUN_IFELSE(), not just AC_LINK_IFELSE(), and it should #define
_GNU_SOURCE and/or other such feature macros in the prologue to get
non-standard math functions (alternatvely jq should only support
standard math functions).
2015-07-03 21:13:13 -05:00
David Tolnay 2348b7245e docs and diagram for exec_stack 2015-07-02 23:58:07 -07:00
David Tolnay 6e27de4f74 strftime wrong day-of-week (fix #838) 2015-07-01 20:37:16 -07:00
Nicolas Williams e5dafaea44 Document --run-tests 2015-06-28 13:57:02 -05:00
Nicolas Williams fd4f4f2087 Make --run-tests' jv_test() quiet 2015-06-28 13:39:32 -05:00
Nicolas Williams 6c89186437 Make --run-tests less verbose by default
Adding --debug-trace or --debug-dump-disasm before --run-tests now makes
it verbose.
2015-06-27 23:31:44 -05:00
Nicolas Williams 32c4759e6b Add more basic number tests 2015-06-27 23:15:16 -05:00
Nicolas Williams 6366cfd7a4 Add pow, better libm detection (fix #443) 2015-06-27 23:14:46 -05:00
David Tolnay 9985c01975 gcov exclusions 2015-06-27 14:48:13 -07:00
David Tolnay e6371712ff flag to enable gcov and coveralls 2015-06-27 11:25:01 -07:00
David Tolnay d7e35101c5 add configure option to run tests without valgrind 2015-06-27 11:24:53 -07:00
Nicolas Williams 1defaa7b00 Fix braino in merging the previous commit
There's a mantest that shows how to use `env`.  Well, we need to set the
env var as expected then, else it will fail.
2015-06-27 13:00:41 -05:00
David Tolnay 815b4c9772 get Travis CI working 2015-06-27 12:40:01 -05:00
Nicolas Williams aaf305868c Restore import into caller's namespace 2015-06-26 23:40:37 -05:00
Nicolas Williams 8cc31f0f49 Slight re-phrasing of module docs 2015-06-26 23:38:24 -05:00
Nicolas Williams a011ac6392 Use set -u in tests/setup 2015-06-26 23:36:34 -05:00
Nicolas Williams 505e23124f Fix #830 2015-06-26 21:24:01 -05:00
Nicolas Williams e7f6d1e6d0 Update Adavanced section of manual 2015-06-26 21:19:29 -05:00
Nicolas Williams a220482de6 Document {$var} 2015-06-26 21:18:58 -05:00
Nicolas Williams e16bd17571 Add {$var} . as {$var} syntax (fix #831) 2015-06-26 20:45:14 -05:00
Nicolas Williams 25d47ca08e Add streaming utilities (fix #827) 2015-06-26 20:45:06 -05:00
Nicolas Williams 5108a451ca Alternative implementation of tovalues 2015-06-26 20:17:02 -05:00
Santiago Lapresta ec7647c4ab Add combinations/0 and combinations/1 2015-06-23 10:59:58 -05:00
Nicolas Williams 8aecf82bfe WriteFile() on WIN32 when stdout isatty (fix #824)
Use WriteFile() and bypass stdio IFF stdout isatty and we're on Windows.
2015-06-22 20:47:47 -05:00
Nicolas Williams 10cbb9b580 Fix test failure introduced by previous commit 2015-06-22 18:32:28 -05:00
David Tolnay 4a316fbb5a fix errors flagged by clang static analyzer
builtin.c: bug - free of uninitialized jv
compile.c: missing assertion
jq_test.c: buggy logic / unreachable code
jv.c: missing assertion
jv_alloc.c: false positive - intentional read of uninitialized memory
jv_file.c: dead code
2015-06-20 16:08:56 -05:00
Nicolas Williams 7811ef1e17 Fix #811: use CommandLineToArgvW() and _wfopen() 2015-06-19 18:54:44 -05:00
David Tolnay b04cd6aada fix use after free in f_strptime 2015-06-19 00:34:27 -05:00
David Tolnay 1146b8b84a separate jq, oniguruma, sh, and man tests 2015-06-18 23:55:43 -05:00
Nicolas Williams 292f2d3208 argv[] may not be UTF-8 (fix #811) 2015-06-18 21:31:22 -05:00
Doug Luce 3cbefde376 Add alloca() discovery to configure.ac
The build failed on FreeBSD as there is no alloca.h.  This patch is
lifted from the autoconf documentation.
2015-06-18 19:19:15 -05:00
Nicolas Williams 0b42457929 Fix finites 2015-06-18 10:14:52 -05:00
David Tolnay 51a81c96f1 fix broken tests in manual.yml 2015-06-18 00:06:52 -05:00
Nicolas Williams 6083581fea Fix #802 2015-06-18 00:03:46 -05:00
Nicolas Williams 164b877bfa Add isnormal and related, rename *inf 2015-06-17 23:14:26 -05:00
Nicolas Williams b9c2a326ba Fix #814: raise on div-0, add inf isinf nan isnan 2015-06-17 19:58:55 -05:00
Nicolas Williams bdc1feb50e Fix infinite loop on error in sequence parser 2015-06-17 19:58:49 -05:00
Nicolas Williams 4ef04e5b5c Sequence parser: wait for RS on startup (fix #687)
Per-RFC7464.
2015-06-17 11:24:34 -05:00
Nicolas Williams 0f5345e515 Fix infinite loop on EOF bug 2015-06-17 11:23:58 -05:00
Aaron Peschel c95b4a8ab4 Add Missing Makefile Dependency
main.c requires version.h, but there is no logic marking this dependency
in the Makefile. This commit adds the dependency to the Makefile
template.
2015-06-09 19:01:20 -05:00
Nicolas Williams 520b429ca0 Clarify array destructuring docs 2015-06-09 17:29:48 -05:00
David Tolnay d3343d5113 array and object destructuring (fix #533)
`. as [$i, $j, $k] | ...`
`. as {a: $i, b: $j} | ...`
`. as [[[$i]], {a: $j}] | ...`
`foreach . as [$i, $j, $k] (...)`
`reduce . as {a: $i, b: $j} (...)`
2015-06-09 17:29:48 -05:00
cdnbacon 2e96fb2c9b Remove extension from links
The downloads are available without an extension.
2015-06-08 21:30:40 -05:00
Nicolas Williams 24a5e5b1b1 Add --tab and -indent n options 2015-06-03 20:20:11 -05:00
Nicolas Williams 74ecb88935 Improve usage message 2015-05-29 15:35:30 -05:00
Nicolas Williams 33874eb513 Fixup --slurpfile/argile docs 2015-05-29 15:25:30 -05:00
Nicolas Williams 1de56bc5df Add --slurpfile 2015-05-29 14:24:33 -05:00
Nicolas Williams 8a79f1d0a3 Better handling of stdout errors 2015-05-29 11:50:08 -05:00
Nicolas Williams f4f5d8882d Fix --argfile memleak (fix #799 part 2) 2015-05-29 11:49:45 -05:00
Nicolas Williams 4451c08007 Fix jv_load_file() (partial fix #799) 2015-05-29 11:48:10 -05:00
Nicolas Williams 89c57f7936 Revert "Fix #705 (--argfile weirdness)"
This reverts commit 3d2ab93b11.
2015-05-29 10:38:08 -05:00
Nicolas Williams 6af7857ccd Revert "Better argfile fix (#705, fix #736)"
This reverts commit 4f8567476d.
2015-05-29 10:37:58 -05:00
Nicolas Williams dff96aebcf Add jv_mem_strdup*() and callocs too 2015-05-25 21:20:37 -05:00
Nicolas Williams 8af52aaf52 Add ./configure --enable-all-static instead 2015-05-25 21:19:56 -05:00
Nicolas Williams d66e434fb4 Always add -all-static when --enable-static 2015-05-25 14:14:53 -05:00
Nicolas Williams 3700b457aa Update parser.c 2015-05-25 13:35:23 -05:00
Nicolas Williams 11f084f9a7 Keywords should be OK as object keys (fix #794)
With this change it's now OK to use keywords as object keys like so:

    {if:0}
2015-05-25 13:34:07 -05:00
Nicolas Williams 454a9dc042 Fix Windows build: util.c 2015-05-25 02:06:44 -05:00
Steven Penny ff458803ce Fix #793 2015-05-25 02:05:07 -05:00
Travis Gockel 110e009996 Add wrapping and clamping to jv_array_slice
Fix #716.  Fix #717.
2015-05-21 19:17:16 -05:00
Assaf Gordon 7b6a018dff Print offending object in runtime error messages
When reporting an error to the user, add information about the offending
object/value (possibly truncated).

The goal is to give a user some context regarding which input object
caused the runtime error.

Examples:

    $ echo '"hello"' | ./jq '-.'
    jq: error: string ("hello") cannot be negated

    $ echo '"very-long-string"' | ./jq '-.'
    jq: error: string ("very-long-...) cannot be negated

    $ echo '["1",2]' | ./jq '.|join(",")'
    jq: error: string (",") and number (2) cannot be added

    $ echo '["1","2",{"a":{"b":{"c":33}}}]' | ./jq '.|join(",")'
    jq: error: string (",") and object ({"a":{"b":{...) cannot be added

    $ echo '{"a":{"b":{"c":33}}}' | ./jq '.a | @tsv'
    jq: error: object ({"b":{"c":33}}) cannot be tsv-formatted, only array

(Fix #754)
2015-05-21 18:49:24 -05:00
Nicolas Williams a50e548cc5 Fix error message for @tsv 2015-05-21 18:20:15 -05:00
Nicolas Williams 4b258f7d31 Don't test input_filename/line_number yet 2015-05-21 17:55:27 -05:00
Assaf Gordon d1cb8ee0ad Add filename/line functions to jq (fix #753)
This adds `input_filename` and `input_line_number` built-in functions
for use in, for example, `error` messages.

Example:

    $ printf '{"a":1}\n{"a":2}\n' > 4.json
    $ printf '{"a":"hello"}\n' > 5.json
    $ ./jq '{ "file":input_filename, "line":input_line_number, "value":.a }' 4.json 5.json
    {
      "file": "4.json",
      "line": 1,
      "value": 1
    }
    {
      "file": "4.json",
      "line": 2,
      "value": 2
    }
    {
      "file": "5.json",
      "line": 1,
      "value": "hello"
    }
2015-05-21 00:49:32 -05:00
Nicolas Williams c7f063188f Fix formatting error in manual.yml 2015-05-21 00:11:21 -05:00
Assaf Gordon a6460f4fe2 Report filename:line on runtime errors (fix #752)
With this patch, jq run-time errors printed to stderr will contain the
filename and line of the offending input.

But note that the JSON text parser does (yet) print the input filename
on parse error.  A jq run-time error is a jq program error, not
including syntax errors nor JSON text input format errors.

Examples:

With stdin and multiple lines:

    $ printf '{"a":43}\n{"a":{"b":66}}\n' | ./jq '.a+1'
    44
    jq: error (at stdin:2): object and number cannot be added

With multiple files:

    $ printf '{"a":43}' > 1.json
    $ printf '{"a":"hello"}\n' > 2.json
    $ printf '{"a":{"b":66}}\n' > 3.json
    $ ./jq '[.a]|@tsv' 1.json 2.json 3.json
    "43"
    "hello"
    jq: error (at 3.json:1): object is not valid in a csv row

With very long lines (spanning multiple `fgets` calls):

    $ (  printf '{"a":43}\n' ;
         printf '{"a":{"b":[' ; seq 10000 | paste -d, -s | tr -d '\n' ;
         printf ']}}\n' ;
         printf '{"a":"hello"}\n' ) | ./jq '[.a] | @tsv'
    "43"
    jq: error (at stdin:2): object is not valid in a csv row
    "hello"

With raw input:

    $ seq 1000 | ./jq --raw-input 'select(.=="700") | . + 10'
    jq: error (at stdin:700): string and number cannot be added

Caveat:
The reported line will be the last line of the (valid) parsed JSON data.
Example:

    $ printf '{\n"a":\n"hello"\n\n\n}\n' | ./jq '.a+4'
    jq: error (at stdin:6): string and number cannot be added
2015-05-20 23:38:22 -05:00
Nicolas Williams 2e257563a6 Fix spelling 2015-05-20 10:21:30 -05:00
Nicolas Williams ad0090964b Document gsub/3 2015-05-19 01:19:51 -05:00
Nicolas Williams cbdaeb4062 Fix gsub, add gsub/3 (fix #782) 2015-05-18 23:02:11 -05:00
Nicolas Williams cf1306f469 Add -all-static when --enable-static 2015-05-18 12:07:29 -05:00
Nicolas Williams 7675f7434a Fix --stream assertion 2015-05-11 21:36:47 -05:00
Nicolas Williams 821d6404b6 Add error injection library 2015-05-11 21:36:46 -05:00
Nicolas Williams e3cb1f76cd Report read errors too (and fix #772) 2015-05-11 21:36:26 -05:00
Nicolas Williams ef12efbf8c Fix README 2015-05-02 17:36:37 -05:00
Nicolas Williams adb9b9b8a7 README: send questions to SO and Freenode 2015-05-02 17:34:59 -05:00
Nicolas Williams 07f94f82a2 usage() should check fprintf() result (fix #771) 2015-04-28 10:39:34 -05:00
Nicolas Williams 215b4c0fe1 Use jv_mem_alloc() in compile.c (fix #771) 2015-04-28 10:37:37 -05:00
Nicolas Williams 89963e1370 Fix header guards (fix #770) 2015-04-28 10:36:21 -05:00
Nicolas Williams 5d40f3a7c0 --raw-input wrongly adds NULs (fix #761) 2015-04-24 10:42:19 -05:00
Nicolas Williams 5e0e7a7ebd With inputs builtin, -n and -R can now coexist 2015-04-23 23:43:44 -05:00
Nicolas Williams dad6e42934 --raw-input ought to read NULs (partial fix #760)
We can't know how many bytes fgets() read when we reach EOF and fgets()
didn't see a newline; we can only assume that at least strlen(buf) bytes
were read.  This is quite obnoxious if one wants to use NULs in raw
input, but at least we can make reading "a\0b\0c\0" with no newline
yield "a\0b\0c", losing only the final sequence of NULs.

We can't use getline() either, since it will want to allocate a buffer
big enough for an entire line, and we might not have any newlines in our
input.  A complete fix will have to use getc() or read(), preferably the
latter.
2015-04-23 23:43:44 -05:00
Nicolas Williams 7d938487dd --slurp --raw-input is broken (fix #761) 2015-04-23 18:26:57 -05:00
Nicolas Williams fcfacb932d from_entries is broken (fix #767) 2015-04-23 18:25:32 -05:00
Assaf Gordon 6906d291c5 regex functions: report informative error if not available.
When trying to use the new regex functions (match/test/sub/capture/etc)
in a JQ that was compiled without the ONIGURAMA regex library,
report an informative error message instead of a 'not defined' error.

Before:

    $ echo '"foo"' | ./jq-old 'test("foo")'
    jq: error: test/1 is not defined at <top-level>, line 1:
    test("foo")
    jq: 1 compile error

After:

    $ echo '"foo"' | ./jq 'test("foo")'
    jq: error: jq was compiled without ONIGURAMA regex libary. match/test/sub and related functions are not available.
2015-04-22 16:57:03 -05:00
Andrew O'Brien 943090846f Fixes manual generation with psych
When running `make` I ran into a couple of problems building the manual. While
I'm not entirely sure that this is the root cause, it appears to have been
related to the fact that ruby 2.0 dropped syck completely in favor of psych
(which was introduced in 1.9.2) for YAML processing. I'm currently using ruby
2.1.0p0.

I'm assuming that the fact that the YAML engine was explicitly set to syck in
the Rakefile was an attempt to work around some incompatibility between the two
libraries, so I looked into what would be necessary to get it to work with the
newer one. The changes to `manual.yml` ended up being pretty minor: I ran it
through `iconv` to convert some ISO-8859-1 characters to UTF-8 and added some
quotes in places (apparently you can't start a string value with '`').
2015-04-22 11:01:39 -05:00
Assaf Gordon 2dc8621d05 Handle NUL in escaped-string output
When escaping string (e.g. for `@tsv` or `@csv` outputs),
escape NULs as '\0'.

Existing behaviour, unchanged by this patch:

    $ echo '"a\u0000b"' | ./jq '.'
    "a\u0000b"
    $ echo '"a\u0000b"' | ./jq -r '.' | od -a
    0000000   a nul   b  nl
    0000004

When using `@tsv`, escape NUL to `\0`:

    $ echo '"a\u0000b"' | ./jq -r '[.]|@tsv'
    a\0b
    $ echo '"a\u0000b"' | ./jq '[.]|@tsv'
    "a\\0b"
2015-04-20 16:51:48 -04:00
tal@whatexit.org b6cc00fa71 manual.yml: Clarify how to specify keys with ":" and special chars.
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2015-04-16 11:09:49 -05:00
Assaf Gordon 9e2d9b6419 docs: expand @tsv section - add escape sequences. 2015-04-15 23:24:24 -04:00
Assaf Gordon 3210b29bba @tsv: escape \r, \n, \\
When using '@tsv' output format with '-r' option,
escape \r, \n and \\ in addition to \t.

Example:
    $ printf '{"id":"hello\\ttab\\nworld","x":43 }' | jq .
    {
      "id": "hello\ttab\nworld",
      "x": 43
    }

Before: newlines are not escaped, generating invalid TSV output:

    $ printf '{"id":"hello\\ttab\\nworld","x":43 }' \
        | ./jq-old -r '[.id,.x] | @tsv'
    hello\ttab
    world	43

After: newlines are properly escaped:

    $ printf '{"id":"hello\\ttab\\nworld","x":43 }' \
        | ./jq-new -r '[.id, .x] | @tsv'
    hello\ttab\nworld	43

Before: backslashes themselves are not escaped, so there's no way to
distinguish between escaped characters and 'real' backslashes
(in the example below, there is should not be newline, despite the
output containing "\n".

    $ printf '{"x":"hello\\ttab\\\\new world"}' \
        | ./jq-old -r '[.x]|@tsv'
    hello\ttab\new world

After: backslashes are escaped:

    $ printf '{"x":"hello\\ttab\\\\new world"}' \
        | ./jq-new -r '[.x]|@tsv'
    hello\ttab\\new world
2015-04-15 16:11:58 -04:00
Nicolas Williams ddad9618dc Test fix for mktime 2015-03-31 10:03:35 -05:00
Nicolas Williams 24005287f4 Add $__loc__ (fix #740) 2015-03-30 22:36:04 -05:00
Nicolas Williams 1dcfc2f547 Include filename and lineno in error messages 2015-03-30 15:56:29 -05:00
Nicolas Williams 7d6d4066dd Tweak fix for #719 2015-03-24 15:05:06 -05:00
Assaf Gordon 4c22bda09b detect and report output writing errors
Detect output errors when the program exits.

Currently:
    $ echo '{}' | jq . > /dev/full && echo ok
    ok

with the patch:
    $ echo '{}' | jq . > /dev/full && echo ok
    Error: writing output failed: No space left on device

also apply to hardware/network/other I/O errors.

Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2015-03-24 15:01:32 -05:00
Santiago Lapresta 9d62c6fd0c Adds Dockerfile
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2015-03-24 14:59:29 -05:00
Assaf Gordon 5e0db6dd65 partial handling of input errors
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2015-03-24 14:56:46 -05:00
Assaf Gordon 551d875be1 always propagate input errors to exit code
Improve robustness in automated system when using exit code in shell scripts,
by exiting with code 2 if there was any input error (even overriding other
possible error exit codes).
Exit code 2 is already used to indicate system errors.

Without the patch:
   $ jq . no-such-file ; echo $?
   jq: no-such-file: No such file or directory
   0

With the patch:
   $ jq . no-such-file ; echo $?
   jq: no-such-file: No such file or directory
   2

Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2015-03-24 14:55:14 -05:00
Nicolas Williams 4f8567476d Better argfile fix (#705, fix #736) 2015-03-24 14:53:35 -05:00
Nicolas Williams ffa2832e33 Drop name-less label/break for now
See #734 and #658.
2015-03-24 01:21:17 -05:00
William Langford 0f7759f831 Fix #735 2015-03-23 22:11:55 -04:00
Nicolas Williams ccfba00178 Add more date builtins 2015-03-09 11:27:58 -05:00
Nico Williams 3e8183fcd5 Merge pull request #720 from agordon/exit-code-5-exceptions
exit with non-zero code on runtime exceptions
2015-03-08 17:09:07 -05:00
Nicolas Williams 0df387f6b5 Automake: jq depends on version.h (fix #721) 2015-03-08 16:52:08 -05:00
Assaf Gordon 4104c4fa1c exit with non-zero code on runtime exceptions
With this change, runtime exceptions are propagated to non-zero exit
code of 'jq', allow better scripting and automation. The new exit code
value is 5.

This allows using the shell's and/or operations ('&&' and '||') to
detect input runtime exceptions.

Before:
runtime exceptions are printed to STDERR, but not reported as non-zero exit-code:
    $ echo '"hello"' | jq '.|tonumber' ; echo $?
    jq: error: Invalid numeric literal at EOF at line 1, column 5 (while parsing 'hello')
    0

After:
    $ echo '"hello"' | ./jq '.|tonumber' ;  echo $?
    jq: error: Invalid numeric literal at EOF at line 1, column 5 (while parsing 'hello')
    5

Note that there's a subtle interplay when using "-e" option.
The value of the non-zero exit code changes from 4 to 5, but it still
indicates a 'failure' or non-true value.

Before:
    $ echo '"hello"' | jq -e '.|tonumber' ;  echo $?
    jq: error: Invalid numeric literal at EOF at line 1, column 5 (while parsing 'hello')
    4

After:
    $ echo '"hello"' | ./jq -e '.|tonumber' ;  echo $?
    jq: error: Invalid numeric literal at EOF at line 1, column 5 (while parsing 'hello')
    5
2015-03-06 18:50:58 -05:00
Nicolas Williams 33a85679b9 Fix #718 2015-03-06 00:18:45 -06:00
Nicolas Williams a4b9552c82 Add date builtins (fix #364)
Windows support for strptime() is missing.  We can add a copy of one
from a BSD later.
2015-03-06 00:14:15 -06:00
Nicolas Williams b82c231900 Remove -i option (#704)
In-place editing should be implemented with builtins for file I/O.
2015-03-05 21:52:02 -06:00
Nicolas Williams 3d2ab93b11 Fix #705 (--argfile weirdness) 2015-02-18 18:38:11 -06:00
Nicolas Williams c86ef36769 Test in-place functionality; fix #704 2015-02-18 18:01:12 -06:00
Nicolas Williams 3b8d08177f Fix #702 2015-02-18 10:21:21 -06:00
Nico Williams 0164ff0bbc Merge pull request #701 from sseemayer/master
Correct automake and autoconf version requirements
2015-02-18 10:00:23 -06:00
Stefan Seemayer a4baac2256 Correct automake and autoconf version requirements 2015-02-18 13:15:44 +01:00
Nicolas Williams 1e5e9f3ef8 Mention --disable-maintainer-mode in bison error 2015-02-17 11:00:07 -06:00
Nico Williams d58d85af9e Merge pull request #699 from hroptatyr/oniguruma-detection
Fix oniguruma detection logic
2015-02-16 10:54:33 -06:00
Sebastian Freundt 10e8d34fd3 Fix oniguruma detection logic
At the moment, a failed oniguruma header check would leave
HAVE_ONIGURUMA set to 1 still, resulting in a compiler error
in builtin.c.
2015-02-16 09:01:08 +00:00
Nicolas Williams ebc090ad15 README tweaks 2015-02-15 18:34:44 -06:00
Nicolas Williams 8cef5a37ab Add --disable-maintainer-mode; make bison optional
Also flex is now optional.

The outputs of flex and bison are now committed.  By default they get
built, but users who want to build from git can now

    ./configure --disable-maintainer-mode

to turn off the dependency on bison and flex.

Maintainers must, of course, commit the bison and/or flex outputs when
they make changes to parser.y and/or lexer.l, respectively.
2015-02-15 18:34:44 -06:00
Nicolas Williams 8afdeee785 Make Oniguruma/regexp optional
Tests won't pass if built without Oniguruma.  We don't have a way to
make a test optional yet.  That will come later.  For now the ability to
reduce build-time dependencies could really help some users.
2015-02-15 18:32:01 -06:00
Nicolas Williams a83a9e0bc2 Reduce number of msg callback typedefs 2015-02-13 15:58:02 -06:00
Nicolas Williams 0d414471bb Refactor moar: move parts of main.c into libjq
This adds utility functions for reading and parsing files that should be
easy to use by other apps, together with jq_start()/jq_next().
2015-02-13 15:58:02 -06:00
Nicolas Williams 91fb3df495 Refactor handling of inputs in main() (fix #667)
Much of this could be in libjq.  Eventually all of the work of reading
from files and looping over `jq_next()` should move into libjq, with
`main()` mostly doing all the command-line option processing.
2015-02-13 15:55:31 -06:00
Nico Williams 373ef71feb Merge pull request #692 from kim-toms/enhance-from_entries
Enhance from_entries to better deal with Amazon AWS Tags
2015-02-10 10:49:35 -06:00
Kim Toms ca78a746e6 Enhance from_entries to better deal with Amazon AWS Tags 2015-02-10 08:33:56 -05:00
Nicolas Williams 1e13e1e06e Fix sequence warnings (fix #686) 2015-01-30 17:21:50 -06:00
Nicolas Williams 42ff8a6959 Usage message for -h should go to stdout 2015-01-30 10:27:46 -06:00
William Langford 2e92c3e568 Merge pull request #678 from isomorphisms/patch-1
readability
2015-01-27 14:15:07 -05:00
i 5389fdb651 readability
Easier to read dashes than hyphens imho.
2015-01-27 13:32:15 -05:00
Nicolas Williams 7a295b30e0 Fix --raw-input 2015-01-20 00:22:24 -06:00
Nico Williams cca3e92854 Merge pull request #669 from joelpurra/join-empty-array-668
Empty arrays join/1 to an empty string, fixes #668 bug introduced by 9760245
2015-01-14 15:50:15 -06:00
Joel Purra 4d05dc55a3 Empty arrays join/1 to an empty string, fixes #668 bug introduced by 9760245 2015-01-14 12:27:55 +01:00
Nicolas Williams aeb52e29d6 Add debug and stderr builtins
And refactor setup of jv dump flags.
2015-01-14 01:39:13 -06:00
Nicolas Williams 97602456e3 join/1: respect empty strings (fix #668) 2015-01-14 01:32:25 -06:00
Nicolas Williams 8b5ff40402 Split on empty sep: fix #552 moar 2015-01-14 01:32:11 -06:00
Nicolas Williams d630597e87 Fix docs for split/0 2015-01-12 10:47:43 -06:00
Nicolas Williams 60d1ecb58a Fix #552 2015-01-12 10:44:44 -06:00
Nicolas Williams d927a2c185 Fix --run-tests arg handling 2015-01-12 10:43:06 -06:00
Nicolas Williams 6e7cf81d74 Look for jq/main.jq for imports 2015-01-02 19:16:43 -06:00
Nicolas Williams 736f1751ee Add comments to tests/run 2015-01-02 19:15:57 -06:00
Nicolas Williams 28aab9ca79 Fix tests/run in from-tar-ball case
Drop useless use of scripts/version
2015-01-02 19:15:11 -06:00
Nicolas Williams 972c048149 Add static build instructions (fix #294) 2015-01-01 16:26:55 -06:00
Nicolas Williams 902aa39fce Fix warning in util.c 2015-01-01 15:15:10 -06:00
Nicolas Williams 22f55aa585 Include missing EXTRA_DIST items; fix #661 2015-01-01 15:14:49 -06:00
Nicolas Williams 157c95b988 Add mkstemp() for mingw build 2015-01-01 03:14:55 -06:00
Nicolas Williams 426913f127 Fix memleak introduced run-tests enhancement 2015-01-01 02:12:08 -06:00
Nicolas Williams c4cc62a053 Add more missing test files 2015-01-01 01:49:40 -06:00
Nicolas Williams 862696a778 Add missing test file 2015-01-01 01:39:50 -06:00
Nicolas Williams 86bc662bd2 Move some module tests into all.test 2014-12-31 20:09:53 -06:00
Nicolas Williams ae7f8d6ab9 Further module system revamp (fix #659)
To import a module now use:

    # Import module.jq file:
    import "relative/path/to/module" as foo;

    # Use the module's defs as foo::<def-name>

To import a JSON file:

    # Read file.json:
    import "relative/path/to/file" as $foo;
    #
    # Use as $foo::foo

Using `-L` now drops the builtin library path and appends the requested
path to the empty array (or the result of an earlier `-L`).

Support for the `$JQ_LIBRARY_PATH` environment variable has been
removed.
2014-12-31 20:09:53 -06:00
Nicolas Williams 7dc34b92af Add label $name | EXP; fix break
This is to fix the problem where `break` is dynamic, not lexical.

With this it should be possible to do this sort of thing:

    label $break | inputs | if ... then $break|error else . end

This is a backwards-incompatible change for master, but the previous
`break` hadn't shipped yet.

Still needed:

 - testing
2014-12-30 11:42:45 -06:00
Nicolas Williams cbfc0d6130 Remove string indexing by string (fix #454)
This turns out to have been a bad idea:

    "foo"|.["o"]

it interacts badly with `path()`.

See #454 for the gory details.
2014-12-30 11:31:52 -06:00
Nicolas Williams c308b2881f Fix parser leak (fuzzing) 2014-12-30 11:31:52 -06:00
Nicolas Williams c959d1fca1 Fix lineno counting in jq_test.c 2014-12-30 11:28:50 -06:00
Nicolas Williams 63511a874f Add support for testing erroneous programs
This will allow moving tests of some tests from tests/run to
tests/all.test.  It will also be useful for more extensive testing of
language features where we want nice error messages, or errors at all,
to be produced, particularly language features where the errors arise at
compile-, codegen-, or link-time rather than parse-time.

This does not check for run-time errors though -- those we can already
check for with try/catch.

    $ jq --run-tests
    %%FAIL
    break
    jq: error: break used outside labeled control structure
    ^D
    1 of 1 tests passed (0 malformed)
    $
2014-12-30 10:55:30 -06:00
Nicolas Williams 90c705f138 Make --run-tests more informative
Print the line number and program text on the same output line where a
failure is reported, for all failures that were already reported on
lines starting with '***'.  This makes poring over test logs with
failures much easier.
2014-12-30 10:55:30 -06:00
Nicolas Williams b67bad82cb Allow resetting of jq err callback
This will be useful for the upcoming test-erroneous-programs improvement
to --run-tests, so we can switch between the default error reporting
method (print to stderr) to a method internal to --run-tests, and back.

The idea is that when testing programs that are expected to compile (and
link), it'd be nice if errors continue going to stderr, while when
testing programs that must fail to compile (or link), the error has to
be captured so it can be compared to the error expected by the test.
2014-12-30 10:52:38 -06:00
Nicolas Williams 6981b46338 Fix streaming bug (fuzzing) 2014-12-30 01:35:22 -06:00
pkoppstein 752e00bc66 transpose/0 for possibly jagged matrices 2014-12-27 18:52:36 -06:00
pkoppstein 00f018a054 bsearch(x) (binary search): builtin.c (tested), with documentation and test case. Always yields an integer (even if input is unsorted); returns (-1 - ix) if x is not in input array. 2014-12-27 18:44:20 -06:00
pkoppstein 56344670f4 ascii_upcase/0 and ascii_downcase/0 2014-12-27 18:38:52 -06:00
Nicolas Williams 5df20f4954 Add debug builtin
And refactor setup of jv dump flags.
2014-12-27 18:25:34 -06:00
Nicolas Williams a9c613e87d Don't force C API users to set input cb 2014-12-27 18:15:10 -06:00
Nicolas Williams 7538ef34be Make jq --run-tests show test line numbers 2014-12-27 18:15:10 -06:00
Nicolas Williams 5c62a4b805 Fix uninitialized struct field 2014-12-27 18:09:28 -06:00
Nicolas Williams 559863ca68 Streaming parser torture tests 2014-12-26 23:18:07 -06:00
Nicolas Williams 845ad5e969 Fuzz JSON parser 2014-12-26 23:05:57 -06:00
Nicolas Williams 243b1f8e5e Better quoting in tests/run 2014-12-26 23:05:56 -06:00
Nicolas Williams 5bfb9781f7 Add Streaming parser (--stream)
Streaming means that outputs are produced as soon as possible.  With the
`foreach` syntax one can write programs which reduce portions of the
streaming parse of a large input (reduce into proper JSON values, for
example), and discard the rest, processing incrementally.

This:

    $ jq -c --stream .

should produce the same output as this:

    $ jq -c '. as $dot | path(..) as $p | $dot | getpath($p) | [$p,.]'

The output of `jq --stream .` should be a sequence of`[[<path>],<leaf>]`
and `[[<path>]]` values.  The latter indicate that the array/object at
that path ended.

Scalars and empty arrays and objects are leaf values for this purpose.

For example, a truncated input produces a path as soon as possible, then
later the error:

    $ printf '[0,\n'|./jq -c --stream .
    [[0],0]
    parse error: Unfinished JSON term at EOF at line 3, column 0
    $
2014-12-26 23:05:56 -06:00
Nicolas Williams 906d2537b9 Allow C-coded functions to empty
Just return a jv_invalid() without a message.
2014-12-26 23:05:56 -06:00
Nicolas Williams bbb287f54b Add BLOCK_8() macro 2014-12-26 23:05:56 -06:00
Nicolas Williams e51e916e31 Fix foreach non-progation of errors
Errors were being re-propagated as "break".

Also add `error/0` builtin, which made this fix easier.
2014-12-26 23:05:20 -06:00
Nicolas Williams 46e3125e26 Allow zero-length buffers in jv_parser_set_buf()
If the caller is at EOF and has no more bytes to feed the parser, how is
the parser to be told about the EOF condition?  A small fix to allow
zero-length buffers in jv_parser_set_buf() fixes this problem (it also
makes it easier to deal with async I/O: feed the parser whatever is
available, including nothing).
2014-12-26 22:56:48 -06:00
Nicolas Williams c02fcc8fef Fix in and inside 2014-12-26 22:56:48 -06:00
Nico Williams 25d4cbd1b3 Merge pull request #624 from Janrain-Colin/patch-1
Doc correction
2014-12-26 22:14:17 -06:00
Nico Williams 3234a7681e Merge pull request #366 from slapresta/inversed-contains
Added `in` command
2014-12-26 22:00:41 -06:00
Nico Williams 36077da66a Merge pull request #628 from slapresta/map-on-objects
Modify map\1 so that it works on objects
2014-12-26 21:50:11 -06:00
Nicolas Williams 9e1fd8cf4d Fix infinite loop in read_more() (fix #656) 2014-12-24 16:49:55 -06:00
Nicolas Williams a55085b662 Fix EOF handling; fix #656 2014-12-24 16:07:36 -06:00
Nico Williams e0f9b6a5cd Merge pull request #651 from eiiches/fix-examples
Fix several errors in the manual
2014-12-24 11:29:29 -06:00
Nicolas Williams 0053aa868c Add @tsv; fix #645 2014-12-24 11:21:18 -06:00
Nico Williams fab2048648 Merge pull request #653 from msabramo/patch-1
.travis.yml: Set sudo false; use containers
2014-12-24 11:20:47 -06:00
Nicolas Williams 56ae88d9d5 Module search revamp for pkg managers
The search path listed in an import directive can now be an array.  The
top-level search path is appended.  Null and empty strings in the path
terminate any search.  The "." in "." and "./*" is replaced with the
directory containing the file doing the import (for command-line
programs this is the current directory, though that may be a bad idea).

No version numbers or anything of the sort are gratuitously added to the
search paths.

All this makes external package managers possible by allowing
dependencies to be installed local to dependents.
2014-12-24 02:31:51 -06:00
Nicolas Williams 1cdcff1c01 Fix bug caused by 8ca07a0 2014-12-24 02:25:11 -06:00
Nicolas Williams 8ca07a08c3 Fix #348: reject unescaped control chars 2014-12-24 00:01:43 -06:00
Nico Williams 2775b90b20 Merge pull request #601 from slapresta/redefine-any-all
Define {any,all}/0,1 in terms of {any,all}/2
2014-12-23 23:37:25 -06:00
Nicolas Williams ae312bd7fe Use __attribute__ __printf__ with GCC 2014-12-23 23:22:57 -06:00
Nicolas Williams 9017b83d4e Make values faster (fix #652) 2014-12-23 23:22:57 -06:00
Nicolas Williams 02cf1831e9 Fix #649 2014-12-23 18:16:21 -06:00
Marc Abramowitz d237de7b30 .travis.yml: Set sudo false; use containers
This is the way to enable Travis's fancy new containers, which should result in faster builds.
2014-12-22 21:37:23 -08:00
Santiago Lapresta 84d3203dd1 Define map_values 2014-12-22 23:05:35 +01:00
Santiago Lapresta a3234034b5 in is now inside, added in as inverse of has 2014-12-22 22:17:53 +01:00
Santiago Lapresta b748eae035 Added in command 2014-12-22 22:14:06 +01:00
Eiichi Sato a6656edc7c Fix examples in manual 2014-12-21 03:26:04 +09:00
Eiichi Sato b4a9ea56ae Fix indents in manual.yml 2014-12-21 03:24:45 +09:00
Eiichi Sato fdbc91e3c4 HTML-escape jq programs in manual 2014-12-21 03:24:41 +09:00
Eiichi Sato bd67bb8273 Fix examples in manual 2014-12-21 03:24:38 +09:00
Nico Williams 54a0470c42 Merge pull request #611 from StevenMaude/tutorial-typo-fixes
Fix typos in tutorial
2014-12-12 17:46:17 -06:00
Nico Williams 3dd790c408 Merge pull request #616 from ianmiell/ianmiell_requirements
Requirements made slightly more complete
2014-12-12 17:45:17 -06:00
Nicolas Williams be11b2768f Add until(cond; next); fix #639 2014-12-12 17:35:59 -06:00
Nicolas Williams 2075bec60f Fix #647, but caused by 89791a0 2014-12-12 17:05:16 -06:00
Nicolas Williams 44c2382402 Add --argjson, fix #648 2014-12-12 16:40:07 -06:00
Nico Williams fd041c2064 Merge pull request #642 from Janrain-Colin/patch-3
fix typo in manual
2014-12-12 16:03:18 -06:00
Colin von Heuring c6495f6632 fix typo in manual 2014-12-06 16:27:43 -08:00
Nicolas Williams 7243989c52 Fix refcount leak, fix #618 2014-11-29 15:24:43 -06:00
Nicolas Williams 46613af64c STOREV/LOADV* should also print refcnts 2014-11-28 20:52:22 -06:00
Nicolas Williams 79000644c6 Enable printing of stack val refcnts 2014-11-28 19:35:29 -06:00
Nicolas Williams b349e7d9a8 Print stack value refcounts when tracing (#636) 2014-11-28 19:26:41 -06:00
Colin von Heuring 6c8882caf3 Doc correction 2014-11-23 11:37:50 -08:00
William Langford 30e00820a7 Fix #600. Add regression test 2014-11-12 20:46:34 -05:00
Ian Miell 0f81e1bcd0 Requirements made slightly more complete: cf https://github.com/ianmiell/shutit/blob/master/library/jq/jq.py 2014-11-11 23:02:31 +00:00
Steven Maude cb376b27f8 Fix typos in tutorial
parrent > parent, url > URL
2014-11-05 10:47:37 +00:00
Santiago Lapresta dc5e77ef8e Define {any,all}/2 independently from {any,all}/0 2014-10-21 13:00:38 +02:00
Santiago Lapresta 72735167f9 Define {any,all}/{0,1} in terms of {any,all}/2 2014-10-20 22:01:25 +02:00
Nicolas Williams 89791a000b Add support for JSON sequence MIME type
Per draft-ietf-json-text-sequence-07 (which soon will be published as an
RFC).
2014-10-12 08:44:40 -05:00
William Langford 3411167c03 Properly call onig_error_code_to_str
Fix #585
2014-10-06 21:48:56 -04:00
pkoppstein 85f0e30c81 fix sub (#586); add gsub/3; add transpose/0.
Signed-off-by: William Langford <wlangfor@gmail.com>
2014-10-06 21:32:07 -04:00
Nicolas Williams 1796a716ea Restore split/1; don't use regexp (fix #576) 2014-10-03 17:58:45 -05:00
Nicolas Williams 07d8d5c5ef Update docs about sort/group/min/max/unique 2014-10-03 17:58:44 -05:00
Nicolas Williams 0b29b44cab from-entries should work with EC2 (fix #592) 2014-10-03 17:47:13 -05:00
Nicolas Williams a0a350f468 Remove sort/1 and group/1
Reserve these for sorting with jq-coded comparators.
2014-10-03 17:47:13 -05:00
Nicolas Williams 4a57b84db0 to_entries should not sort keys (fix #561) 2014-09-30 21:52:30 -05:00
William Langford f7a2af7052 Properly handle when objects cannot be folded
Fix #579.
2014-09-22 20:14:46 -04:00
Nicolas Williams 456bafa82f Drop the jq version directory from search path 2014-08-30 00:58:24 -05:00
Nicolas Williams 7a8e3c759e Never close stdin; allow multiple - arguments 2014-08-30 00:40:03 -05:00
Nicolas Williams b70bea8d34 Handle invalid inputs in argument files (fix #562) 2014-08-30 00:40:03 -05:00
William Langford d177944b75 Properly handle incomplete json when input is file
Fix #562
2014-08-28 21:52:45 -04:00
Nicolas Williams 9bd55487ea C-coded builtins should not assert (fix #553) 2014-08-21 00:12:29 -05:00
Nicolas Williams 23e2e2eab3 Quiet warning about freopen() of stdout 2014-08-20 20:49:30 -05:00
Nicolas Williams 8d2d5e37e5 Drop "any/" in module search; use 1.x-master 2014-08-20 20:48:48 -05:00
Nicolas Williams 287e2c96ed BSD sed lacks -r; fix #551 2014-08-14 03:31:25 -05:00
Nicolas Williams f8d9478517 Document module system
Fix #511.
2014-08-14 03:26:28 -05:00
Nicolas Williams 1ba8c2cfa6 Add module directive, modulemeta builtin
Fix #425.
2014-08-14 03:26:26 -05:00
Nicolas Williams d654724fef Add JV_OBJECT() macro 2014-08-14 03:21:38 -05:00
Nicolas Williams 3375089013 Add JV_ARRAY() macro 2014-08-14 03:21:38 -05:00
Nicolas Williams 9f13afa20f Add jq_report_error() function; use it
Put a stop to fprintf(stderr, ...) where we shouldn't.
2014-08-14 03:21:35 -05:00
Nicolas Williams 908c10928b Fix #549 2014-08-11 14:58:44 -05:00
Nicolas Williams c321c3b86b Constant fold objects 2014-08-09 20:47:03 -05:00
Nicolas Williams f87521183f Fold constant arrays 2014-08-09 20:27:08 -05:00
Nicolas Williams 8a561120c4 More constant folding: null, true, and false
A step towards doing constant folding for arrays and objects.
2014-08-09 19:15:50 -05:00
Nicolas Williams 20ca21cb0d Out of bounds negative array indices should raise 2014-08-09 19:15:50 -05:00
Nicolas Williams 2d1a75f550 .foo[-1] = ... trips assertion (fix #490) 2014-08-09 13:10:41 -05:00
Nicolas Williams 8cddb7c681 Allow any number of jq-coded function arguments 2014-08-09 12:42:39 -05:00
Nicolas Williams 4249bbf0d5 Make nwise private 2014-08-08 19:36:43 -05:00
Nicolas Williams 8a57c27e92 Make regexp builtins and range/3 use #524 too 2014-08-08 19:31:11 -05:00
Nicolas Williams 8706b6b16a Use def f($a): ...; syntax for builtins 2014-08-08 19:23:46 -05:00
Nicolas Williams 32c08d48f3 Add def f($arg): syntax (fix #524) 2014-08-08 19:16:01 -05:00
Nicolas Williams fc52e78ed4 Fix tests for #432 2014-08-08 18:17:58 -05:00
Nicolas Williams eb12f0358e Fix docs YAML (introduced in #432) 2014-08-08 18:01:42 -05:00
pkoppstein a696c6b551 regex filters (#432): scan, splits, split, sub, gsub 2014-08-08 17:00:14 -05:00
Nicolas Williams 0d437e25de Better error msg for bad shell quoting (fix #538) 2014-08-06 17:51:53 -05:00
William Langford 6744664ff4 Actually check version for bison.
Clean up oniguruma checks.
2014-08-06 12:26:34 -04:00
William Langford ef5bd5a6de Merge pull request #532 from wtlangford/top-removal
Remove duplicate TOP insertions, drop unused defs.
2014-08-05 13:41:59 -04:00
Nicolas Williams 2159f9f5e0 Document TCO a bit more 2014-08-05 01:15:33 -05:00
Nicolas Williams 2518b3a34f Fix docs (missing backquotes) 2014-08-05 01:15:33 -05:00
William Langford c3d6d5fd37 Merge pull request #523 from eproxus/patch-1
Add example of selecting object with keys
2014-08-05 00:50:21 -04:00
William Langford a25950a58c Remove duplicate TOP insertions, drop unused defs. 2014-08-05 00:46:10 -04:00
pkoppstein f8fed0f0bc Apply TCO to recurse/1, add recurse/2; tweak docs
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-08-04 21:11:01 -05:00
Adam Lindberg 89545ea9d0 Add example of selecting object with keys
It is not very straight forward how to select objects by their attributes from an array. This example provides the basic use case of how to select some objects based key values.
2014-08-01 12:13:35 +02:00
Nicolas Williams a2f99d43c3 Some builtins are unnecessarily special (fix #521) 2014-08-01 00:20:30 -05:00
Nicolas Williams a7878a8d1a Correct @wtlangford's address 2014-07-30 13:19:46 -05:00
Nicolas Williams c73ad74be0 Add @wtlangford to the AUTHORS list 2014-07-30 13:02:34 -05:00
pkoppstein 53993a9942 Add capture; document regular expression filters
Fix #493.
2014-07-28 19:41:21 -05:00
Nicolas Williams e1b20b48f0 Add first, nth, last (fix #510) 2014-07-28 13:18:58 -05:00
William Langford 14bc1f6526 Fixing crash when a library's dependency could not be loaded.
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-07-27 17:51:48 -05:00
Nicolas Williams 2e2538ccb8 Fold constants (fix #504) 2014-07-27 17:48:49 -05:00
Nicolas Williams ae27178352 Fix #499, #500 2014-07-27 17:41:40 -05:00
William Langford 0f89270d08 Changing color codes to fix #495 2014-07-22 23:05:43 -05:00
Nicolas Williams 10f5a3448d Do fix remaining bison warning (fix #433) 2014-07-22 22:51:11 -05:00
Nicolas Williams 50b85c2911 Rename jq_memmem() to _jq_memmem() 2014-07-22 22:51:11 -05:00
William Langford 38b939688a Added library system with -l, -L, and JQ_LIBRARY_PATH
Created util.[ch] to hold common utilities.
2014-07-22 22:51:11 -05:00
Nicolas Williams 01fc8168e9 Add -i option to edit files in place (fix #105) 2014-07-20 00:11:23 -05:00
Nicolas Williams 3362fb3406 Add -n to short usage msg; fix --arg msg 2014-07-20 00:04:24 -05:00
Nicolas Williams 8c3d503d54 Fix bison empty rule warnings (#433, partial fix) 2014-07-14 16:41:48 -05:00
Nicolas Williams 2bb9fc5dda Fix #484, try/catch syntax has conflicts 2014-07-14 16:41:48 -05:00
Nico Williams ea3e947b50 Merge pull request #483 from else/master
jq 1.4 is in Debian
2014-07-14 09:16:01 -05:00
Simon Elsbrock 538e012e85 jq 1.4 is in Debian
jq 1.4 is in Debian, please see https://tracker.debian.org/pkg/jq
2014-07-14 11:24:47 +02:00
Nico Williams 918ada06dc Merge pull request #482 from mbruggmann/manual-fixes
Fix manual example for `endswith`.
2014-07-13 19:01:57 -05:00
Nicolas Williams cb2737a433 Add regression test for #479 2014-07-13 19:00:37 -05:00
Nicolas Williams c38e5b1b2c Lib defs don't bind to each other; fix #479 again 2014-07-13 18:36:27 -05:00
Marc Bruggmann 089041b090 Fix manual example for endswith. 2014-07-13 19:02:21 +02:00
Nicolas Williams cadf8c3cb0 Revert "Library defs don't bind to each other; fix #479"
This reverts commit 6b6e3f4262.  It was
the wrong fix.
2014-07-13 02:04:27 -05:00
Nicolas Williams 6b6e3f4262 Library defs don't bind to each other; fix #479 2014-07-12 18:38:55 -05:00
Nicolas Williams 6e88d419ba Fix #478 assertion failure 2014-07-10 19:23:02 -05:00
Nico Williams ab4bf05300 Merge pull request #475 from qqshfox/patch-1
Fix examples for `del` in manual
2014-07-09 10:09:28 -05:00
Hanfei Shen ecac7bd3a1 Fix examples for del in manual 2014-07-09 16:37:17 +08:00
Zhiming Wang 1d620c0de3 Fix invalid YAML in manual.yml
Grave accent "`" is a reserved indicator in YAML per
http://www.yaml.org/spec/1.2/spec.html#id2774228, so it can't start a
plain scalar. This commit applies quoting to titles beginning with
grave accents.

Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-07-09 01:12:23 -05:00
Zhiming Wang f68815d5ad Add tests/all.trs to .gitignore
tests/all.trs is auto generated during make check.

Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-07-09 01:11:41 -05:00
Nicolas Williams 666aeda82c Better document path()'s power; also |= 2014-07-09 01:05:06 -05:00
Nicolas Williams 5be80b81eb Add foreach EXP as $var (INIT; UPDATE) form 2014-07-09 00:43:06 -05:00
Nicolas Williams 10477fc2d4 Make while() handle break 2014-07-09 00:39:25 -05:00
Nicolas Williams d8672e1b2a Make C-coded built-ins take jq_state * argument 2014-07-07 23:37:42 -05:00
Nicolas Williams a68958e5dc error(x) should not tostring its arg; fix #466 2014-07-07 22:26:53 -05:00
Nicolas Williams 824f7df404 limit should use break 2014-07-07 22:26:07 -05:00
Nicolas Williams 4bcff40828 Make any/2 and all/2 efficient using foreach 2014-07-07 22:25:34 -05:00
Nicolas Williams 80a9937e48 exec_stack.h was not using jv_mem_realloc() 2014-07-07 19:33:19 -05:00
Nicolas Williams b963ebaf1d jv_invalid() shouldn't allocate
jv_invalid() should behave like jv_invalid_with_msg(jv_null()), and
neither should allocate memory, because neither ought to need to.
2014-07-07 19:33:18 -05:00
Nicolas Williams eb45372414 jv_show() should be able to display invalid values 2014-07-07 19:33:18 -05:00
Nicolas Williams 539dccae90 Add break builtin for foreach 2014-07-07 19:33:17 -05:00
Nicolas Williams 6458910ba3 Explain foreach's powers a bit more 2014-07-07 17:22:53 -05:00
Nicolas Williams ef9b591215 Document path(path_expression) builtin 2014-07-07 17:13:51 -05:00
Nicolas Williams f845808813 Add missing backtick in manual 2014-07-07 17:13:48 -05:00
Nicolas Williams 25719b5596 $var["foo"]=1 can't work as expected; doc fix #236 2014-07-07 16:56:14 -05:00
Nicolas Williams 8780bc0b8e Better check for lib has only functions (fix #138) 2014-07-07 16:03:32 -05:00
Nicolas Williams 821cd31e67 Add any/N and all/N x N in (1, 2) (fix #455)
Contributed by @pkoppstein.
2014-07-06 20:08:06 -05:00
Nicolas Williams 5a863bf010 Add foreach and limit 2014-07-06 19:40:05 -05:00
William Langford d0ca11d665 Add support for negative indices for .[]; fix #462
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-07-06 01:40:22 -05:00
Nicolas Williams 7d3a44a1e2 Add general ? operator 2014-07-06 01:29:43 -05:00
Nicolas Williams 7fce34292e Add try EXP catch EXP 2014-07-06 01:29:42 -05:00
Nicolas Williams 9113282c27 Document error/1 2014-07-06 00:27:05 -05:00
Nicolas Williams 78a8419428 Add while(cond; update) (fix #314) 2014-07-02 22:05:33 -05:00
Nicolas Williams ff9a61ead2 Add range(init;upto;by) (fix #317) 2014-07-02 22:05:33 -05:00
Nicolas Williams 3a647d3e47 Multi-arity needs better errors (fix #438) 2014-07-02 02:18:10 -05:00
Nicolas Williams 1f17ef3623 Descrive generators, range() with by to manual 2014-07-01 23:32:44 -05:00
Nicolas Williams a6030ab374 Fix typo in manual 2014-07-01 23:32:40 -05:00
William Langford 9f4d7e2fb8 Fixed base64 issue with UTF-8 strings
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-07-01 22:56:13 -05:00
Nicolas Williams ba1acbe961 Teach disassembler about TAIL_CALL_JQ 2014-07-01 22:49:25 -05:00
Nicolas Williams 9deee38dc8 Fix off-by-one in TCO
Now we have the ability to define a generator in jq:

        def for(cond; update):
            def _for:
                if cond then ., (update | _for) else . end;
            _for;

        for(. < 10; . + 1) # generates numbers between `.` and 10

    Running this by hand with --debug-dump-disasm (with a fix for that
    coming up next) we can see that the call to _for is optimized:

        _for:0:
          0000 DUP
          0001 CALL_JQ cond:0^1
          0005 JUMP_F 0022
          0007 POP
          0008 FORK 0012
          0010 JUMP 0020
          0012 CALL_JQ update:1^1
          0016 TAIL_CALL_JQ _for:0^1
          0020 JUMP 0023
          0022 POP
          0023 RET

    And timing this with 1000, 10000, 100000 iterations shows that
    indeed we must be applying TCO; otherwise, without TCO, this gets
    very slow very quickly.
2014-07-01 22:40:40 -05:00
Nicolas Williams 436941d48b TCO to the max!
Close #446.

    Currently tested by disassembling and tracing various recursive jq
    programs by hand under valgrind.  An improved test framework that
    can test for errors and specific bytecode patterns is in
    development.
2014-06-30 23:41:20 -05:00
William Langford e1c5a2f575 Added cross-compilation script to build libjq for iOS.
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-06-30 20:02:19 -05:00
Zhiming Wang a5e9086676 Let @uri produce uppercase hexadecimal digits...
instead of lowercase ones.

According to RFC 3986,

   The uppercase hexadecimal digits 'A' through 'F' are equivalent to
   the lowercase digits 'a' through 'f', respectively.  If two URIs
   differ only in the case of hexadecimal digits used in percent-encoded
   octets, they are equivalent.  For consistency, URI producers and
   normalizers should use uppercase hexadecimal digits for all percent-
   encodings.

See https://github.com/stedolan/jq/issues/451 for details.

Test suite and manual are also updated to reflect this change.

Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-06-30 19:52:42 -05:00
Nicolas Williams 1204e328df Add much commentary about CALL_JQ and call frames 2014-06-30 19:40:56 -05:00
Nicolas Williams 3e1baf5916 Get "Try Online" button working (fix #440) 2014-06-24 00:39:00 -05:00
Nicolas Williams beb0d081bb Improve TCO
Instead of checking for self-recursion check that the thing we're
calling is a function and not a closure, therefore the new frame will
have the same env as the current frame.
2014-06-23 19:59:00 -05:00
Nicolas Williams 4b7c701fdd Tail call optimization (close #437) 2014-06-22 00:24:02 -05:00
Nicolas Williams 233e32208c Fix option stacking bug 2014-06-21 18:01:00 -05:00
Nicolas Williams 63e31c2a35 Remove stray fprintf() from last commit 2014-06-20 23:29:53 -05:00
Nicolas Williams f9349becab Allow stacking of short options (fix #346) 2014-06-20 23:26:54 -05:00
Nicolas Williams ff5cf0abc7 Remove extra free of testmode
I added a jv_free() too many while rebasing @wtlangford's contribution.
It could only be triggered by calling `_match_impl` directly.
2014-06-18 21:11:06 -05:00
William Langford 8ff935c01a Added regex support as per issue #164.
jq now depends on oniguruma for regex support.
Modified configure.ac accordingly.

Added valgrind suppression file for oniguruma to prevent one-time and bounded
leaks from causing tests to fail.

Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-06-18 21:02:47 -05:00
Nicolas Williams 5d9d1b1020 Partial revamp of scripts/crosscompile
Fix #430.
2014-06-18 16:29:37 -05:00
Nicolas Williams 8725d9fa3e Minor style cleanup in main.c 2014-06-17 19:04:55 -05:00
Nicolas Williams 9ae2d66d21 Remove remnants of --online-input option 2014-06-17 19:02:23 -05:00
Nicolas Williams 0c762925b2 Add -j / --join-output option, similar to -r
Fix #215.
2014-06-17 18:59:35 -05:00
David Haguenauer ad52026550 Fixed typo.
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-06-17 18:47:27 -05:00
Nicolas Williams cf7895876b Rebuild jq.1.prebuilt 2014-06-17 18:17:50 -05:00
Nicolas Williams f902d5fae6 Remove trailing whitespace from manual.yml 2014-06-17 18:17:50 -05:00
Nicolas Williams 98e3ebc378 Use new style in manual for defs with args 2014-06-17 18:17:50 -05:00
Santiago Lapresta dde43f796e Simplified standard library
Close #426.

Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-06-17 18:17:50 -05:00
Nicolas Williams 7ee3b724d1 Fix #419, improve Cannot index message (sortof)
jv_get() doesn't know if it's being called in the context of a jq
program or not, so it can't produce a very useful error message when the
types of the to-be-indexed value and the key don't agree.  For now,
including the key (when it is a short string) in the error message is as
significant an improvement as is easy to make.
2014-06-17 17:00:23 -05:00
Nicolas Williams e151a300d0 Fix #266; make help message more useful 2014-06-17 16:47:12 -05:00
Nicolas Williams f58f771660 Fix #280: from_entries of [] is null, should be {} 2014-06-16 22:40:44 -05:00
Nicolas Williams ea63d5d3c2 No args default w/ tty stdout, not tty stdin #220 2014-06-16 22:34:50 -05:00
Nicolas Williams ea0ffe24f8 Don't declare environ on WIN32 2014-06-16 22:34:37 -05:00
Santiago Lapresta 061a604a2a Added flatten and flatten(x) functions
Fix #415.
2014-06-16 17:03:05 -05:00
Nicolas Williams f741074267 Remove download 1.3 button; reposition try online 2014-06-16 17:01:09 -05:00
Nicolas Williams de5952d67e Add ChangeLog and NEWS files 2014-06-16 15:29:48 -05:00
Nicolas Williams a03f4802ef Add missing contributors to AUTHORS 2014-06-16 15:29:31 -05:00
Nicolas Williams 778ba9f7ab Update AUTHORS 2014-06-16 13:25:50 -05:00
Nicolas Williams 676e0ce38e Fix Win64 jq.exe link on main page 2014-06-16 11:13:55 -05:00
Nicolas Williams 088a42fc53 Allow multiple functions with different arities 2014-06-16 00:05:30 -05:00
Nicolas Williams 63dbac28ad Fix typo; rename jq.1-prebuit to jq.1.prebuilt 2014-06-13 19:04:06 -05:00
Nicolas Williams e9a1de47b4 Add env builtin 2014-06-13 17:51:41 -05:00
Nicolas Williams d14fca0cc6 Document the lambda nature of function args #391 2014-06-13 17:22:43 -05:00
Nicolas Williams bb83813f51 Automatically update jq.1.prebuilt 2014-06-13 17:22:17 -05:00
Nicolas Williams 8225d4e0c5 Add jqplay link to the site 2014-06-13 17:21:56 -05:00
Jingwen Owen Ou d45195ab5c jqplay has a domain now 2014-06-12 18:17:39 -07:00
Nicolas Williams 73bd347fcf Add links to Solaris 11+ executables 2014-06-12 19:26:05 -05:00
Nicolas Williams c9dbe090c5 Include links to 1.3 executables in gh-pages 2014-06-12 17:30:30 -05:00
Nicolas Williams 61cc0d4fb1 Make a better jq.1 when Ruby deps missing 2014-06-12 17:30:09 -05:00
Nico Williams 15c4a7f95f Merge pull request #400 from kdeme/master
Heuristic IEEE754 endianness autoconf detection

Use AC_C_BIGENDIAN, though it's not really the correct approach.  Autoconf ought to have provided a test specifically for IEEE754 endianness, since it can differ from integer/pointer endianness!
2014-06-12 15:55:41 -05:00
Kim De Mey 20e629284f Detect endianness at configuration with Autoconf AC_C_BIGENDIAN feature 2014-06-11 10:37:32 +02:00
Nicolas Williams e73951f3d1 Add lib.h to dist file list 2014-06-09 18:58:46 -05:00
Nicolas Williams fdf843c08b Make the note about shell quoting appear on site 2014-06-09 17:43:17 -05:00
Nicolas Williams cf145ec65e Add note about cmd.exe quoting 2014-06-09 10:22:55 -05:00
Nicolas Williams 4889844d0c Building docs fails on powerpc (#349)
Thanks @shym!!
2014-06-09 09:39:02 -05:00
Nicolas Williams dc7857c585 Update site news 2014-06-08 20:45:06 -05:00
Nicolas Williams d65dbf89c9 Also fix configure.ac to use git describe --tags 2014-06-08 19:36:06 -05:00
Nicolas Williams ed2b3e26fb Fix scripts/version: use git describe --tags ...
After tagging as 1.4 scripts/version was still producing jq-1.3-....
2014-06-08 19:31:21 -05:00
Nicolas Williams 46436bd870 Add test of indices with short input 2014-06-08 02:27:27 -05:00
Nicolas Williams 1dbe9317bc Add indices(s), improve index(s), rindex(s)
Now these deal with arrays as input and `s` being an array or a scalar.
2014-06-08 02:01:44 -05:00
Nicolas Williams ef4f3a54fe Improve index and rindex examples 2014-06-08 02:01:21 -05:00
Nicolas Williams 9af03c2562 Remove reference to getpath from docs 2014-06-08 01:35:03 -05:00
Nicolas Williams c10e5f4e73 Document index and rindex (#389) 2014-06-08 00:00:17 -05:00
Santiago Lapresta 01f676041d Added join function
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2014-06-07 21:53:03 -05:00
Nicolas Williams 6856ab8a69 String * number should be commutative 2014-06-07 21:43:30 -05:00
Nicolas Williams 8212750fe9 Add cross-compilation notes to README
A detailed set of instruction as to how to setup a cross-compilation
environment for OS X and Win32/64 would be nice.
2014-06-04 18:36:30 -05:00
Nicolas Williams 35b6b949e3 Add -j option to scripts/crosscompile 2014-06-04 18:36:30 -05:00
Nicolas Williams d1ea3ab89d Add flags argument to jv_parser_new()
For extensibility.  We might add streaming parser options, even binary
JSON encoding options.
2014-06-04 18:35:30 -05:00
Nicolas Williams ae625d0de7 Revert "Add -I / --online-input for huge top-level arrays"
This reverts commit 77936a594d.

There are too many odd bugs in this mode, and it turns out to be a bad
idea anyways.  Instead, in the future a better option will be to pursue
alternative parsers, such as:

 - streaming parser that outputs only when a new leaf value is added or
   an array/object is opened/closed; options here include whether to
   include a path in each output;

 - parsers for binary JSON encodings (there's a variety of them).

Then one might run jq with a streaming parser and use `reduce` to
coalesce inputs from some depth down (instead of from one level down as
the reverted commit had intended).

Besides, a fully streaming parser is desirable in some cases, therefore
we should have such a thing as an option.

I've explored modifying the current parser to support a streaming
option, but it only makes the code very difficult to follow, which is
one reason that alternate parsers makes sense.  At any rate, this is all
for the future.  For now there's no streaming of individual texts, just
text sequences.
2014-06-04 18:15:58 -05:00
Nicolas Williams 5fb82d1018 Fix tests failures on Windows
And Solaris 8 and 9 too, no doubt.  The problem was that non-standard
vsnprintf()s that return -1 when the buffer is too small were not
properly supported.
2014-06-02 00:56:01 -05:00
Nicolas Williams f9d1b94496 Update .gitignore and config/.gitignore 2014-06-01 22:32:53 -05:00
Nico Williams 854ff5643a Merge pull request #367 from slapresta/del-docs
Documented `del` command
2014-05-20 22:11:01 -05:00
Santiago Lapresta 072ebb911b Documented del command 2014-05-21 01:23:28 +02:00
Nico Williams d46f5d29fa Merge pull request #360 from slapresta/275-unique-by
unique_by(.foo) function
2014-05-12 00:30:55 -05:00
Santiago Lapresta 69aa0003af Added texts/examples to unique_by function 2014-05-12 01:44:53 +02:00
Santiago Lapresta 41a093c1f2 Added unique_by function 2014-05-12 01:37:27 +02:00
Nicolas Williams 022a418894 Make pthread tls configurable for Mingw build
For the Mingw build we don't want to pull in the pthread DLL just
because we can autodetect pthread support.  That would make the jq.exe
binary not self-contained.
2014-04-17 20:17:06 -05:00
Nicolas Williams d056668f4f Add autoconf checks for pthreads; fix #340 2014-04-16 18:42:36 -05:00
Nico Williams 917334d18a Merge pull request #332 from jingweno/master
Add link to jq playground
2014-03-20 23:47:40 -05:00
Jingwen Owen Ou 7a83f1c416 Add link to jqplay 2014-03-20 15:49:59 -07:00
Nico Williams 6f0a9521e1 Merge pull request #176 from pearkes/new-tutorial
Docs: Update the tutorial to use GitHub's API
2014-03-13 00:57:54 -05:00
Nicolas Williams aee5c3ecb0 Fix for #303 in the sources 2014-03-13 00:57:33 -05:00
Nico Williams da0d575649 Merge pull request #278 from polyester/master
work with newer versions of automake
2014-03-13 00:52:58 -05:00
Nicolas Williams 74d2216da2 Test arrays and friend filters 2014-03-13 00:29:53 -05:00
Nicolas Williams 769314a8a2 Document scalars 2014-03-13 00:29:53 -05:00
Nicolas Williams 831be04027 Also add scalars 2014-03-13 00:29:53 -05:00
Nicolas Williams 1a1adf73e8 Document arrays, objects, ... 2014-03-13 00:29:53 -05:00
Santiago Lapresta 68f41097b9 Added arrays and other filters
Arrays, objects, numbers, strings, booleans, nulls, values (non-nulls)
-- these builtins filter out those inputs that don't match the name of
the builtin.

This fixes #322 and #324.
2014-03-13 00:27:56 -05:00
Nicolas Williams 4402c6d806 One more recursive merge test 2014-03-12 23:44:21 -05:00
Filippo Valsorda 2aa8a43c5b Add a recursive object merge strategy and bind it to *
This commit adds a jv_object_merge_recursive function, that performs
recursive object merging, and binds it to multiply when applied to
two objects.

Added docs and tests.

Closes #320
2014-03-08 03:56:05 +01:00
Nicolas Williams 219bb9ecb7 Make libm tests more portable 2014-03-06 21:38:10 -06:00
Nico Williams 88fd2ee4f2 Merge pull request #310 from arodland/master
Make jq --raw-output --unbuffered work
2014-03-03 13:46:38 -06:00
Andrew Rodland 6c3683dfe9 Repair jv_show 2014-02-26 01:43:00 -06:00
Andrew Rodland 36e495da1e Make jq --raw-output --unbuffered work
--unbuffered was only affecting the normal output case, not the --raw-output case. Make the two of them play together.

This also makes sure that the output is flushed *after* printing the newline, so a consumer doesn't lag a line behind.
2014-02-26 01:42:29 -06:00
Nicolas Williams 15faf9dc3b Add cbrt (cube root) 2014-02-21 10:51:16 -06:00
Nicolas Williams 59302fd208 Add missing trig functions and barebones test 2014-02-21 10:49:21 -06:00
Nicolas Williams 24202d1ecf Remove non-standard exp10() 2014-02-21 10:49:10 -06:00
Mike McCabe 336f4e27e6 Initial add of math functions. 2014-02-21 08:46:56 +00:00
Nicolas Williams fe29d3d3fa Add ?, .[]?, and .. operators
Make XPath-like `//a/b` recursive structure traversal easier in jq,
which then becomes:

    ..|.a?.b?

The `?` operator suppresses errors about . not being an array or object.
The `..` operator is equivalent to calling the new `recurse_down`
built-in, which in turn is equivalent to

    recurse(.[]?)

Note that `..a` is not supported; neither is `...a`.  That could be add
added, but it doesn't seem worth the trouble of saving the need to type
a '|'.
2014-02-20 15:33:07 -06:00
Nico Williams 3d33412e9a Merge pull request #300 from lcd047/master
Fix building of the manual
2014-02-19 11:21:04 -06:00
LCD 47 fb9196021e manual.yml: fix indent for the new any and all commands. 2014-02-19 15:10:32 +02:00
Nico Williams b23fae9ee3 Merge pull request #296 from slapresta/all-any
Added `all` and `any` builtins
2014-02-16 22:45:49 -06:00
Santiago Lapresta 8b41415b07 Added all and any builtins 2014-02-17 04:01:32 +01:00
Nicolas Williams 1fa55a3fae Fix cut-n-paste in leaf_paths; doc and test 'em 2014-02-05 23:14:05 -06:00
Nicolas Williams a45c937f80 #285 add and builtins 2014-02-05 15:23:32 -06:00
polyester 6ed3adb091 work with newer versions of automake
when using a newer automake, the autoreconf step fails with warnings:
"linking libtool libraries using a non-POSIX archiver requires 'AM_PROG_AR' in 'configure.ac' "

This happens for instance on ubuntu 13.10. 
Doing just that, adding 'AM_PROG_AR' to configure.ac fixes the problem.
2014-01-25 18:55:58 +01:00
Nicolas Williams 106fdf5114 Fix #201; check that bison accepts --warnings 2014-01-01 23:10:00 -06:00
Nicolas Williams 99f170adc3 Fix version for make dist on master
- Re-remove VERSION file and all traces of it
 - Pass a decent version indicator to AC_INIT (using git describe)

When we tag 1.4 this will produce 1.4 as the version string when
building on the HEAD of that tag.
2013-12-31 17:19:40 -06:00
Joe Littlejohn f60d83c15f Fix rpm build (make rpm)
* Re-add VERSION as it's required for `./setup superclean`
  and `make rpm`.
* Add *.rpm to git ignore, we never want them under version control.
2013-12-27 13:01:14 -06:00
Filippo Giunchedi 36a47bae56 include additional files in jq.spec
this will probably need changing upon SONAME bump
2013-12-27 12:49:15 -06:00
Filippo Giunchedi dc8528af0f fix rpm Makefile target and prerequisites
depend on dist and the specfile, plus use automake's variables
2013-12-27 12:49:15 -06:00
Nicolas Williams e12d0ffd1e Document --version 2013-12-26 18:48:51 -06:00
Nicolas Williams a71138a43a Add jv_dumpf() and jv_show()
jv_dumpf() takes a FILE *.

jv_show() is intended for use in debuggers, so it dumps the jv to stderr
and it does not jv_free() the jv, so it's safe to
"call jv_show(some_jv, -1)" in a debugger.  If flags == -1 then the jv
will be shown pretty-printed and in color.
2013-12-26 18:40:34 -06:00
Nicolas Williams cb976b9a50 Document .foo.bar in manual 2013-12-26 18:25:31 -06:00
Nicolas Williams 060eb39bf9 Document exit numbers 2013-12-26 12:54:07 -06:00
Nicolas Williams ab363e9e50 Normalize errors for -e 2013-12-26 12:54:03 -06:00
Nicolas Williams 41a8ae7557 Fix doc typos (.[foo] wanted to be .["foo"]) 2013-12-25 17:09:27 -06:00
Nicolas Williams 1956abbedf Add note to jq.1 about shell quoting 2013-12-25 17:05:32 -06:00
Stephen Dolan 2003a0440f Merge pull request #251 from phihag/fix-uri-in-manual
Fix @uri example
2013-12-21 11:47:24 -08:00
Stephen Dolan a0274cc46e Merge pull request #252 from phihag/ignore-config-test-driver
Ignore the config/test-driver file
2013-12-21 11:46:53 -08:00
Philipp Hagemeister 3b384740b9 Ignore the config/test-driver file
This file is automatically generated and does not need to be committed.
2013-12-20 11:36:52 +01:00
Philipp Hagemeister 4d40a47eab Fix @uri example
Previously, the @uri example didn't match the actual behavior of the current jq, as exclamation marks do not need to be encoded in URIs.
Replace the example with an input that needs encoding, and is encoded by jq.
2013-12-20 11:32:53 +01:00
Stephen Dolan 18e828f17c Allow negated object values without parens. Fixes #247 2013-12-17 22:28:31 +00:00
Nicolas Williams 0966230ba8 Fix memmem() error 2013-12-17 08:40:03 -06:00
Stephen Dolan 669f4ab4c3 Merge pull request #242 from sieben/travis-ci
Adding a .travis.yml file to use the travis-ci.org
2013-12-15 12:54:17 -08:00
Rémy Léone 3455714410 Adding a .travis.yml file to use the travis-ci.org
From wikipedia:

Travis CI is a hosted, distributed continuous integration service used
to build and test projects hosted at GitHub.

Travis CI is configured by adding a file named .travis.yml, which is a
YAML format text file, to the root directory of the GitHub repository.

Travis CI automatically detects when a commit has been made and pushed
to a GitHub repository that is using Travis CI, and each time this
happens, it will try to build the project and run tests. This includes
commits to all branches, not just to the master branch. When that
process has completed, it will notify a developer in the way it has been
configured to do so — for example, by sending an email containing the
test results (showing success or failure), or by posting a message on an
IRC channel. It can be configured to run the tests on a range of
different machines, with different software installed (such as older
versions of a programming language, to test for compatibility).
2013-12-13 17:14:37 +01:00
Stephen Dolan 32ea50d336 Make the testsuite run on machines without valgrind 2013-12-13 15:22:17 +00:00
Stephen Dolan 5ac6a460fa Format more integers as integers, not scientific notation.
jq is now willing to put up to 15 zeros after an integer before
moving to scientific notation.
2013-12-13 15:22:17 +00:00
Stephen Dolan f147b7fae5 Merge pull request #239 from DRMacIver/overflows
Avoid undefined behaviour with large array indices
2013-12-12 16:38:14 -08:00
Nicolas Williams 474386a1d9 Complete more-arity feature not complete
And test
2013-12-11 14:14:26 -06:00
Stephen Dolan 7fd2c2d08b Merge pull request #235 from DRMacIver/prototypes
some functions were missing proper prototypes
2013-12-10 03:56:02 -08:00
David R. MacIver 5412f3f1c1 convert range bounds to integers in a way that avoids undefined behaviour 2013-12-10 09:20:13 +00:00
David R. MacIver 014b45b4a9 add checking of numeric indices to an array to see if they can reasonably be considered integers. Avoid undefined behaviour if out of bounds 2013-12-10 09:20:12 +00:00
David R. MacIver 30ea390b77 some functions were missing prototypes. Add them 2013-12-10 00:07:08 +00:00
Stephen Dolan 00f244385b Merge pull request #232 from DRMacIver/teardown_on_error
consistent use of goto out in main
2013-12-08 16:41:16 -08:00
David R. MacIver 7b671b95d2 don't need to check for NULL there 2013-12-08 23:52:07 +00:00
Stephen Dolan 1535f23455 Merge pull request #233 from DRMacIver/printf
Fix warnings about vprintf
2013-12-08 15:44:33 -08:00
Stephen Dolan 4ba0c8baef Merge pull request #231 from DRMacIver/fix_mem_leak_in_compile
args to jq_compile_args were not getting freed when there were errors in the compile
2013-12-08 15:17:20 -08:00
Stephen Dolan a7dd3ab793 Clean up string/object interactions in jv. 2013-12-08 22:49:28 +00:00
David R. MacIver f6f7d4d973 These vfprintfs are being used as if they were printfs. Fix that 2013-12-08 20:08:04 +00:00
David R. MacIver f4ae5c883b consistent use of goto out in main 2013-12-08 19:22:18 +00:00
Stephen Dolan 74a14f5de7 Refactor jv structure.
New structure layout is simpler and also faster.  In particular, it's
now small enough to be passed in registers on amd64.
2013-12-08 17:46:23 +00:00
Stephen Dolan fee21c959a Make testsuite not leak when compiled with -DNDEBUG. 2013-12-08 17:44:54 +00:00
David R. MacIver 4b48054f41 test for losing memory on compile errors 2013-12-08 16:19:12 +00:00
David R. MacIver 17a319d120 args to jq_compile_args were not getting freed when there were errors in the compile 2013-12-08 15:28:29 +00:00
Nicolas Williams 3a1dab5396 Fix double-free typo in print_error() 2013-12-06 23:25:06 -06:00
Nicolas Williams dac081e183 Fix manual.yml 2013-12-06 11:58:55 -06:00
Stephen Dolan 489fcdc089 Merge pull request #224 from nicowilliams/features
Features: more arity, string ops
2013-12-04 17:36:08 -08:00
Nicolas Williams 3ba7c97b2a Add self to AUTHORS 2013-12-04 18:21:42 -06:00
Nicolas Williams 54635000c5 Conditionally #define _GNU_SOURCE in compile.c 2013-12-04 18:21:42 -06:00
Nicolas Williams 426edff09c Add tests for string index by string and builtins 2013-12-04 18:21:42 -06:00
Nicolas Williams b37ce20c2a Add index and rindex builtins 2013-12-04 18:21:42 -06:00
Nicolas Williams cac14a531d Add index strings by string; return string indexes
% jq '.[","]'
    "a,bc,def,ghij,klmno"
    [1,4,8,13]
    %
2013-12-04 18:21:42 -06:00
Nicolas Williams ae7a042876 Make length return abs value of numeric inputs 2013-12-04 18:21:42 -06:00
Nicolas Williams eb165459aa Add callback interface for errors
Printing to stderr is not the right answer for a library.
2013-12-04 18:21:41 -06:00
Nicolas Williams 04bc2ef7cf Add jv_string_vfmt() 2013-12-04 18:21:41 -06:00
Nicolas Williams 09104ce531 Document ltrimstr and rtrimstr 2013-12-04 18:21:41 -06:00
Nicolas Williams 9fa2173825 Test ltrimstr and rtrimstr functions 2013-12-04 18:21:41 -06:00
Nicolas Williams 346da34432 Add ltrimstr and rtrimstr functions 2013-12-04 18:21:41 -06:00
Nicolas Williams fa316ac430 Document -u / --unslurp option 2013-12-04 18:21:41 -06:00
Nicolas Williams 77936a594d Add -I / --online-input for huge top-level arrays 2013-12-04 18:21:41 -06:00
Nicolas Williams 4e07eac356 Document -e / --exit-status argument 2013-12-04 18:21:40 -06:00
Nicolas Williams d018e43ddc Add -e | --exit-status CLI option 2013-12-04 18:21:40 -06:00
Nicolas Williams 8cee66e609 Document tojson and fromjson builtins 2013-12-04 18:21:40 -06:00
Nicolas Williams 3c4248192d Test tojson and fromjson 2013-12-04 18:21:40 -06:00
Nicolas Williams 255f8ef5be Add tojson and fromjson builtins 2013-12-04 18:21:40 -06:00
Nicolas Williams 20b32db5af Document split function 2013-12-04 18:21:40 -06:00
Nicolas Williams b634722c8a Document string multiplication and division 2013-12-04 18:21:40 -06:00
Nicolas Williams c9e8581f45 Document string functions and slicing 2013-12-04 18:21:39 -06:00
Nicolas Williams da129f6664 Test string slicing 2013-12-04 18:21:39 -06:00
Nicolas Williams 884e6c7d8b Add string slicing 2013-12-04 18:21:39 -06:00
Nicolas Williams 5aadaa79eb Add tests for string division/splitting 2013-12-04 18:21:39 -06:00
Nicolas Williams cf562961b7 Add string division by string (split on separator) 2013-12-04 18:21:39 -06:00
Nicolas Williams 63bed9bdf1 Test starts/endswith and string multiplication 2013-12-04 18:21:39 -06:00
Nicolas Williams 5989dbdfcf Add string multiplication by number 2013-12-04 18:21:39 -06:00
Nicolas Williams db19a11399 Add startswith/endswith 2013-12-04 18:21:38 -06:00
Nicolas Williams 6c734cb609 Add explode/implode jq functions to match jv API 2013-12-04 18:21:38 -06:00
Nicolas Williams ef41d1cb57 Use uint32_t for codepoint in jv_string_append_codepoint() 2013-12-04 18:21:38 -06:00
Nicolas Williams 08b4a34a8e Add jv string utility functions
jv_string_empty()
        -> return an empty string with given allocated length (for fast
           appends)
    jv_string_append_codepoint
        -> append a single codepoint (int) to the given string
    jv_string_explode
        -> return an array of codepoints making up a string
    jv_string_implode
        -> return the UTF-8 encoding of an array of codepoint numbers
2013-12-04 18:21:38 -06:00
Nicolas Williams 1fc5656762 Support more arguments for defs 2013-12-04 18:21:38 -06:00
Stephen Dolan 91cfc34ae4 Preserve insertion order in objects. Closes #169. 2013-12-04 22:30:39 +00:00
Nicolas Pouillard a0b942a7f5 Add a few more test cases (from the man page)
Signed-off-by: Nicolas Williams <nico@cryptonector.com>
2013-11-30 00:55:26 -06:00
Stephen Dolan 6a401c8262 Add a --unbuffered option. Closes #206 2013-11-08 12:21:45 +00:00
Stephen Dolan d235f32bc9 Merge pull request #210 from Habbie/patch-1
count should be length
2013-11-08 03:43:57 -08:00
Peter van Dijk bdbfa7e32c count should be length
Example refers to a count function, which does not exist. Replacing it with length works.
2013-11-07 16:39:44 +01:00
Stephen Dolan 78976b3504 Merge pull request #193 from ryo1kato/fix-docs
Docs: add description of --from-file option
2013-11-07 04:41:01 -08:00
Stephen Dolan 8d4748c8df Fix a crash on group_by of empty list. Fixes #208. 2013-11-07 12:18:48 +00:00
Ryoichi KATO da723d3e11 Docs: add description of --from-file option 2013-10-16 21:42:29 +09:00
Stephen Dolan 0feeb7d0d4 Merge pull request #188 from Juanxo/patch-1
Fix typo on error message
2013-10-07 06:59:50 -07:00
Juan Guerrero 9e53f36a74 Fix typo on error message 2013-10-06 17:52:04 +02:00
Stephen Dolan 7e7c08da47 Merge pull request #185 from qoelet/master
Add missing -i flag in build instructions
2013-09-20 06:05:42 -07:00
Kenny Shen 2f6b89ef70 Add missing -i flag in build instructions 2013-09-20 10:34:57 +08:00
Stephen Dolan 4e3024cb61 Merge pull request #182 from mdaines/sqrt-builtin
Add builtin for calculating square root
2013-09-14 16:34:52 -07:00
Michael Daines c427bf6a94 Add test showing calculation of standard deviation 2013-09-14 17:48:19 -04:00
Stephen Dolan dae2422fd1 Merge branch 'libjq'
Conflicts:
	Makefile.am
	configure.ac
2013-09-14 19:30:39 +01:00
Stephen Dolan f98e3e6c26 Merge pull request #181 from mdaines/patch-1
Fix typo
2013-09-13 15:24:22 -07:00
Mike Daines fe99532f8b Fix typo 2013-09-13 12:15:52 -04:00
Stephen Dolan 41a4968c90 Merge pull request #171 from joelittlejohn/fix-makefile
Fix Makefile after refactoring of stacks in 05d90517b0
2013-09-13 09:02:42 -07:00
Stephen Dolan 1cdaabf2dd Merge pull request #175 from lipidity/fix-build
Call AM_INIT_AUTOMAKE once only
2013-09-13 09:02:24 -07:00
Michael Daines 82d8253c19 Add sqrt operator 2013-09-11 20:24:41 -04:00
Jack Pearkes c1717d6e12 docs: update the tutorial to use GitHub's API 2013-09-04 11:42:40 +02:00
Ankur f0d1c39b5b Call AM_INIT_AUTOMAKE once only
Fixes build with automake-1.14
2013-09-01 18:58:26 +10:00
Joe Littlejohn 111aea3f0a Fix Makefile after refactoring of stacks in 05d90517b0 2013-08-19 13:40:08 +01:00
Stephen Dolan 37cfc912c1 Remove #includes from jv.h 2013-06-23 14:23:07 +01:00
Stephen Dolan 8c2e228c74 Fix the jv_parser interface. 2013-06-23 12:26:49 +01:00
Stephen Dolan 8630fb02bb Use libtool's built-in symbol exporting rather than a mapfile. 2013-06-23 12:10:58 +01:00
Stephen Dolan 5052ab4e2b Move gen_utf8_tables to scripts 2013-06-23 12:08:22 +01:00
Stephen Dolan a44f739356 Move libtool m4 junk to config/ and delete some autogenerated files. 2013-06-23 12:01:58 +01:00
Stephen Dolan f44ecf3872 Remove Autoconf-generated config.h. 2013-06-23 12:01:58 +01:00
Stephen Dolan 1c9e03f800 Merge branch 'header-cleanup' into libjq
Conflicts:
	Makefile.am
2013-06-22 23:27:16 +01:00
Stephen Dolan 5d9ec83805 Build libjq only once, and link it statically to ./jq
This means ./jq is a real binary rather than a libtool turd.
2013-06-22 20:53:28 +01:00
Stephen Dolan 3a295c659b Fix distcheck.
Update list of files to be distributed.
2013-06-22 20:53:03 +01:00
Stephen Dolan d253414783 Merge pull request #162 from stedolan/utf8-fixes
Utf8 fixes. Closes #161
2013-06-22 09:30:59 -07:00
Stephen Dolan 8b1b503609 Reject all overlong UTF8 sequences. 2013-06-22 13:43:46 +01:00
Stephen Dolan ff48bd6ec5 Fix various UTF8 parsing bugs.
In particular, parse bad UTF8 by replacing the broken bits with U+FFFD
and resychronise correctly after broken sequences.
2013-06-22 13:34:24 +01:00
Stephen Dolan 54b9c9bdb2 Fix example in manual for floor. See #155. 2013-06-22 12:17:28 +01:00
Nicolas Williams 3dcdc582ea Document floor 2013-06-21 15:27:34 -05:00
Nicolas Williams 7c4171d414 Add floor operator 2013-06-21 15:27:34 -05:00
Nicolas Williams 1d839ff9df Document mod 2013-06-21 15:27:34 -05:00
Nicolas Williams 3403d07912 Add mod (and setmod) operators 2013-06-21 15:27:34 -05:00
Nicolas Williams e8643787cf Update .gitignore 2013-06-21 12:41:57 -05:00
Nicolas Williams 298b2a6033 Add libjq autoconf goo 2013-06-21 11:57:12 -05:00
Nicolas Williams c791428905 Quiet setup.sh re: tmp dir 2013-06-21 11:57:11 -05:00
Stephen Dolan dc2fe63e42 Merge pull request #157 from nicowilliams/argfile-fixes
Argfile fixes
2013-06-21 09:40:32 -07:00
Stephen Dolan 7af88962ee Move cfunction invocation code to the interpreter loop. 2013-06-21 12:06:28 +01:00
Nicolas Williams 3216d7683a Fix serious bug in handling of --argfile 2013-06-18 19:05:52 -05:00
Nicolas Williams e4094c8664 Fix leaks in jv_load_file() 2013-06-18 19:05:52 -05:00
Stephen Dolan b49d65a276 Fold opcode.{c,h} into bytecode.{c,h} 2013-06-18 01:36:18 +01:00
Stephen Dolan 824ce76cec Simplify block functions for variables 2013-06-18 01:07:18 +01:00
Stephen Dolan 2a18f97d12 Saner build instructions in README.md
Closes #144
2013-06-18 00:29:05 +01:00
Stephen Dolan 8c4d29ee38 Remove some initialise-to-zero code.
This lets valgrind find more bugs - if a field isn't given a
well-defined value valgrind will now find it instead of seeing it
set to zero with memset.
2013-06-18 00:17:20 +01:00
Stephen Dolan 2c13f4fe72 Merge branch 'stack-refactor-merge' 2013-06-18 00:13:44 +01:00
Stephen Dolan 94931040a8 Merge branch 'stack-refactor'
Conflicts:
	execute.c
2013-06-18 00:06:00 +01:00
Stephen Dolan b78a4cdc93 Merge pull request #154 from nicowilliams/no-fopen-re
Remove accidentally introduced use of fopen "e"
2013-06-17 15:34:01 -07:00
Nicolas Williams da09544bb0 Remove accidentally introduced use of fopen "e" 2013-06-17 17:27:25 -05:00
Stephen Dolan ce17b6bd53 Merge pull request #114 from nicowilliams/nomem_handler
Add jv_nomem_handler()
2013-06-16 06:20:27 -07:00
Nicolas Williams fe03bea191 Remove last remnant of main.h 2013-06-16 08:06:52 -05:00
Nicolas Williams 0ed6347d47 Allow --run-tests to take a file argument 2013-06-15 17:37:15 -05:00
Nicolas Williams 3f86e97f70 Fixup API to get closer to a libjq 2013-06-15 17:37:15 -05:00
Stephen Dolan 69fa279e3c Merge pull request #150 from nicowilliams/jv_load_file
Move slurp_file() into library as jv_load_file()
2013-06-15 05:29:17 -07:00
Nicolas Williams bbf4e05fde Move slurp_file() into library as jv_load_file()
Needed as part of creating a libjq.
2013-06-15 00:08:59 -05:00
Stephen Dolan 05d90517b0 Clean up lots of stack and frame logic.
Move frame defs to execute.c
2013-06-14 22:08:18 +01:00
Stephen Dolan 5f5c1dc5a6 Simplify frame logic. 2013-06-14 01:20:24 +01:00
Stephen Dolan e0524644f8 Unify all stacks. Passes tests, but needs cleanup. 2013-06-13 21:50:32 +01:00
Stephen Dolan 81e2336ace Support ."foo" syntax for accessing fields. See #141. 2013-06-11 22:26:39 +01:00
Stephen Dolan 25bf1a0169 Unify frame and data stacks 2013-06-10 01:17:58 +01:00
Stephen Dolan c8ab67be27 Speed up cached configure (./configure -C) 2013-06-05 16:40:01 +01:00
Stephen Dolan 6c34288ebf Clean up flex lines in build 2013-06-05 13:43:23 +01:00
Stephen Dolan 2ffbb9d6b7 Lex and parse .foo better.
'.as' is now valid, '. foo' is now invalid. See #141.
2013-06-05 13:41:56 +01:00
Stephen Dolan dad608d5c0 Merge pull request #142 from lanthaler/master
Update README.md
2013-06-04 04:13:24 -07:00
Markus Lanthaler 04b939625b Update README.md
Update the link to the documentation. All GitHub pages are now using the github.io domain.
2013-06-04 13:04:42 +02:00
Stephen Dolan 5dac485458 Make jq --version print to stdout, not stderr 2013-06-03 23:22:59 +01:00
Stephen Dolan 2c4ccd122e Better error handling for .foo case in parser. See #141. 2013-06-03 23:12:31 +01:00
Stephen Dolan b90ae078b8 Let the parser rather than the lexer handle invalid characters. 2013-06-03 23:12:31 +01:00
Stephen Dolan cc8761dbde Add command-line option to sort object keys.
Closes #79.
2013-06-03 23:12:31 +01:00
Stephen Dolan 08cc591884 Clean up Makefile.am (distcheck, rebuild version.h less often) 2013-06-03 23:12:31 +01:00
Stephen Dolan 1bc4d04f43 Merge pull request #139 from 13ren/stopwarning
Stop warning on fgets, jq_test.c:42
2013-06-01 07:30:15 -07:00
Brendan Macmillan d4018192a9 Stop warning on fgets, simple version 2013-06-01 11:12:28 +10:00
Brendan Macmillan 19ddbfeca9 Stop warning on fgets, complex version 2013-06-01 11:03:15 +10:00
Stephen Dolan 4fed6763fc Squash a warning on some GCC versions 2013-05-31 12:15:58 +01:00
Stephen Dolan 73446a9cce Support for printing object keys in sorted order.
No command-line option to enable this yet. See #79.
2013-05-29 11:47:12 +01:00
Stephen Dolan dcf1ac0d1f Merge pull request #135 from 13ren/locfile_bugfix
Locfile bugfix
2013-05-29 03:38:15 -07:00
Stephen Dolan 364c58d13f Merge pull request #130 from 13ren/libload_2
libload_2 (update to pull request #126, for issue  #112)
2013-05-29 03:37:36 -07:00
Brendan Macmillan 8cfe11e4e2 Bugfix multiline off-by-one (locfile.c) 2013-05-29 15:23:08 +10:00
Brendan Macmillan 40378a18f7 locfile.h -> locfile.h + locfile.c
clean up includes of a few files
2013-05-29 15:17:01 +10:00
Brendan Macmillan 7fb5d8c973 Hack bugfix for multiline off-by-one (locfile.c) 2013-05-29 15:16:45 +10:00
Brendan Macmillan 6e373942e5 Load library from ~/.jq 2013-05-29 15:05:40 +10:00
Stephen Dolan f0b982795c Make jq --version report an actual git revision.
Closes #129.
2013-05-24 23:35:38 +01:00
Stephen Dolan cbd422d56e Merge pull request #133 from nicowilliams/option_argfile-rebase0
Add --argfile variant of --arg (issue #117)
2013-05-24 04:13:45 -07:00
Nicolas Williams 03598bb5d6 Add --argfile variant of --arg (issue #117)
This is useful when one has a database (in JSON form) to query using jq
input data.

    % echo '{"a":1, "c":5}' > db.json
    % echo '"c"'|./jq --argfile f /tmp/a '$f[.]'
    5
    % echo '"a"'|./jq --argfile f /tmp/a '$f[.]'
    1
    % echo '"b"'|./jq --argfile f /tmp/a '$f[.]'
    null
    %
2013-05-23 13:52:06 -05:00
Stephen Dolan 983a53a643 'make clean' won't delete jq.1 if it can't be rebuilt.
See #131
2013-05-23 19:20:19 +01:00
139 changed files with 142534 additions and 3520 deletions

No files matched your search

+26 -7
View File
@@ -1,28 +1,47 @@
*.o
*.a
*.lo
*.la
*.lai
*.so
*.so.*
*~
.*.sw[a-p]
tags
jq
!tests/modules/lib/jq/
jq.1
# Something delightfully recursive happens otherwise
docs/content/2.download/source/*
# Autogenerated
lexer.c
lexer.h
parser.c
parser.h
# Autotools junk
.libs
.deps
libtool
*.log
stamp-h1
config.log
config.status
autom4te.cache
config.h
INSTALL
Makefile
jq-*.tar.gz
configure
aclocal.m4
Makefile.in
version.h
.remake-version-h
config.cache
*.rpm
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
tests/*.trs
cscope.in.out
cscope.out
cscope.po.out
+53
View File
@@ -0,0 +1,53 @@
sudo: false
language: c
compiler:
- gcc
- clang
matrix:
include:
- compiler: gcc
env: COVERAGE="--disable-valgrind --enable-gcov"
addons:
apt:
packages:
- libonig-dev
- valgrind
before_install:
- rm lexer.h lexer.c parser.h parser.c
install:
- bundle install --gemfile=docs/Gemfile
- wget http://ftp.debian.org/debian/pool/main/b/bison/bison_3.0.2.dfsg-2_amd64.deb
- ar p bison_3.0.2.dfsg-2_amd64.deb data.tar.xz | tar xJ
- if [ -n "$COVERAGE" ]; then pip install --user cpp-coveralls; fi
before_script:
- autoreconf -i
- ./configure
YACC="usr/bin/bison -y"
$COVERAGE
script:
- make -j4 BISON_PKGDATADIR=$(pwd)/usr/share/bison
- make check -j4
after_script:
- |
if [ -n "$COVERAGE" ]; then
rm -rf .libs usr # don't care about coverage for libjq and bison
coveralls -e lexer.c -e parser.c -e jv_dtoa.c --gcov-options '\-lp'
fi
after_failure:
- cat test-suite.log
- cat tests/*.log
notifications:
email: false
+70 -3
View File
@@ -1,6 +1,73 @@
Created By:
Stephen Dolan <mu@netsoc.tcd.ie>
Contributions by
Anthony Shortland <anthony.shortland@me.com> - rpmbuild target
Lee Thompson <stagr.lee@gmail.com> - autoconf stuff
Maintained by:
Nicolas Williams <nico@cryptonector.com>
William Langford <wlangfor@gmail.com>
David Tolnay <dtolnay@gmail.com>
Contributions by:
Andrew Rodland <andrew@cleverdomain.org> - bug fixes
Ankur <ankz.kothari@gmail.com> - bug fixes
Anthony Shortland <anthony.shortland@me.com> - rpmbuild target
Brendan Macmillan <melbourne.research@gmail.com> - bug fixes, load library from ~/.jq
David R. MacIver <david@drmaciver.com> - bug fixes
David Tolnay <dtolnay@gmail.com> - destructuring, build improvements
Filippo Giunchedi <fgiunchedi@gmail.com> - bug fixes
Filippo Valsorda <filippo.valsorda@gmail.com> - recursive object merge (`*`)
Jack Pearkes <jackpearkes@gmail.com> - update tutorial
Jingwen Owen Ou <jingweno@gmail.com> - jqplay.org and link to it
Joe Littlejohn <joe.littlejohn@nokia.com> - bug fixes
Juan Guerrero <juan.guerrero.lozano@gmail.com> - bug fixes
Kenny Shen <kenny.shen@zalora.com> - doc fixes
Lee Thompson <stagr.lee@gmail.com> - autoconf stuff
Markus Lanthaler <mark_lanthaler@gmx.net> - doc fixes
Michael Daines <michael@mdaines.com> - add sqrt; doc fixes
Mike McCabe <mccabe@archive.org> - math (libm) functions
Nicolas Pouillard <nicolas.pouillard@gmail.com> - add tests
Nicolas Williams <nico@cryptonector.com> - library-fication, autoconf stuff, exception handling, various
Peter van Dijk <peter@7bits.nl> - doc fixes
Philipp Hagemeister <phihag@phihag.de> - doc fixes
polyester <paul@cleanclothes.org> - automake version update
Rémy Léone <remy.leone@gmail.com> - add .travis.yml
Ryoichi KATO <ryo1kato@gmail.com> - doc fixes
Santiago Lapresta <santiago.lapresta@gmail.com> - join, arrays, all, any, other filters
pkoppstein <pkoppstein@gmail.com> - various builtins, improvements
13ren <melbourne.research@gmail.com>
Aaron Peschel <apeschel@zendesk.com>
Adam Lindberg <hello@alind.io>
Alex Chamberlain <alex@alexchamberlain.co.uk>
Andrew O'Brien <obrien.andrew@gmail.com> - docs build
Assaf Gordon <assafgordon@gmail.com> - error handling
cdnbacon <mike@busbud.com>
Charles Merriam <charles.merriam@gmail.com>
Colin von Heuring <colin@janrain.com>
Damian Gryski <damian@gryski.com>
David Haguenauer <ml@kurokatta.org>
Doug Luce <doug@github.con.com> - build
Eiichi Sato <sato.eiichi@gmail.com>
Hanfei Shen <qqshfox@gmail.com>
Ian Miell <ian.miell@gmail.com>
i <isomorphisms@sdf.org>
James Andariese <james.andariese@locationlabs.com> - Dockerfile
jkleint <jkleint@gmail.com>
Joel Purra <code+github@joelpurra.com>
Kim De Mey <kim.demey@gmail.com> - build
Kim Toms <kim.toms@bplglobal.net>
LCD 47 <lcd047@gmail.com>
Lee Thompson <thompson@dtosolutions.com> - rpm
Marc Abramowitz <marc@marc-abramowitz.com>
Marc Bruggmann <marcbr@spotify.com>
Maxime Biais <maxime.biais@gmail.com> - build
Mike Fletcher <john.m.fletcher@bankofamerica.com>
Sebastian Freundt <freundt@ga-group.nl> - build
Shay Elkin <shay@everything.me>
Simon Elsbrock <simon@iodev.org> - Debian
Stefan Seemayer <stefan@seemayer.de>
Stephen Roantree <stroantree@gmail.com>
Stephen Shaw <stesh@netsoc.tcd.ie>
Steven Maude <StevenMaude@users.noreply.github.com>
Steven Penny <svnpenn@gmail.com> - Windows bug fixes
tal@whatexit.org <tal@whatexit.org>
Travis Gockel <travis@gockelhut.com>
Zhiming Wang <zmwangx@gmail.com>
+1 -1
View File
@@ -25,7 +25,7 @@ jq's documentation (everything found under the docs/ subdirectory in
the source tree) is licensed under the Creative Commons CC BY 3.0
license, which can be found at:
http://creativecommons.org/licenses/by/3.0/
https://creativecommons.org/licenses/by/3.0/
The documentation website includes a copy of Twitter's Boostrap and
relies on Bonsai, Liquid templates and various other projects, look
+1349
View File
File diff suppressed because it is too large. Load diff
+50
View File
@@ -0,0 +1,50 @@
FROM debian:8
COPY . /app
# get dependencies, build, and remove anything we don't need for running jq.
# valgrind seems to have trouble with pthreads TLS so it's off.
RUN apt-get update && \
apt-get install -y \
build-essential \
autoconf \
libtool \
git \
bison \
flex \
ruby \
wget \
ruby-dev && \
wget http://www.geocities.jp/kosako3/oniguruma/archive/onig-5.9.6.tar.gz && \
sha512sum onig-5.9.6.tar.gz | grep 4a181ea6f0e1a018bbaf6c87e666dfffd1ef4b8f5dcead07fa0b6564a76174e7e01854173924668433ae74c455dbced6a0e1b43e9066f0499b4a57e855e1a2b2 && \
tar zxvf onig-5.9.6.tar.gz && \
(cd onig-5.9.6 && \
./configure --prefix=/usr/local && \
make && \
make install ) && \
gem install bundler && \
(cd /app/docs && bundle install) && \
(cd /app && \
autoreconf -i && \
./configure --disable-valgrind --enable-all-static --prefix=/usr/local && \
make -j8 && \
make check && \
make install && \
make distclean ) && \
(cd onig-5.9.6 && \
make uninstall ) && \
apt-get purge -y \
build-essential \
autoconf \
libtool \
bison \
git \
flex \
ruby \
ruby-dev && \
apt-get autoremove -y && \
rm -rf onig-5.9.6 && \
rm -rf /var/lib/apt/lists/* /var/lib/gems
ENTRYPOINT ["/usr/local/bin/jq"]
+105 -30
View File
@@ -1,48 +1,100 @@
### C source files to be built and distributed.
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.h lexer.l
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 \
jq_test.c ${JQ_INCS}
LIBJQ_INCS = jq_parser.h builtin.h bytecode.h compile.h exec_stack.h \
libm.h jv_alloc.h jv_dtoa.h jv_unicode.h locfile.h \
opcode_list.h parser.y jv_utf8_tables.h lexer.l util.h linker.h
LIBJQ_SRC = locfile.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_file.c \
jv_alloc.c jq_test.c util.c linker.c ${LIBJQ_INCS}
### C build options
AM_CFLAGS = -Wextra -Wall -Wno-missing-field-initializers \
-Wno-unused-parameter -Wno-unused-function
ACLOCAL_AMFLAGS = -I config/m4
### Generating the lexer and parser
# While there is some autoconf macro support for lex/flex, it doesn't support
# header file creation so we'll use good old make
BUILT_SOURCES = lexer.h lexer.c parser.h parser.c
if MAINTAINER_MODE
BUILT_SOURCES = lexer.h lexer.c parser.h parser.c version.h
lexer.c: lexer.l
flex -o lexer.c --header-file=lexer.h $<
$(AM_V_LEX) flex -o lexer.c --header-file=lexer.h $<
lexer.h: lexer.c
else
BUILT_SOURCES =
.y.c:
$(AM_V_YACC) echo "NOT building parser.c!"
.l.c:
$(AM_V_LEX) echo "NOT building lexer.c!"
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
### libjq
lib_LTLIBRARIES = libjq.la
libjq_la_SOURCES = ${LIBJQ_SRC}
libjq_la_LIBADD = -lm
libjq_la_LDFLAGS = -export-symbols-regex '^j[qv]_' -version-info 1:4:0
include_HEADERS = jv.h jq.h
### Running tests under Valgrind
if ENABLE_VALGRIND
NO_VALGRIND =
else
NO_VALGRIND = 1
endif
### Code coverage with gcov
if ENABLE_GCOV
AM_CFLAGS += --coverage --no-inline
endif
### Error injection for testing
if ENABLE_ERROR_INJECTION
lib_LTLIBRARIES += libinject_errors.la
libinject_errors_la_SOURCES = inject_errors.c
libinject_errors_la_LIBADD = -ldl
libinject_errors_la_LDFLAGS = -module
endif
### Building the jq binary
main.c: config.h
# Remake the version.h header file if, and only if, the git ID has changed
.PHONY: .FORCE
.FORCE:
generate_ver = ver="`{ $(srcdir)/scripts/version || echo '$(VERSION)' ; } | sed 's/.*/\#define JQ_VERSION \"&\"/'`"
.remake-version-h: .FORCE
@ $(generate_ver); test "x`cat version.h 2>/dev/null`" = "x$$ver" || touch .remake-version-h
version.h: .remake-version-h
$(AM_V_GEN) $(generate_ver); echo "$$ver" > $@
main.c: version.h
bin_PROGRAMS = jq
jq_SOURCES = ${JQ_SRC} main.c
jq_SOURCES = main.c version.h
jq_LDFLAGS = -static-libtool-libs
jq_LDADD = libjq.la -lm
if ENABLE_ALL_STATIC
jq_LDFLAGS += -all-static
endif
### Tests (make check)
TESTS = tests/all.test
TEST_LOG_COMPILER = ${srcdir}/tests/run
TESTS = tests/mantest tests/jqtest tests/onigtest tests/shtest
TESTS_ENVIRONMENT = NO_VALGRIND=$(NO_VALGRIND)
### Building the manpage
@@ -56,20 +108,23 @@ man_MANS = jq.1
.PHONY: real_docs
if ENABLE_DOCS
jq.1: $(srcdir)/docs/content/3.manual/manual.yml
( cd ${abs_srcdir}/docs; '$(BUNDLER)' exec rake manpage ) > $@ || { rm -f $@; false; }
$(AM_V_GEN) ( cd ${abs_srcdir}/docs; '$(BUNDLER)' exec rake manpage ) > $@ || { rm -f $@; false; }
jq.1.prebuilt: jq.1
$(AM_V_GEN) cp $^ $@ || { rm -f $@; false; }
jq.1.default: $(srcdir)/docs/default_manpage.md
( cd ${abs_srcdir}/docs; '$(BUNDLER)' exec rake manpage_default ) > $@ || { rm -f $@; false; }
real_docs: jq.1
if cmp jq.1 $(srcdir)/jq.1.default > /dev/null; then\
$(AM_V_GEN) ( cd ${abs_srcdir}/docs; '$(BUNDLER)' exec rake manpage_default ) > $@ || { rm -f $@; false; }
real_docs: jq.1 jq.1.prebuilt
@if cmp jq.1 $(srcdir)/jq.1.default > /dev/null; then\
rm -f jq.1; $(MAKE) $(AM_MAKEFLAGS) jq.1;\
fi
else
jq.1: $(srcdir)/jq.1.default
cp $^ $@
jq.1: $(srcdir)/jq.1.prebuilt
$(AM_V_GEN) cp $^ $@
real_docs:
@echo "Ruby dependencies not found, cannot build manpage." > /dev/stderr
@echo "Follow the instructions in docs/README.md to install them" > /dev/stderr
@echo "and then rerun ./configure" > /dev/stderr
@echo "A pre-built, possibly out-of-date manpage used." > /dev/stderr
false
endif
@@ -93,24 +148,33 @@ DOC_FILES = docs/content docs/public docs/templates docs/site.yml \
# 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 = config.h.in $(BUILT_SOURCES) $(man_MANS) $(TESTS) \
$(TEST_LOG_COMPILER) gen_utf8_tables.py jq.spec \
$(DOC_FILES)
EXTRA_DIST = $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) jq.spec \
$(DOC_FILES) scripts/version parser.h parser.c lexer.h \
lexer.c tests/onig.supp tests/torture/input0.json \
tests/modules/.jq tests/modules/a.jq tests/modules/b/b.jq \
tests/modules/c/c.jq tests/modules/c/d.jq \
tests/modules/lib/jq/e/e.jq tests/modules/lib/jq/f.jq \
tests/setup tests/jq.test tests/onig.test \
tests/modules/data.json \
tests/modules/syntaxerror/syntaxerror.jq \
tests/modules/test_bind_order.jq \
tests/modules/test_bind_order0.jq \
tests/modules/test_bind_order1.jq \
tests/modules/test_bind_order2.jq \
jq.1.prebuilt
# 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 COPYING AUTHORS README
releasetag:
git tag -s "jq-$$(cat VERSION)" -m "jq release $$(cat VERSION)"
RELEASE ?= 1
rpm: jq
rpm: dist jq.spec
@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 /usr" --define "myver $$(cat VERSION)" --define "myrel ${RELEASE}" rpm/SOURCES/jq-$$(cat VERSION).tar.gz
cp jq-$(VERSION).tar.gz rpm/SOURCES/
rpmbuild -tb --define "_topdir ${PWD}/rpm" --define "_prefix /usr" --define "myver $(VERSION)" --define "myrel ${RELEASE}" rpm/SOURCES/jq-$(VERSION).tar.gz
find rpm/RPMS/ -name "*.rpm" -exec mv {} ./ \;
rm -rf rpm
@@ -119,5 +183,16 @@ dist-clean-local:
# Not sure why this doesn't get cleaned up automatically, guess
# automake used to man pages which are hand coded?
clean-local:
# 'make clean' doesn't delete the manpage if it can't be rebuilt
clean-local-docs:
if ENABLE_DOCS
rm -f jq.1
endif
clean-local-gcov:
rm -f *.gcno *.gcda *.gcov
clean-local: clean-local-docs clean-local-gcov
rm -f version.h .remake-version-h
.PHONY: clean-local-docs clean-local-gcov
+1646
View File
File diff suppressed because it is too large. Load diff
+88
View File
@@ -0,0 +1,88 @@
Release history
* jq version 1.0 was released on Sun Oct 21 2012
* jq version 1.1 was released on Sun Oct 21 2012
* jq version 1.2 was released on Thu Dec 20 2012
* jq version 1.3 was released on Sun May 19 2013
* jq version 1.4 was released on Mon Jun 9 2014
New features in 1.5 since 1.4:
- regular expressions (with Oniguruma)
- a library/module system
- many new builtins
- datetime builtins
- math builtins
- regexp-related builtins
- stream-related builtins (e.g., all/1, any/1)
- minimal I/O builtins (`inputs`, `debug`)
- new syntactic features, including:
- destructuring (`. as [$first, $second] | ...`)
- try/catch, generalized `?` operator, and label/break
- `foreach`
- multiple definitions of a function with different numbers of
arguments
- command-line arguments
- --join-lines / -j for raw output
- --argjson and --slurpfile
- --tab and --indent
- --stream (streaming JSON parser)
- --seq (RFC7464 JSON text sequence)
- --run-tests improvements
- optimizations:
- tail-call optimization
- reduce and foreach no longer leak a reference to .
New features in 1.4 since 1.3:
- command-line arguments
- jq --arg-file variable file
- jq --unbuffered
- jq -e / --exit-status (set exit status based on outputs)
- jq -S / --sort-keys (now jq no longer sorts object keys by
default
- syntax
- .. -> like // in XPath (recursive traversal)
- question mark (e.g., .a?) to suppress errors
- ."foo" syntax (equivalent to .["foo"])
- better error handling for .foo
- added % operator (modulo)
- allow negation without requiring extra parenthesis
- more function arguments (up to six)
- filters:
- any, all
- iterables, arrays, objects, scalars, nulls, booleans, numbers,
strings, values
- string built-ins:
- split
- join (join an array of strings with a given separator string)
- ltrimstr, rtrimstr
- startswith, endswith
- explode, implode
- fromjson, tojson
- index, rindex, indices
- math functions
- floor, sqrt, cbrt, etetera (depends on what's available from libm)
- libjq -- a C API interface to jq's JSON representation and for
running jq programs from C applications
+49 -8
View File
@@ -4,20 +4,61 @@ jq
jq is a command-line JSON processor.
If you want to learn to use jq, read the documentation at
[http://stedolan.github.com/jq](http://stedolan.github.com/jq). This
[https://stedolan.github.io/jq](https://stedolan.github.io/jq). This
documentation is generated from the docs/ folder of this repository.
You can also try it online at [jqplay.org](https://jqplay.org).
If you want to hack on jq, feel free, but be warned that its internals
are not well-documented at the moment. Bring a hard hat and a
shovel. Also, read the wiki: http://github.com/stedolan/jq/wiki
shovel. Also, read the wiki: https://github.com/stedolan/jq/wiki
To build jq, run
Source tarball and built executable releases can be found on the
homepage and on the github release page, https://github.com/stedolan/jq/releases
If you're building directly from the latest git, you'll need flex,
bison (3.0 or newer), libtool, make, and autoconf installed. To get
regexp support you'll also need to install Oniguruma (note that jq's
tests require regexp support to pass). To build, run:
autoreconf -i # if building from git
./configure
make
sudo make install (optionally)
make -j8
make check
If you've just checked out the latest version from git (rather than
using a released source tarball) then you'll need to run this first:
To build without bison or flex, add `--disable-maintainer-mode` to the
./configure invocation:
autoreconf
./configure --disable-maintainer-mode
(Developers must not use `--disable-maintainer-mode`, not when making
changes to the jq parser and/or lexer.)
To build a statically linked version of jq, run:
make LDFLAGS=-all-static
After make finishes, you'll be able to use `./jq`. You can also
install it using:
sudo make install
If you're not using the latest git version but instead building a
released tarball (available on the website), then you won't need to
run `autoreconf` (and shouldn't), and you won't need flex or bison.
To cross-compile for OS X and Windows, see docs/Rakefile's build task
and scripts/crosscompile. You'll need a cross-compilation environment,
such as Mingw for cross-compiling for Windows.
Cross-compilation requires a clean workspace, then:
# git clean ...
autoreconf -i
./configure
make distclean
scripts/crosscompile <name-of-build> <configure-options>
Use the --host= and --target= ./configure options to select a
cross-compilation environment. See also the wiki.
Send questions to https://stackoverflow.com/questions/tagged/jq or to the #jq channel (http://irc.lc/freenode/%23jq/) on Freenode (https://webchat.freenode.net/).
Vendored
+1255
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+550
View File
@@ -0,0 +1,550 @@
# This file was generated by Autom4te Thu Apr 10 10:06:43 UTC 2014.
# It contains the lists of macros which have been traced.
# It can be safely removed.
@request = (
bless( [
'0',
1,
[
'/usr/share/autoconf'
],
[
'/usr/share/autoconf/autoconf/autoconf.m4f',
'-',
'/usr/share/aclocal-1.14/internal/ac-config-macro-dirs.m4',
'/usr/share/aclocal/argz.m4',
'/usr/share/aclocal/libtool.m4',
'/usr/share/aclocal/ltdl.m4',
'/usr/share/aclocal/ltoptions.m4',
'/usr/share/aclocal/ltsugar.m4',
'/usr/share/aclocal/ltversion.m4',
'/usr/share/aclocal/lt~obsolete.m4',
'/usr/share/aclocal-1.14/amversion.m4',
'/usr/share/aclocal-1.14/ar-lib.m4',
'/usr/share/aclocal-1.14/auxdir.m4',
'/usr/share/aclocal-1.14/cond.m4',
'/usr/share/aclocal-1.14/depend.m4',
'/usr/share/aclocal-1.14/depout.m4',
'/usr/share/aclocal-1.14/init.m4',
'/usr/share/aclocal-1.14/install-sh.m4',
'/usr/share/aclocal-1.14/lead-dot.m4',
'/usr/share/aclocal-1.14/maintainer.m4',
'/usr/share/aclocal-1.14/make.m4',
'/usr/share/aclocal-1.14/missing.m4',
'/usr/share/aclocal-1.14/options.m4',
'/usr/share/aclocal-1.14/prog-cc-c-o.m4',
'/usr/share/aclocal-1.14/runlog.m4',
'/usr/share/aclocal-1.14/sanity.m4',
'/usr/share/aclocal-1.14/silent.m4',
'/usr/share/aclocal-1.14/strip.m4',
'/usr/share/aclocal-1.14/substnot.m4',
'/usr/share/aclocal-1.14/tar.m4',
'config/m4/check-math-func.m4',
'config/m4/find-func-no-libs.m4',
'config/m4/find-func-no-libs2.m4',
'config/m4/find-func.m4',
'config/m4/misc.m4',
'configure.ac'
],
{
'AM_MAINTAINER_MODE' => 1,
'AC_LIBLTDL_CONVENIENCE' => 1,
'AC_LTDL_ENABLE_INSTALL' => 1,
'LT_PATH_NM' => 1,
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
'_LT_PROG_ECHO_BACKSLASH' => 1,
'LT_SYS_DLOPEN_SELF' => 1,
'_LTDL_SETUP' => 1,
'LT_SYS_DLSEARCH_PATH' => 1,
'AC_LIBTOOL_F77' => 1,
'm4_pattern_forbid' => 1,
'm4_pattern_allow' => 1,
'LT_SYS_MODULE_PATH' => 1,
'_LT_LIBOBJ' => 1,
'AC_CHECK_LIBM' => 1,
'_LT_PATH_TOOL_PREFIX' => 1,
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
'AC_FIND_FUNC' => 1,
'LT_SYS_DLOPEN_DEPLIBS' => 1,
'AC_LIB_LTDL' => 1,
'gl_FUNC_ARGZ' => 1,
'LT_LIB_DLLOAD' => 1,
'AM_ENABLE_SHARED' => 1,
'AC_PROG_LD_RELOAD_FLAG' => 1,
'AC_LIBTOOL_OBJDIR' => 1,
'_LT_PROG_LTMAIN' => 1,
'LTSUGAR_VERSION' => 1,
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
'AC_LIBTOOL_RC' => 1,
'LT_LANG' => 1,
'_AM_PROG_CC_C_O' => 1,
'LTDL_INIT' => 1,
'_LT_COMPILER_BOILERPLATE' => 1,
'AM_PROG_INSTALL_STRIP' => 1,
'LTOPTIONS_VERSION' => 1,
'AC_LIBTOOL_DLOPEN' => 1,
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'_LT_COMPILER_OPTION' => 1,
'_AM_SET_OPTION' => 1,
'_LT_AC_LANG_GCJ_CONFIG' => 1,
'LT_CMD_MAX_LEN' => 1,
'AM_SET_DEPDIR' => 1,
'AC_PROG_LD_GNU' => 1,
'AC_PATH_MAGIC' => 1,
'_LT_CC_BASENAME' => 1,
'AM_MISSING_PROG' => 1,
'LT_OUTPUT' => 1,
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
'AC_PATH_TOOL_PREFIX' => 1,
'LT_INIT' => 1,
'_LT_AC_LANG_F77_CONFIG' => 1,
'AC_WITH_LTDL' => 1,
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
'AC_LIBTOOL_PROG_CC_C_O' => 1,
'_LT_AC_TRY_DLOPEN_SELF' => 1,
'LT_LIB_M' => 1,
'LT_SYS_MODULE_EXT' => 1,
'AC_LTDL_DLSYM_USCORE' => 1,
'AC_DEFUN' => 1,
'_AC_PROG_LIBTOOL' => 1,
'_LT_PROG_F77' => 1,
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
'AM_SILENT_RULES' => 1,
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
'AM_DEP_TRACK' => 1,
'AM_PROG_LD' => 1,
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
'AC_LTDL_SHLIBPATH' => 1,
'AM_RUN_LOG' => 1,
'AC_DISABLE_STATIC' => 1,
'AU_DEFUN' => 1,
'include' => 1,
'_LT_AC_SYS_COMPILER' => 1,
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'LT_AC_PROG_GCJ' => 1,
'AC_LIBTOOL_COMPILER_OPTION' => 1,
'AC_LTDL_SYMBOL_USCORE' => 1,
'AC_LIBTOOL_PICMODE' => 1,
'LT_AC_PROG_SED' => 1,
'_LT_AC_FILE_LTDLL_C' => 1,
'LT_AC_PROG_EGREP' => 1,
'AC_PROG_LD' => 1,
'_AM_PROG_TAR' => 1,
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
'_m4_warn' => 1,
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'_LT_AC_CHECK_DLFCN' => 1,
'LT_SUPPORTED_TAG' => 1,
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
'AC_LIBTOOL_CONFIG' => 1,
'_LT_AC_LANG_F77' => 1,
'LTDL_INSTALLABLE' => 1,
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
'AC_LIBTOOL_DLOPEN_SELF' => 1,
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
'_LT_LINKER_OPTION' => 1,
'LTOBSOLETE_VERSION' => 1,
'AC_LTDL_SYSSEARCHPATH' => 1,
'AC_ENABLE_SHARED' => 1,
'AM_AUX_DIR_EXPAND' => 1,
'_LT_AC_TAGVAR' => 1,
'LT_AC_PROG_RC' => 1,
'LT_FUNC_DLSYM_USCORE' => 1,
'LT_SYS_SYMBOL_USCORE' => 1,
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
'LTDL_CONVENIENCE' => 1,
'AC_PROG_EGREP' => 1,
'AM_PROG_AR' => 1,
'AC_ENABLE_FAST_INSTALL' => 1,
'AX_PROG_BISON_VERSION' => 1,
'_LT_WITH_SYSROOT' => 1,
'AC_FIND_FUNC_NO_LIBS2' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_LTDL_OBJDIR' => 1,
'AC_PROG_LIBTOOL' => 1,
'_LT_AC_LOCK' => 1,
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
'AC_LTDL_SHLIBEXT' => 1,
'upcase' => 1,
'LT_PROG_GCJ' => 1,
'AX_COMPARE_VERSION' => 1,
'AC_LTDL_DLLIB' => 1,
'_LT_AC_LANG_RC_CONFIG' => 1,
'AC_CONFIG_MACRO_DIR' => 1,
'_LT_PROG_CXX' => 1,
'AM_PROG_CC_C_O' => 1,
'AM_PROG_NM' => 1,
'LT_PATH_LD' => 1,
'_AM_IF_OPTION' => 1,
'_AM_MANGLE_OPTION' => 1,
'AM_DISABLE_SHARED' => 1,
'm4_include' => 1,
'_AM_SET_OPTIONS' => 1,
'_LT_AC_SYS_LIBPATH_AIX' => 1,
'AM_ENABLE_STATIC' => 1,
'AC_DEFUN_ONCE' => 1,
'_AM_AUTOCONF_VERSION' => 1,
'AC_DEPLIBS_CHECK_METHOD' => 1,
'AM_PROG_LIBTOOL' => 1,
'AC_DISABLE_SHARED' => 1,
'AM_SUBST_NOTMAKE' => 1,
'_LT_AC_PROG_CXXCPP' => 1,
'AC_LTDL_PREOPEN' => 1,
'_LT_LINKER_BOILERPLATE' => 1,
'AC_LIBTOOL_SETUP' => 1,
'AC_CHECK_MATH_FUNC' => 1,
'AM_SANITY_CHECK' => 1,
'_LT_AC_LANG_CXX' => 1,
'_LT_AC_TAGCONFIG' => 1,
'LT_WITH_LTDL' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
'AC_LIBTOOL_FC' => 1,
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AM_MISSING_HAS_RUN' => 1,
'AM_PROG_INSTALL_SH' => 1,
'AC_LIBTOOL_WIN32_DLL' => 1,
'AC_ENABLE_STATIC' => 1,
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'_LT_AC_SHELL_INIT' => 1,
'AM_SET_LEADING_DOT' => 1,
'LTVERSION_VERSION' => 1,
'AC_LIBLTDL_INSTALLABLE' => 1,
'LT_PROG_RC' => 1,
'_AM_DEPENDENCIES' => 1,
'LT_PROG_GO' => 1,
'AC_LIBTOOL_GCJ' => 1,
'gl_PREREQ_ARGZ' => 1,
'_AM_CONFIG_MACRO_DIRS' => 1,
'AC_FIND_FUNC_NO_LIBS' => 1,
'AC_LIBTOOL_CXX' => 1,
'AM_DISABLE_STATIC' => 1,
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AC_LIBTOOL_LINKER_OPTION' => 1,
'AM_CONDITIONAL' => 1,
'_LT_AC_LANG_GCJ' => 1,
'AC_PROG_NM' => 1,
'AC_DISABLE_FAST_INSTALL' => 1,
'_LT_AC_LANG_CXX_CONFIG' => 1,
'_LT_AC_LANG_C_CONFIG' => 1,
'AM_MAKE_INCLUDE' => 1,
'_LT_PROG_FC' => 1,
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1
}
], 'Autom4te::Request' ),
bless( [
'1',
1,
[
'/usr/share/autoconf'
],
[
'/usr/share/autoconf/autoconf/autoconf.m4f',
'aclocal.m4',
'configure.ac'
],
{
'AC_FC_PP_DEFINE' => 1,
'AC_INIT' => 1,
'AM_XGETTEXT_OPTION' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
'AM_PROG_CC_C_O' => 1,
'include' => 1,
'AC_LIBSOURCE' => 1,
'AM_PROG_FC_C_O' => 1,
'AM_GNU_GETTEXT' => 1,
'AC_CANONICAL_HOST' => 1,
'AM_POT_TOOLS' => 1,
'AM_NLS' => 1,
'_AM_MAKEFILE_INCLUDE' => 1,
'AM_CONDITIONAL' => 1,
'AH_OUTPUT' => 1,
'_AM_COND_ELSE' => 1,
'_AM_COND_IF' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AM_SILENT_RULES' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_PROG_LIBTOOL' => 1,
'AM_PROG_MOC' => 1,
'AM_PROG_CXX_C_O' => 1,
'AC_CONFIG_LINKS' => 1,
'm4_sinclude' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AM_PROG_AR' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_SUBST_TRACE' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'AM_MAKEFILE_INCLUDE' => 1,
'AM_EXTRA_RECURSIVE_TARGETS' => 1,
'AC_CANONICAL_SYSTEM' => 1,
'AM_PROG_MKDIR_P' => 1,
'AC_SUBST' => 1,
'AM_PATH_GUILE' => 1,
'LT_INIT' => 1,
'sinclude' => 1,
'AM_PROG_F77_C_O' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'_LT_AC_TAGCONFIG' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'm4_pattern_forbid' => 1,
'm4_pattern_allow' => 1,
'AC_FC_PP_SRCEXT' => 1,
'AC_FC_FREEFORM' => 1,
'AC_CANONICAL_BUILD' => 1,
'LT_SUPPORTED_TAG' => 1,
'AM_ENABLE_MULTILIB' => 1,
'_m4_warn' => 1,
'AC_CONFIG_FILES' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'AC_FC_SRCEXT' => 1,
'AC_CANONICAL_TARGET' => 1,
'_AM_COND_ENDIF' => 1,
'm4_include' => 1,
'AM_MAINTAINER_MODE' => 1,
'AC_REQUIRE_AUX_FILE' => 1
}
], 'Autom4te::Request' ),
bless( [
'2',
1,
[
'/usr/share/autoconf'
],
[
'/usr/share/autoconf/autoconf/autoconf.m4f',
'-',
'/usr/share/aclocal-1.14/internal/ac-config-macro-dirs.m4',
'/usr/share/aclocal/argz.m4',
'/usr/share/aclocal/ltdl.m4',
'/usr/share/aclocal-1.14/amversion.m4',
'/usr/share/aclocal-1.14/ar-lib.m4',
'/usr/share/aclocal-1.14/auxdir.m4',
'/usr/share/aclocal-1.14/cond.m4',
'/usr/share/aclocal-1.14/depend.m4',
'/usr/share/aclocal-1.14/depout.m4',
'/usr/share/aclocal-1.14/init.m4',
'/usr/share/aclocal-1.14/install-sh.m4',
'/usr/share/aclocal-1.14/lead-dot.m4',
'/usr/share/aclocal-1.14/maintainer.m4',
'/usr/share/aclocal-1.14/make.m4',
'/usr/share/aclocal-1.14/missing.m4',
'/usr/share/aclocal-1.14/options.m4',
'/usr/share/aclocal-1.14/prog-cc-c-o.m4',
'/usr/share/aclocal-1.14/runlog.m4',
'/usr/share/aclocal-1.14/sanity.m4',
'/usr/share/aclocal-1.14/silent.m4',
'/usr/share/aclocal-1.14/strip.m4',
'/usr/share/aclocal-1.14/substnot.m4',
'/usr/share/aclocal-1.14/tar.m4',
'config/m4/check-math-func.m4',
'config/m4/find-func-no-libs.m4',
'config/m4/find-func-no-libs2.m4',
'config/m4/find-func.m4',
'config/m4/libtool.m4',
'config/m4/ltoptions.m4',
'config/m4/ltsugar.m4',
'config/m4/ltversion.m4',
'config/m4/lt~obsolete.m4',
'config/m4/misc.m4',
'configure.ac'
],
{
'AC_LIBTOOL_DLOPEN_SELF' => 1,
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
'_LT_LINKER_OPTION' => 1,
'AC_ENABLE_SHARED' => 1,
'AC_LTDL_SYSSEARCHPATH' => 1,
'LTOBSOLETE_VERSION' => 1,
'_LT_AC_TAGVAR' => 1,
'AM_AUX_DIR_EXPAND' => 1,
'LT_AC_PROG_RC' => 1,
'AC_LIBTOOL_CONFIG' => 1,
'_LT_AC_LANG_F77' => 1,
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
'LTDL_INSTALLABLE' => 1,
'_AM_PROG_TAR' => 1,
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
'_m4_warn' => 1,
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
'_LT_AC_CHECK_DLFCN' => 1,
'LT_SUPPORTED_TAG' => 1,
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
'_LT_AC_FILE_LTDLL_C' => 1,
'LT_AC_PROG_EGREP' => 1,
'AC_PROG_LD' => 1,
'_LT_AC_LANG_RC_CONFIG' => 1,
'AC_LTDL_DLLIB' => 1,
'AC_CONFIG_MACRO_DIR' => 1,
'_LT_PROG_CXX' => 1,
'AM_PROG_CC_C_O' => 1,
'AM_PROG_NM' => 1,
'LT_PATH_LD' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_LTDL_OBJDIR' => 1,
'AC_PROG_LIBTOOL' => 1,
'_LT_AC_LOCK' => 1,
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
'AC_LTDL_SHLIBEXT' => 1,
'LT_PROG_GCJ' => 1,
'upcase' => 1,
'AX_COMPARE_VERSION' => 1,
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
'LTDL_CONVENIENCE' => 1,
'AC_ENABLE_FAST_INSTALL' => 1,
'AM_PROG_AR' => 1,
'AC_PROG_EGREP' => 1,
'AX_PROG_BISON_VERSION' => 1,
'_LT_WITH_SYSROOT' => 1,
'AC_FIND_FUNC_NO_LIBS2' => 1,
'LT_FUNC_DLSYM_USCORE' => 1,
'LT_SYS_SYMBOL_USCORE' => 1,
'_LT_AC_TAGCONFIG' => 1,
'LT_WITH_LTDL' => 1,
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'AC_LIBTOOL_FC' => 1,
'AM_SUBST_NOTMAKE' => 1,
'_LT_AC_PROG_CXXCPP' => 1,
'AC_LTDL_PREOPEN' => 1,
'AC_CHECK_MATH_FUNC' => 1,
'_LT_LINKER_BOILERPLATE' => 1,
'AC_LIBTOOL_SETUP' => 1,
'AM_SANITY_CHECK' => 1,
'_LT_AC_LANG_CXX' => 1,
'AC_DEFUN_ONCE' => 1,
'AM_ENABLE_STATIC' => 1,
'_AM_AUTOCONF_VERSION' => 1,
'AM_PROG_LIBTOOL' => 1,
'AC_DEPLIBS_CHECK_METHOD' => 1,
'AC_DISABLE_SHARED' => 1,
'_AM_IF_OPTION' => 1,
'_AM_MANGLE_OPTION' => 1,
'AM_DISABLE_SHARED' => 1,
'_AM_SET_OPTIONS' => 1,
'm4_include' => 1,
'_LT_AC_SYS_LIBPATH_AIX' => 1,
'_LT_AC_LANG_GCJ' => 1,
'AC_PROG_NM' => 1,
'AC_DISABLE_FAST_INSTALL' => 1,
'_LT_AC_LANG_CXX_CONFIG' => 1,
'_LT_PROG_FC' => 1,
'AM_MAKE_INCLUDE' => 1,
'_LT_AC_LANG_C_CONFIG' => 1,
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
'gl_PREREQ_ARGZ' => 1,
'_AM_CONFIG_MACRO_DIRS' => 1,
'AC_FIND_FUNC_NO_LIBS' => 1,
'AM_DISABLE_STATIC' => 1,
'AC_LIBTOOL_CXX' => 1,
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'AC_LIBTOOL_LINKER_OPTION' => 1,
'AM_CONDITIONAL' => 1,
'_LT_AC_SHELL_INIT' => 1,
'AM_SET_LEADING_DOT' => 1,
'LTVERSION_VERSION' => 1,
'LT_PROG_RC' => 1,
'_AM_DEPENDENCIES' => 1,
'AC_LIBLTDL_INSTALLABLE' => 1,
'LT_PROG_GO' => 1,
'AC_LIBTOOL_GCJ' => 1,
'AM_MISSING_HAS_RUN' => 1,
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
'AM_PROG_INSTALL_SH' => 1,
'AC_LIBTOOL_WIN32_DLL' => 1,
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'AC_ENABLE_STATIC' => 1,
'LT_SYS_MODULE_PATH' => 1,
'_LT_PATH_TOOL_PREFIX' => 1,
'AC_CHECK_LIBM' => 1,
'_LT_LIBOBJ' => 1,
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
'LT_SYS_DLSEARCH_PATH' => 1,
'AC_LIBTOOL_F77' => 1,
'm4_pattern_forbid' => 1,
'm4_pattern_allow' => 1,
'_LT_PROG_ECHO_BACKSLASH' => 1,
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
'LT_SYS_DLOPEN_SELF' => 1,
'_LTDL_SETUP' => 1,
'AC_LIBLTDL_CONVENIENCE' => 1,
'AM_MAINTAINER_MODE' => 1,
'AC_LTDL_ENABLE_INSTALL' => 1,
'LT_PATH_NM' => 1,
'LT_LANG' => 1,
'_AM_PROG_CC_C_O' => 1,
'LTDL_INIT' => 1,
'_LT_COMPILER_BOILERPLATE' => 1,
'AM_ENABLE_SHARED' => 1,
'AC_LIBTOOL_OBJDIR' => 1,
'AC_PROG_LD_RELOAD_FLAG' => 1,
'LTSUGAR_VERSION' => 1,
'_LT_PROG_LTMAIN' => 1,
'AC_LIBTOOL_RC' => 1,
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
'gl_FUNC_ARGZ' => 1,
'LT_LIB_DLLOAD' => 1,
'AC_FIND_FUNC' => 1,
'LT_SYS_DLOPEN_DEPLIBS' => 1,
'AC_LIB_LTDL' => 1,
'AM_MISSING_PROG' => 1,
'LT_OUTPUT' => 1,
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
'AC_PATH_TOOL_PREFIX' => 1,
'LT_INIT' => 1,
'_LT_CC_BASENAME' => 1,
'_AM_SET_OPTION' => 1,
'_LT_AC_LANG_GCJ_CONFIG' => 1,
'LT_CMD_MAX_LEN' => 1,
'AM_SET_DEPDIR' => 1,
'AC_PATH_MAGIC' => 1,
'AC_PROG_LD_GNU' => 1,
'AM_PROG_INSTALL_STRIP' => 1,
'LTOPTIONS_VERSION' => 1,
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
'AC_LIBTOOL_DLOPEN' => 1,
'_LT_COMPILER_OPTION' => 1,
'AC_DISABLE_STATIC' => 1,
'AU_DEFUN' => 1,
'include' => 1,
'_LT_AC_SYS_COMPILER' => 1,
'LT_AC_PROG_GCJ' => 1,
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
'AC_LIBTOOL_COMPILER_OPTION' => 1,
'AC_LIBTOOL_PICMODE' => 1,
'AC_LTDL_SYMBOL_USCORE' => 1,
'LT_AC_PROG_SED' => 1,
'_LT_PROG_F77' => 1,
'_AC_PROG_LIBTOOL' => 1,
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
'AM_SILENT_RULES' => 1,
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
'AM_PROG_LD' => 1,
'AM_DEP_TRACK' => 1,
'AC_LTDL_SHLIBPATH' => 1,
'AM_RUN_LOG' => 1,
'AC_LIBTOOL_PROG_CC_C_O' => 1,
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
'_LT_AC_TRY_DLOPEN_SELF' => 1,
'LT_SYS_MODULE_EXT' => 1,
'LT_LIB_M' => 1,
'AC_LTDL_DLSYM_USCORE' => 1,
'AC_DEFUN' => 1,
'_LT_AC_LANG_F77_CONFIG' => 1,
'AC_WITH_LTDL' => 1,
'AC_LIBTOOL_POSTDEP_PREDEP' => 1
}
], 'Autom4te::Request' )
);
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+1199 -96
View File
File diff suppressed because it is too large. Load diff
+3 -14
View File
@@ -1,21 +1,10 @@
#ifndef BUILTIN_H
#define BUILTIN_H
#include "jq.h"
#include "bytecode.h"
#include "compile.h"
block builtins_bind(block);
typedef void (*cfunction_ptr)(void);
struct cfunction {
cfunction_ptr fptr;
const char* name;
int nargs;
};
jv cfunction_invoke(struct cfunction* function, jv input[]);
int builtins_bind(jq_state *, block*);
#endif
+58 -25
View File
@@ -3,17 +3,64 @@
#include <stdlib.h>
#include "bytecode.h"
#include "opcode.h"
#include "jv_alloc.h"
static int bytecode_operation_length(uint16_t* codeptr) {
// flags, length
#define NONE 0, 1
#define CONSTANT OP_HAS_CONSTANT, 2
#define VARIABLE (OP_HAS_VARIABLE | OP_HAS_BINDING), 3
#define GLOBAL (OP_HAS_CONSTANT | OP_HAS_VARIABLE | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4
#define BRANCH OP_HAS_BRANCH, 2
#define CFUNC (OP_HAS_CFUNC | OP_HAS_BINDING), 3
#define UFUNC (OP_HAS_UFUNC | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4
#define DEFINITION (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0
#define CLOSURE_REF_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 2
#define OP(name, imm, in, out) \
{name, #name, imm, in, out},
static const struct opcode_description opcode_descriptions[] = {
#include "opcode_list.h"
};
static const struct opcode_description invalid_opcode_description = {
-1, "#INVALID", 0, 0, 0, 0
};
const struct opcode_description* opcode_describe(opcode op) {
if ((int)op >= 0 && (int)op < NUM_OPCODES) {
return &opcode_descriptions[op];
} else {
return &invalid_opcode_description;
}
}
int bytecode_operation_length(uint16_t* codeptr) {
int length = opcode_describe(*codeptr)->length;
if (*codeptr == CALL_JQ) {
if (*codeptr == CALL_JQ || *codeptr == TAIL_CALL_JQ) {
length += codeptr[1] * 2;
}
return length;
}
static void dump_code(int indent, struct bytecode* bc) {
int pc = 0;
while (pc < bc->codelen) {
printf("%*s", indent, "");
dump_operation(bc, bc->code + pc);
printf("\n");
pc += bytecode_operation_length(bc->code + pc);
}
}
static void symbol_table_free(struct symbol_table* syms) {
jv_mem_free(syms->cfunctions);
jv_free(syms->cfunc_names);
jv_mem_free(syms);
}
void dump_disassembly(int indent, struct bytecode* bc) {
if (bc->nclosures > 0) {
printf("%*s[params: ", indent, "");
@@ -37,16 +84,6 @@ void dump_disassembly(int indent, struct bytecode* bc) {
}
}
void dump_code(int indent, struct bytecode* bc) {
int pc = 0;
while (pc < bc->codelen) {
printf("%*s", indent, "");
dump_operation(bc, bc->code + pc);
printf("\n");
pc += bytecode_operation_length(bc->code + pc);
}
}
static struct bytecode* getlevel(struct bytecode* bc, int level) {
while (level > 0) {
bc = bc->parent;
@@ -62,17 +99,17 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
printf("%s", op->name);
if (op->length > 1) {
uint16_t imm = bc->code[pc++];
if (op->op == CALL_JQ) {
if (op->op == CALL_JQ || op->op == TAIL_CALL_JQ) {
for (int i=0; i<imm+1; i++) {
uint16_t level = bc->code[pc++];
uint16_t idx = bc->code[pc++];
jv name;
if (idx & ARG_NEWCLOSURE) {
idx &= ~ARG_NEWCLOSURE;
name = jv_object_get(jv_copy(getlevel(bc,level)->subfunctions[idx]->debuginfo),
name = jv_object_get(jv_copy(getlevel(bc,level)->subfunctions[idx]->debuginfo),
jv_string("name"));
} else {
name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,level)->debuginfo),
name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,level)->debuginfo),
jv_string("params")), idx);
}
printf(" %s:%d",
@@ -96,8 +133,8 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
} else if (op->flags & OP_HAS_VARIABLE) {
uint16_t v = bc->code[pc++];
jv name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,imm)->debuginfo), jv_string("locals")), v);
printf(" $%s:%d",
jv_string_value(name),
printf(" $%s:%d",
jv_string_value(name),
v);
jv_free(name);
if (imm) {
@@ -106,16 +143,12 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
} else {
printf(" %d", imm);
}
}
}
void symbol_table_free(struct symbol_table* syms) {
jv_mem_free(syms->cfunctions);
jv_free(syms->cfunc_names);
jv_mem_free(syms);
}
}
void bytecode_free(struct bytecode* bc) {
if (!bc)
return;
jv_mem_free(bc->code);
jv_free(bc->constants);
for (int i=0; i<bc->nsubfunctions; i++)
+48 -4
View File
@@ -3,10 +3,55 @@
#include <stdint.h>
#include "jv.h"
#include "opcode.h"
#include "builtin.h"
typedef enum {
#define OP(name, imm, in, out) name,
#include "opcode_list.h"
#undef OP
} opcode;
enum {
NUM_OPCODES =
#define OP(name, imm, in, out) +1
#include "opcode_list.h"
#undef OP
};
enum {
OP_HAS_CONSTANT = 2,
OP_HAS_VARIABLE = 4,
OP_HAS_BRANCH = 8,
OP_HAS_CFUNC = 32,
OP_HAS_UFUNC = 64,
OP_IS_CALL_PSEUDO = 128,
OP_HAS_BINDING = 1024,
// NOTE: Not actually part of any op -- a pseudo-op flag for special
// handling of `break`.
OP_BIND_WILDCARD = 2048,
};
struct opcode_description {
opcode op;
const char* name;
int flags;
// length in 16-bit units
int length;
int stack_in, stack_out;
};
const struct opcode_description* opcode_describe(opcode op);
#define MAX_CFUNCTION_ARGS 10
typedef void (*cfunction_ptr)();
struct cfunction {
cfunction_ptr fptr;
const char* name;
int nargs;
};
struct symbol_table {
struct cfunction* cfunctions;
int ncfunctions;
@@ -39,10 +84,9 @@ struct bytecode {
};
void dump_disassembly(int, struct bytecode* code);
void dump_code(int, struct bytecode* code);
void dump_operation(struct bytecode* bc, uint16_t* op);
void symbol_table_free(struct symbol_table* syms);
int bytecode_operation_length(uint16_t* codeptr);
void bytecode_free(struct bytecode* bc);
#endif
Executable
+102
View File
@@ -0,0 +1,102 @@
#!/bin/bash
# old values
OLD_CFLAGS=$CFLAGS
OLD_LDFLAGS=$LDFLAGS
ORIG_PWD=`pwd`
# For parallelism in make
NJOBS="-j`sysctl -n hw.ncpu || echo 1`"
# Get oniguruma
rm -rf $PWD/build/ios onig-5.9.5
echo "Downloading oniguruma 5.9.5"
curl http://www.geocities.jp/kosako3/oniguruma/archive/onig-5.9.5.tar.gz | tar xz
cd onig-5.9.5
# So, we need to remake the configure scripts so that the arm64 architecture
# exists in config.sub. In order to keep autoreconf from failing, create
# NEWS and ChangeLog.
touch NEWS ChangeLog
autoreconf -fi >/dev/null 2>&1
CC=`xcrun -f clang`
cd $ORIG_PWD
autoreconf -fi
for arch in i386 x86_64 armv7 armv7s arm64; do
# Some of the architectures are a bit different...
if [[ "$arch" = "i386" || "$arch" = "x86_64" ]]
then
SYSROOT=`xcrun -f --sdk iphonesimulator --show-sdk-path`
else
SYSROOT=`xcrun -f --sdk iphoneos --show-sdk-path`
fi
if [[ "$arch" = "arm64" ]]
then
HOST="aarch64-apple-darwin"
else
HOST="$arch-apple-darwin"
fi
CFLAGS="-arch $arch -miphoneos-version-min=6.0 -isysroot $SYSROOT $OLD_CFLAGS"
LDFLAGS="-arch $arch -miphoneos-version-min=6.0 -isysroot $SYSROOT $OLD_LDFLAGS"
# Build oniguruma for this architecture
cd onig-5.9.5
CC=$CC CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS ./configure --disable-shared --enable-static --host=$HOST --prefix=$ORIG_PWD/build/ios/$arch
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Failed to configure oniguruma for architecture $arch. Check `pwd`/config.log for details."
cd $PWD
exit $STATUS
fi
make clean
make $NJBOS install
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Failed to make oniguruma for architecture $arch."
cd $PWD
exit $STATUS
fi
# Build jq for this architecture
cd $ORIG_PWD
CC=$CC CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS ./configure --disable-shared --enable-static -host=$HOST --prefix=$ORIG_PWD/build/ios/$arch --with-oniguruma=$ORIG_PWD/build/ios/$arch
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Failed to configure jq for architecture $arch"
exit $STATUS
fi
make clean
make $NJOBS install
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Failed to make jq for architecture $arch"
exit $STATUS
fi
done
# lipo together the different architectures into a universal 'fat' file
lipo -create -output $ORIG_PWD/build/ios/libonig.a $ORIG_PWD/build/ios/{i386,x86_64,armv7,armv7s,arm64}/lib/libonig.a
lipo -create -output $ORIG_PWD/build/ios/libjq.a $ORIG_PWD/build/ios/{i386,x86_64,armv7,armv7s,arm64}/lib/libjq.a
# copy the products into the destination directory and clean up the single-architecture files.
cp $ORIG_PWD/build/ios/i386/include/*.h $ORIG_PWD/build/ios/
rm -rf $ORIG_PWD/build/ios/{i386,x86_64,armv7,armv7s,arm64}
echo "Products are in $ORIG_PWD/build/ios"
+630 -98
View File
File diff suppressed because it is too large. Load diff
+37 -13
View File
@@ -2,13 +2,9 @@
#define COMPILE_H
#include <stdint.h>
#include "jv.h"
#include "opcode.h"
#include "bytecode.h"
#include "locfile.h"
struct bytecode;
struct symbol_table;
struct cfunction;
struct inst;
typedef struct inst inst;
@@ -18,41 +14,68 @@ typedef struct block {
inst* last;
} block;
block gen_location(location, block);
block gen_location(location, struct locfile*, block);
block gen_noop();
int block_is_noop(block b);
block gen_op_simple(opcode op);
block gen_const(jv constant);
block gen_const_global(jv constant, const char *name);
int block_is_const(block b);
int block_is_const_inf(block b);
jv_kind block_const_kind(block b);
jv block_const(block b);
block gen_op_target(opcode op, block target);
block gen_op_var_unbound(opcode op, const char* name);
block gen_op_var_bound(opcode op, block binder);
block gen_op_block_unbound(opcode op, const char* name);
block gen_op_unbound(opcode op, const char* name);
block gen_op_bound(opcode op, block binder);
block gen_op_var_fresh(opcode op, const char* name);
block gen_module(block metadata);
jv block_module_meta(block b);
block gen_import(const char* name, block metadata, const char *as, int is_data);
block gen_function(const char* name, block formals, block body);
block gen_param_regular(const char* name);
block gen_param(const char* name);
block gen_lambda(block body);
block gen_call(const char* name, block body);
block gen_subexp(block a);
block gen_both(block a, block b);
block gen_const_object(block expr);
block gen_collect(block expr);
block gen_reduce(const char* varname, block source, block init, block body);
block gen_reduce(block source, block matcher, block init, block body);
block gen_foreach(block source, block matcher, block init, block update, block extract);
block gen_definedor(block a, block b);
block gen_condbranch(block iftrue, block iffalse);
block gen_and(block a, block b);
block gen_or(block a, block b);
block gen_var_binding(block var, const char* name, block body);
block gen_array_matcher(block left, block curr);
block gen_object_matcher(block name, block curr);
block gen_destructure(block var, block matcher, block body);
block gen_cond(block cond, block iftrue, block iffalse);
block gen_try_handler(block handler);
block gen_try(block exp, block handler);
block gen_label(const char *label, block exp);
block gen_cbinding(const struct cfunction* functions, int nfunctions, block b);
void block_append(block* b, block b2);
block block_join(block a, block b);
int block_has_only_binders_and_imports(block, int bindflags);
int block_has_only_binders(block, int bindflags);
int block_has_main(block);
int block_is_funcdef(block b);
int block_is_single(block b);
block block_bind(block binder, block body, int bindflags);
block block_bind_library(block binder, block body, int bindflags, const char* libname);
block block_bind_referenced(block binder, block body, int bindflags);
block block_drop_unreferenced(block body);
int block_compile(block, struct locfile*, struct bytecode**);
jv block_take_imports(block* body);
int block_compile(block, struct bytecode**, struct locfile*);
void block_free(block);
@@ -68,10 +91,11 @@ void block_free(block);
#define BLOCK_5(b1,b2,b3,b4,b5) (block_join(BLOCK_4(b1,b2,b3,b4),(b5)))
#define BLOCK_6(b1,b2,b3,b4,b5,b6) (block_join(BLOCK_5(b1,b2,b3,b4,b5),(b6)))
#define BLOCK_7(b1,b2,b3,b4,b5,b6,b7) (block_join(BLOCK_6(b1,b2,b3,b4,b5,b6),(b7)))
#define BLOCK_8(b1,b2,b3,b4,b5,b6,b7,b8) (block_join(BLOCK_7(b1,b2,b3,b4,b5,b6,b7),(b8)))
#define BLOCK_IDX(_1,_2,_3,_4,_5,_6,_7,NAME,...) NAME
#define BLOCK_IDX(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define BLOCK(...) \
BLOCK_IDX(__VA_ARGS__, BLOCK_7, BLOCK_6, BLOCK_5, BLOCK_4, BLOCK_3, BLOCK_2, BLOCK_1)(__VA_ARGS__)
BLOCK_IDX(__VA_ARGS__, BLOCK_8, BLOCK_7, BLOCK_6, BLOCK_5, BLOCK_4, BLOCK_3, BLOCK_2, BLOCK_1)(__VA_ARGS__)
#endif
-32
View File
@@ -1,32 +0,0 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Version number of package */
#undef VERSION
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
#undef YYTEXT_POINTER
+10
View File
@@ -0,0 +1,10 @@
config.guess
config.sub
compile
depcomp
install-sh
ltmain.sh
missing
ylwrap
test-driver
ar-lib
Executable
+270
View File
@@ -0,0 +1,270 @@
#! /bin/sh
# Wrapper for Microsoft lib.exe
me=ar-lib
scriptversion=2012-03-01.08; # UTC
# Copyright (C) 2010-2013 Free Software Foundation, Inc.
# Written by Peter Rosin <peda@lysator.liu.se>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# func_error message
func_error ()
{
echo "$me: $1" 1>&2
exit 1
}
file_conv=
# func_file_conv build_file
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv in
mingw)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin)
file=`cygpath -m "$file" || echo "$file"`
;;
wine)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_at_file at_file operation archive
# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
# for each of them.
# When interpreting the content of the @FILE, do NOT use func_file_conv,
# since the user would need to supply preconverted file names to
# binutils ar, at least for MinGW.
func_at_file ()
{
operation=$2
archive=$3
at_file_contents=`cat "$1"`
eval set x "$at_file_contents"
shift
for member
do
$AR -NOLOGO $operation:"$member" "$archive" || exit $?
done
}
case $1 in
'')
func_error "no command. Try '$0 --help' for more information."
;;
-h | --h*)
cat <<EOF
Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
Members may be specified in a file named with @FILE.
EOF
exit $?
;;
-v | --v*)
echo "$me, version $scriptversion"
exit $?
;;
esac
if test $# -lt 3; then
func_error "you must specify a program, an action and an archive"
fi
AR=$1
shift
while :
do
if test $# -lt 2; then
func_error "you must specify a program, an action and an archive"
fi
case $1 in
-lib | -LIB \
| -ltcg | -LTCG \
| -machine* | -MACHINE* \
| -subsystem* | -SUBSYSTEM* \
| -verbose | -VERBOSE \
| -wx* | -WX* )
AR="$AR $1"
shift
;;
*)
action=$1
shift
break
;;
esac
done
orig_archive=$1
shift
func_file_conv "$orig_archive"
archive=$file
# strip leading dash in $action
action=${action#-}
delete=
extract=
list=
quick=
replace=
index=
create=
while test -n "$action"
do
case $action in
d*) delete=yes ;;
x*) extract=yes ;;
t*) list=yes ;;
q*) quick=yes ;;
r*) replace=yes ;;
s*) index=yes ;;
S*) ;; # the index is always updated implicitly
c*) create=yes ;;
u*) ;; # TODO: don't ignore the update modifier
v*) ;; # TODO: don't ignore the verbose modifier
*)
func_error "unknown action specified"
;;
esac
action=${action#?}
done
case $delete$extract$list$quick$replace,$index in
yes,* | ,yes)
;;
yesyes*)
func_error "more than one action specified"
;;
*)
func_error "no action specified"
;;
esac
if test -n "$delete"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
for member
do
case $1 in
@*)
func_at_file "${1#@}" -REMOVE "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
;;
esac
done
elif test -n "$extract"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
if test $# -gt 0; then
for member
do
case $1 in
@*)
func_at_file "${1#@}" -EXTRACT "$archive"
;;
*)
func_file_conv "$1"
$AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
;;
esac
done
else
$AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
do
$AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
done
fi
elif test -n "$quick$replace"; then
if test ! -f "$orig_archive"; then
if test -z "$create"; then
echo "$me: creating $orig_archive"
fi
orig_archive=
else
orig_archive=$archive
fi
for member
do
case $1 in
@*)
func_file_conv "${1#@}"
set x "$@" "@$file"
;;
*)
func_file_conv "$1"
set x "$@" "$file"
;;
esac
shift
shift
done
if test -n "$orig_archive"; then
$AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
else
$AR -NOLOGO -OUT:"$archive" "$@" || exit $?
fi
elif test -n "$list"; then
if test ! -f "$orig_archive"; then
func_error "archive not found"
fi
$AR -NOLOGO -LIST "$archive" || exit $?
fi
+7 -3
View File
@@ -1,10 +1,9 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-03-05.13; # UTC
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
# Software Foundation, Inc.
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
@@ -113,6 +112,11 @@ func_cl_dashl ()
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
Vendored Executable
+1558
View File
File diff suppressed because it is too large. Load diff
Vendored Executable
+1791
View File
File diff suppressed because it is too large. Load diff
+270 -187
View File
@@ -1,10 +1,9 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2012-03-27.16; # UTC
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
# 2011, 2012 Free Software Foundation, Inc.
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -28,9 +27,9 @@ scriptversion=2012-03-27.16; # UTC
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
@@ -57,11 +56,65 @@ EOF
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
digits=0123456789
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
@@ -75,6 +128,9 @@ tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interferences from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
@@ -86,32 +142,32 @@ if test "$depmode" = hp; then
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
@@ -134,8 +190,7 @@ gcc3)
done
"$@"
stat=$?
if test $stat -eq 0; then :
else
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
@@ -143,13 +198,17 @@ gcc3)
;;
gcc)
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
@@ -157,15 +216,14 @@ gcc)
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
@@ -174,15 +232,15 @@ gcc)
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' "$nl" < "$tmpdepfile" |
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -200,8 +258,7 @@ sgi)
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
@@ -209,7 +266,6 @@ sgi)
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
@@ -217,19 +273,15 @@ sgi)
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr "$nl" ' ' >> "$depfile"
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
@@ -247,9 +299,8 @@ aix)
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
@@ -262,9 +313,7 @@ aix)
"$@" -M
fi
stat=$?
if test $stat -eq 0; then :
else
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
@@ -273,65 +322,113 @@ aix)
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependent.h'.
# Do two passes, one to just change these to
# '$object: dependent.h' and one to simply 'dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
aix_post_process_depfile
;;
icc)
# Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
# However on
# $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\':
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
# tcc 0.9.26 (FIXME still under development at the moment of writing)
# will emit a similar output, but also prepend the continuation lines
# with horizontal tabulation characters.
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form 'foo.o: dependent.h',
# or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# '$object: dependent.h' and one to simply 'dependent.h:'.
sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
< "$tmpdepfile" > "$depfile"
sed '
s/[ '"$tab"'][ '"$tab"']*/ /g
s/^ *//
s/ *\\*$//
s/^[^:]*: *//
/^$/d
/:$/d
s/$/ :/
' < "$tmpdepfile" >> "$depfile"
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -342,9 +439,8 @@ hp2)
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
@@ -355,8 +451,7 @@ hp2)
"$@" +Maked
fi
stat=$?
if test $stat -eq 0; then :
else
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
@@ -366,76 +461,61 @@ hp2)
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mechanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
@@ -446,8 +526,7 @@ msvc7)
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test "$stat" = 0; then :
else
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
@@ -473,6 +552,7 @@ $ {
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
@@ -524,13 +604,14 @@ dashmstdout)
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' "$nl" < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -583,10 +664,12 @@ makedepend)
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
@@ -622,10 +705,10 @@ cpp)
esac
done
"$@" -E |
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
@@ -657,15 +740,15 @@ msvisualcpp)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
+7 -7
View File
@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-01-19.21; # UTC
scriptversion=2011-11-20.07; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -35,7 +35,7 @@ scriptversion=2011-01-19.21; # UTC
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
@@ -156,7 +156,7 @@ while test $# -ne 0; do
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for `test' and other utilities.
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
@@ -190,7 +190,7 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
fi
shift # arg
dst_arg=$arg
# Protect names problematic for `test' and other utilities.
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
@@ -202,7 +202,7 @@ if test $# -eq 0; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
@@ -240,7 +240,7 @@ fi
for src
do
# Protect names problematic for `test' and other utilities.
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
@@ -354,7 +354,7 @@ do
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writeable bit of parent directory when it shouldn't.
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
+9661
View File
File diff suppressed because it is too large. Load diff
+2
View File
@@ -0,0 +1,2 @@
libtool.m4
lt*.m4
+4
View File
@@ -0,0 +1,4 @@
dnl AC_FIND_FUNC(func, arguments)
AC_DEFUN([AC_CHECK_MATH_FUNC], [
AC_FIND_FUNC_NO_LIBS([$1], [m], [#include <math.h>], [$2])
])
+8
View File
@@ -0,0 +1,8 @@
dnl Shamelessly stolen from Heimdal
dnl
dnl Look for function in any of the specified libraries
dnl
dnl AC_FIND_FUNC_NO_LIBS(func, libraries, includes, arguments, extra libs, extra args)
AC_DEFUN([AC_FIND_FUNC_NO_LIBS], [
AC_FIND_FUNC_NO_LIBS2([$1], ["" $2], [$3], [$4], [$5], [$6])])
+62
View File
@@ -0,0 +1,62 @@
dnl Shamelessly stolen from Heimdal
dnl
dnl Look for function in any of the specified libraries
dnl
dnl AC_FIND_FUNC_NO_LIBS2(func, libraries, includes, arguments, extra libs, extra args)
AC_DEFUN([AC_FIND_FUNC_NO_LIBS2], [
AC_MSG_CHECKING([for $1])
AC_CACHE_VAL(ac_cv_funclib_$1,
[
if eval "test \"\$ac_cv_func_$1\" != yes" ; then
ac_save_LIBS="$LIBS"
for ac_lib in $2; do
case "$ac_lib" in
"") ;;
yes) ac_lib="" ;;
no) continue ;;
-l*) ;;
*) ac_lib="-l$ac_lib" ;;
esac
LIBS="$6 $ac_lib $5 $ac_save_LIBS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[$3]],[[$1($4)]])],[eval "if test -n \"$ac_lib\";then ac_cv_funclib_$1=$ac_lib; else ac_cv_funclib_$1=yes; fi";break])
done
eval "ac_cv_funclib_$1=\${ac_cv_funclib_$1-no}"
LIBS="$ac_save_LIBS"
fi
])
eval "ac_res=\$ac_cv_funclib_$1"
if false; then
AC_CHECK_FUNCS($1)
dnl AC_CHECK_LIBS($2, foo)
fi
# $1
eval "ac_tr_func=HAVE_[]upcase($1)"
eval "ac_tr_lib=HAVE_LIB[]upcase($ac_res | sed -e 's/-l//')"
eval "LIB_$1=$ac_res"
case "$ac_res" in
yes)
eval "ac_cv_func_$1=yes"
eval "LIB_$1="
AC_DEFINE_UNQUOTED($ac_tr_func)
AC_MSG_RESULT([yes])
;;
no)
eval "ac_cv_func_$1=no"
eval "LIB_$1="
AC_MSG_RESULT([no])
;;
*)
eval "ac_cv_func_$1=yes"
eval "ac_cv_lib_`echo "$ac_res" | sed 's/-l//'`=yes"
AC_DEFINE_UNQUOTED($ac_tr_func)
AC_DEFINE_UNQUOTED($ac_tr_lib)
AC_MSG_RESULT([yes, in $ac_res])
;;
esac
AC_SUBST(LIB_$1)
])
+9
View File
@@ -0,0 +1,9 @@
dnl Shamelessly stolen from Heimdal
dnl
dnl AC_FIND_FUNC(func, libraries, includes, arguments)
AC_DEFUN([AC_FIND_FUNC], [
AC_FIND_FUNC_NO_LIBS([$1], [$2], [$3], [$4])
if test -n "$LIB_$1"; then
LIBS="$LIB_$1 $LIBS"
fi
])
+7997
View File
File diff suppressed because it is too large. Load diff
+384
View File
@@ -0,0 +1,384 @@
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 7 ltoptions.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
# ------------------------------------------
m4_define([_LT_MANGLE_OPTION],
[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
# ---------------------------------------
# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
# matching handler defined, dispatch to it. Other OPTION-NAMEs are
# saved as a flag.
m4_define([_LT_SET_OPTION],
[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
_LT_MANGLE_DEFUN([$1], [$2]),
[m4_warning([Unknown $1 option `$2'])])[]dnl
])
# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
# ------------------------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
m4_define([_LT_IF_OPTION],
[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
# -------------------------------------------------------
# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
# are set.
m4_define([_LT_UNLESS_OPTIONS],
[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
[m4_define([$0_found])])])[]dnl
m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
])[]dnl
])
# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
# ----------------------------------------
# OPTION-LIST is a space-separated list of Libtool options associated
# with MACRO-NAME. If any OPTION has a matching handler declared with
# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
# the unknown option and exit.
m4_defun([_LT_SET_OPTIONS],
[# Set options
m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
[_LT_SET_OPTION([$1], _LT_Option)])
m4_if([$1],[LT_INIT],[
dnl
dnl Simply set some default values (i.e off) if boolean options were not
dnl specified:
_LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
])
_LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
])
dnl
dnl If no reference was made to various pairs of opposing options, then
dnl we run the default mode handler for the pair. For example, if neither
dnl `shared' nor `disable-shared' was passed, we enable building of shared
dnl archives by default:
_LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
_LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
_LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
_LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
[_LT_ENABLE_FAST_INSTALL])
])
])# _LT_SET_OPTIONS
## --------------------------------- ##
## Macros to handle LT_INIT options. ##
## --------------------------------- ##
# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
# -----------------------------------------
m4_define([_LT_MANGLE_DEFUN],
[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
# -----------------------------------------------
m4_define([LT_OPTION_DEFINE],
[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
])# LT_OPTION_DEFINE
# dlopen
# ------
LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
])
AU_DEFUN([AC_LIBTOOL_DLOPEN],
[_LT_SET_OPTION([LT_INIT], [dlopen])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `dlopen' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
# win32-dll
# ---------
# Declare package support for building win32 dll's.
LT_OPTION_DEFINE([LT_INIT], [win32-dll],
[enable_win32_dll=yes
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
AC_CHECK_TOOL(AS, as, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(OBJDUMP, objdump, false)
;;
esac
test -z "$AS" && AS=as
_LT_DECL([], [AS], [1], [Assembler program])dnl
test -z "$DLLTOOL" && DLLTOOL=dlltool
_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
test -z "$OBJDUMP" && OBJDUMP=objdump
_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
])# win32-dll
AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
_LT_SET_OPTION([LT_INIT], [win32-dll])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `win32-dll' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
# _LT_ENABLE_SHARED([DEFAULT])
# ----------------------------
# implement the --enable-shared flag, and supports the `shared' and
# `disable-shared' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_SHARED],
[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([shared],
[AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
[build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_shared=yes ;;
no) enable_shared=no ;;
*)
enable_shared=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_shared=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
_LT_DECL([build_libtool_libs], [enable_shared], [0],
[Whether or not to build shared libraries])
])# _LT_ENABLE_SHARED
LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
# Old names:
AC_DEFUN([AC_ENABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
])
AC_DEFUN([AC_DISABLE_SHARED],
[_LT_SET_OPTION([LT_INIT], [disable-shared])
])
AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_SHARED], [])
dnl AC_DEFUN([AM_DISABLE_SHARED], [])
# _LT_ENABLE_STATIC([DEFAULT])
# ----------------------------
# implement the --enable-static flag, and support the `static' and
# `disable-static' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_STATIC],
[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([static],
[AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
[build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_static=yes ;;
no) enable_static=no ;;
*)
enable_static=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_static=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_static=]_LT_ENABLE_STATIC_DEFAULT)
_LT_DECL([build_old_libs], [enable_static], [0],
[Whether or not to build static libraries])
])# _LT_ENABLE_STATIC
LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
# Old names:
AC_DEFUN([AC_ENABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
])
AC_DEFUN([AC_DISABLE_STATIC],
[_LT_SET_OPTION([LT_INIT], [disable-static])
])
AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AM_ENABLE_STATIC], [])
dnl AC_DEFUN([AM_DISABLE_STATIC], [])
# _LT_ENABLE_FAST_INSTALL([DEFAULT])
# ----------------------------------
# implement the --enable-fast-install flag, and support the `fast-install'
# and `disable-fast-install' LT_INIT options.
# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
m4_define([_LT_ENABLE_FAST_INSTALL],
[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
AC_ARG_ENABLE([fast-install],
[AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
[optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
[p=${PACKAGE-default}
case $enableval in
yes) enable_fast_install=yes ;;
no) enable_fast_install=no ;;
*)
enable_fast_install=no
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for pkg in $enableval; do
IFS="$lt_save_ifs"
if test "X$pkg" = "X$p"; then
enable_fast_install=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
_LT_DECL([fast_install], [enable_fast_install], [0],
[Whether or not to optimize for fast installation])dnl
])# _LT_ENABLE_FAST_INSTALL
LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
# Old names:
AU_DEFUN([AC_ENABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `fast-install' option into LT_INIT's first parameter.])
])
AU_DEFUN([AC_DISABLE_FAST_INSTALL],
[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you put
the `disable-fast-install' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
# _LT_WITH_PIC([MODE])
# --------------------
# implement the --with-pic flag, and support the `pic-only' and `no-pic'
# LT_INIT options.
# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
m4_define([_LT_WITH_PIC],
[AC_ARG_WITH([pic],
[AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
[try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
[lt_p=${PACKAGE-default}
case $withval in
yes|no) pic_mode=$withval ;;
*)
pic_mode=default
# Look at the argument we got. We use all the common list separators.
lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
for lt_pkg in $withval; do
IFS="$lt_save_ifs"
if test "X$lt_pkg" = "X$lt_p"; then
pic_mode=yes
fi
done
IFS="$lt_save_ifs"
;;
esac],
[pic_mode=default])
test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
])# _LT_WITH_PIC
LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
# Old name:
AU_DEFUN([AC_LIBTOOL_PICMODE],
[_LT_SET_OPTION([LT_INIT], [pic-only])
AC_DIAGNOSE([obsolete],
[$0: Remove this warning and the call to _LT_SET_OPTION when you
put the `pic-only' option into LT_INIT's first parameter.])
])
dnl aclocal-1.4 backwards compatibility:
dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
## ----------------- ##
## LTDL_INIT Options ##
## ----------------- ##
m4_define([_LTDL_MODE], [])
LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
[m4_define([_LTDL_MODE], [nonrecursive])])
LT_OPTION_DEFINE([LTDL_INIT], [recursive],
[m4_define([_LTDL_MODE], [recursive])])
LT_OPTION_DEFINE([LTDL_INIT], [subproject],
[m4_define([_LTDL_MODE], [subproject])])
m4_define([_LTDL_TYPE], [])
LT_OPTION_DEFINE([LTDL_INIT], [installable],
[m4_define([_LTDL_TYPE], [installable])])
LT_OPTION_DEFINE([LTDL_INIT], [convenience],
[m4_define([_LTDL_TYPE], [convenience])])
+123
View File
@@ -0,0 +1,123 @@
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 6 ltsugar.m4
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
# lt_join(SEP, ARG1, [ARG2...])
# -----------------------------
# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
# associated separator.
# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
# versions in m4sugar had bugs.
m4_define([lt_join],
[m4_if([$#], [1], [],
[$#], [2], [[$2]],
[m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
m4_define([_lt_join],
[m4_if([$#$2], [2], [],
[m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
# lt_car(LIST)
# lt_cdr(LIST)
# ------------
# Manipulate m4 lists.
# These macros are necessary as long as will still need to support
# Autoconf-2.59 which quotes differently.
m4_define([lt_car], [[$1]])
m4_define([lt_cdr],
[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
[$#], 1, [],
[m4_dquote(m4_shift($@))])])
m4_define([lt_unquote], $1)
# lt_append(MACRO-NAME, STRING, [SEPARATOR])
# ------------------------------------------
# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
# Note that neither SEPARATOR nor STRING are expanded; they are appended
# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
# No SEPARATOR is output if MACRO-NAME was previously undefined (different
# than defined and empty).
#
# This macro is needed until we can rely on Autoconf 2.62, since earlier
# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
m4_define([lt_append],
[m4_define([$1],
m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
# ----------------------------------------------------------
# Produce a SEP delimited list of all paired combinations of elements of
# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
# has the form PREFIXmINFIXSUFFIXn.
# Needed until we can rely on m4_combine added in Autoconf 2.62.
m4_define([lt_combine],
[m4_if(m4_eval([$# > 3]), [1],
[m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
[[m4_foreach([_Lt_prefix], [$2],
[m4_foreach([_Lt_suffix],
]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
[_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
# -----------------------------------------------------------------------
# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
m4_define([lt_if_append_uniq],
[m4_ifdef([$1],
[m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
[lt_append([$1], [$2], [$3])$4],
[$5])],
[lt_append([$1], [$2], [$3])$4])])
# lt_dict_add(DICT, KEY, VALUE)
# -----------------------------
m4_define([lt_dict_add],
[m4_define([$1($2)], [$3])])
# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
# --------------------------------------------
m4_define([lt_dict_add_subkey],
[m4_define([$1($2:$3)], [$4])])
# lt_dict_fetch(DICT, KEY, [SUBKEY])
# ----------------------------------
m4_define([lt_dict_fetch],
[m4_ifval([$3],
m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
# -----------------------------------------------------------------
m4_define([lt_if_dict_fetch],
[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
[$5],
[$6])])
# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
# --------------------------------------------------------------
m4_define([lt_dict_filter],
[m4_if([$5], [], [],
[lt_join(m4_quote(m4_default([$4], [[, ]])),
lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
[lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
])
+23
View File
@@ -0,0 +1,23 @@
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# @configure_input@
# serial 3337 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.2])
m4_define([LT_PACKAGE_REVISION], [1.3337])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.2'
macro_revision='1.3337'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
+98
View File
@@ -0,0 +1,98 @@
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
# serial 5 lt~obsolete.m4
# These exist entirely to fool aclocal when bootstrapping libtool.
#
# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
# which have later been changed to m4_define as they aren't part of the
# exported API, or moved to Autoconf or Automake where they belong.
#
# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
# using a macro with the same name in our local m4/libtool.m4 it'll
# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
# and doesn't know about Autoconf macros at all.)
#
# So we provide this file, which has a silly filename so it's always
# included after everything else. This provides aclocal with the
# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
# because those macros already exist, or will be overwritten later.
# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
#
# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
# Yes, that means every name once taken will need to remain here until
# we give up compatibility with versions before 1.7, at which point
# we need to keep only those names which we still refer to.
# This is to help aclocal find these macros, as it can't see m4_define.
AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
+3
View File
@@ -0,0 +1,3 @@
dnl Shamelessly stolen from Heimdal
AC_DEFUN([upcase],[`echo $1 | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`])dnl
+148 -264
View File
@@ -1,11 +1,10 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2012-01-06.13; # UTC
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -26,68 +25,40 @@ scriptversion=2012-01-06.13; # UTC
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
run=:
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
msg="missing on your system"
case $1 in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
# Exit code 63 means version mismatch. This often happens
# when the user try to use an ancient version of a tool on
# a file that requires a minimum version. In this case we
# we should proceed has if the program had been absent, or
# if --run hadn't been passed.
if test $? = 63; then
run=:
msg="probably too old"
fi
;;
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
autom4te touch the output file, or create a stub one
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
\`g' are ignored when checking the name.
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
@@ -99,228 +70,141 @@ Send bug reports to <bug-automake@gnu.org>."
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# normalize program name to check for.
program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
# Run the given program, remember its exit status.
"$@"; st=$?
# Now exit if we have it, but it failed. Also exit now if we
# don't have it and --version was passed (most likely to detect
# the program). This is about non-GNU programs, so use $1 not
# $program.
case $1 in
lex*|yacc*)
# Not GNU programs, they don't have --version.
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
# Could not run --version or --help. This is probably someone
# running `$TOOL --version' or `$TOOL --help' to check whether
# $TOOL exists and not knowing $TOOL uses missing.
exit 1
fi
;;
esac
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case $program in
aclocal*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case $f in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te*)
echo 1>&2 "\
WARNING: \`$1' is needed, but is $msg.
You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison*|yacc*)
echo 1>&2 "\
WARNING: \`$1' $msg. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if test $# -ne 1; then
eval LASTARG=\${$#}
case $LASTARG in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if test ! -f y.tab.h; then
echo >y.tab.h
fi
if test ! -f y.tab.c; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex*|flex*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if test $# -ne 1; then
eval LASTARG=\${$#}
case $LASTARG in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if test ! -f lex.yy.c; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit $?
fi
;;
makeinfo*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
# The file to touch is that specified with -o ...
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -z "$file"; then
# ... or it is the one specified with @setfilename ...
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '
/^@setfilename/{
s/.* \([^ ]*\) *$/\1/
p
q
}' $infile`
# ... or it is derived from the source name (dir/f.texi becomes f.info)
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
fi
# If the file does not exist, the user really needs makeinfo;
# let's fail without touching anything.
test -f $file || exit 1
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and is $msg.
You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
+139
View File
@@ -0,0 +1,139 @@
#! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2013-07-13.22; # UTC
# Copyright (C) 2011-2013 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <<END
Usage:
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
[--expect-failure={yes|no}] [--color-tests={yes|no}]
[--enable-hard-errors={yes|no}] [--]
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
END
}
test_name= # Used for reporting.
log_file= # Where to save the output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=no
color_tests=no
enable_hard_errors=yes
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "test-driver $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) enable_hard_errors=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
*) break;;
esac
shift
done
missing_opts=
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
if test x"$missing_opts" != x; then
usage_error "the following mandatory options are missing:$missing_opts"
fi
if test $# -eq 0; then
usage_error "missing argument"
fi
if test $color_tests = yes; then
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
red='' # Red.
grn='' # Green.
lgn='' # Light green.
blu='' # Blue.
mgn='' # Magenta.
std='' # No color.
else
red= grn= lgn= blu= mgn= std=
fi
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
trap "st=129; $do_exit" 1
trap "st=130; $do_exit" 2
trap "st=141; $do_exit" 13
trap "st=143; $do_exit" 15
# Test script is run here.
"$@" >$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
estatus=1
fi
case $estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
+111 -90
View File
@@ -1,10 +1,9 @@
#! /bin/sh
# ylwrap - wrapper for lex/yacc invocations.
scriptversion=2011-08-25.18; # UTC
scriptversion=2013-01-12.17; # UTC
# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005,
# 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
#
# Written by Tom Tromey <tromey@cygnus.com>.
#
@@ -30,9 +29,41 @@ scriptversion=2011-08-25.18; # UTC
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
get_dirname ()
{
case $1 in
*/*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
# Otherwise, we want the empty string (not ".").
esac
}
# guard FILE
# ----------
# The CPP macro used to guard inclusion of FILE.
guard ()
{
printf '%s\n' "$1" \
| sed \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \
-e 's/__*/_/g'
}
# quote_for_sed [STRING]
# ----------------------
# Return STRING (or stdin) quoted to be used as a sed pattern.
quote_for_sed ()
{
case $# in
0) cat;;
1) printf '%s\n' "$1";;
esac \
| sed -e 's|[][\\.*]|\\&|g'
}
case "$1" in
'')
echo "$0: No files given. Try \`$0 --help' for more information." 1>&2
echo "$0: No files given. Try '$0 --help' for more information." 1>&2
exit 1
;;
--basedir)
@@ -65,39 +96,71 @@ esac
# The input.
input="$1"
input=$1
shift
case "$input" in
# We'll later need for a correct munging of "#line" directives.
input_sub_rx=`get_dirname "$input" | quote_for_sed`
case $input in
[\\/]* | ?:[\\/]*)
# Absolute path; do nothing.
;;
*)
# Relative path. Make it absolute.
input="`pwd`/$input"
input=`pwd`/$input
;;
esac
input_rx=`get_dirname "$input" | quote_for_sed`
pairlist=
while test "$#" -ne 0; do
if test "$1" = "--"; then
# Since DOS filename conventions don't allow two dots,
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
y_tab_nodot=false
if test -f y_tab.c || test -f y_tab.h; then
y_tab_nodot=true
fi
# The parser itself, the first file, is the destination of the .y.c
# rule in the Makefile.
parser=$1
# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
# instance, we rename #include "y.tab.h" into #include "parse.h"
# during the conversion from y.tab.c to parse.c.
sed_fix_filenames=
# Also rename header guards, as Bison 2.7 for instance uses its header
# guard in its implementation file.
sed_fix_header_guards=
while test $# -ne 0; do
if test x"$1" = x"--"; then
shift
break
fi
pairlist="$pairlist $1"
from=$1
# Handle y_tab.c and y_tab.h output by DOS
if $y_tab_nodot; then
case $from in
"y.tab.c") from=y_tab.c;;
"y.tab.h") from=y_tab.h;;
esac
fi
shift
to=$1
shift
sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;"
sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;"
done
# The program to run.
prog="$1"
prog=$1
shift
# Make any relative path in $prog absolute.
case "$prog" in
case $prog in
[\\/]* | ?:[\\/]*) ;;
*[\\/]*) prog="`pwd`/$prog" ;;
*[\\/]*) prog=`pwd`/$prog ;;
esac
# FIXME: add hostname here for parallel makes that run commands on
# other machines. But that might take us over the 14-char limit.
dirname=ylwrap$$
do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
@@ -115,98 +178,56 @@ esac
ret=$?
if test $ret -eq 0; then
set X $pairlist
shift
first=yes
# Since DOS filename conventions don't allow two dots,
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
y_tab_nodot="no"
if test -f y_tab.c || test -f y_tab.h; then
y_tab_nodot="yes"
fi
# The directory holding the input.
input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
# Quote $INPUT_DIR so we can use it in a regexp.
# FIXME: really we should care about more than `.' and `\'.
input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
while test "$#" -ne 0; do
from="$1"
# Handle y_tab.c and y_tab.h output by DOS
if test $y_tab_nodot = "yes"; then
if test $from = "y.tab.c"; then
from="y_tab.c"
else
if test $from = "y.tab.h"; then
from="y_tab.h"
fi
fi
fi
for from in *
do
to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"`
if test -f "$from"; then
# If $2 is an absolute path name, then just use that,
# otherwise prepend `../'.
case "$2" in
[\\/]* | ?:[\\/]*) target="$2";;
*) target="../$2";;
# otherwise prepend '../'.
case $to in
[\\/]* | ?:[\\/]*) target=$to;;
*) target=../$to;;
esac
# We do not want to overwrite a header file if it hasn't
# changed. This avoid useless recompilations. However the
# parser itself (the first file) should always be updated,
# because it is the destination of the .y.c rule in the
# Makefile. Divert the output of all other files to a temporary
# file so we can compare them to existing versions.
if test $first = no; then
realtarget="$target"
target="tmp-`echo $target | sed s/.*[\\/]//g`"
# Do not overwrite unchanged header files to avoid useless
# recompilations. Always update the parser itself: it is the
# destination of the .y.c rule in the Makefile. Divert the
# output of all other files to a temporary file so we can
# compare them to existing versions.
if test $from != $parser; then
realtarget=$target
target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
fi
# Edit out `#line' or `#' directives.
#
# We don't want the resulting debug information to point at
# an absolute srcdir; it is better for it to just mention the
# .y file with no path.
#
# We want to use the real output file name, not yy.lex.c for
# instance.
#
# We want the include guards to be adjusted too.
FROM=`echo "$from" | sed \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
TARGET=`echo "$2" | sed \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
-e "s,$FROM,$TARGET," "$from" >"$target" || ret=$?
# Munge "#line" or "#" directives. Don't let the resulting
# debug information point at an absolute srcdir. Use the real
# output file name, not yy.lex.c for instance. Adjust the
# include guards too.
sed -e "/^#/!b" \
-e "s|$input_rx|$input_sub_rx|" \
-e "$sed_fix_filenames" \
-e "$sed_fix_header_guards" \
"$from" >"$target" || ret=$?
# Check whether header files must be updated.
if test $first = no; then
# Check whether files must be updated.
if test "$from" != "$parser"; then
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
echo "$2" is unchanged
echo "$to is unchanged"
rm -f "$target"
else
echo updating "$2"
echo "updating $to"
mv -f "$target" "$realtarget"
fi
fi
else
# A missing file is only an error for the first file. This
# is a blatant hack to let us support using "yacc -d". If -d
# is not specified, we don't want an error when the header
# file is "missing".
if test $first = yes; then
# A missing file is only an error for the parser. This is a
# blatant hack to let us support using "yacc -d". If -d is not
# specified, don't fail when the header file is "missing".
if test "$from" = "$parser"; then
ret=1
fi
fi
shift
shift
first=no
done
else
ret=$?
fi
# Remove the directory.
Vendored Executable
+20676
View File
File diff suppressed because it is too large. Load diff
+175 -20
View File
@@ -1,28 +1,76 @@
AC_INIT([jq], [1.3], [mu@netsoc.tcd.ie],
[jq], [http://stedolan.github.com/jq/])
m4_define([jq_version], m4_esyscmd_s([git describe --tags --dirty --match 'jq-*'|sed 's/^jq-//']))
AC_INIT([jq], [jq_version], [https://github.com/stedolan/jq/issues],
[jq], [https://stedolan.github.io/jq])
m4_include([m4/ax_compare_version.m4])
m4_include([m4/ax_prog_bison_version.m4])
dnl Created autoconf implementation thompson@dtosolutions, 26NOV12
AC_PREREQ([2.61])
AC_PREREQ([2.64])
AC_CONFIG_AUX_DIR([config])
AM_INIT_AUTOMAKE([parallel-tests foreign])
AM_INIT_AUTOMAKE([1.11.2 parallel-tests foreign -Wall])
AM_SILENT_RULES([yes])
AM_PROG_AR
AM_MAINTAINER_MODE([enable])
AC_PROG_CC
AC_PROG_CC_STDC
AC_PROG_CPP_WERROR
AC_PROG_YACC
AC_OBJEXT
AC_EXEEXT
LT_INIT([shared static win32-dll])
AM_PROG_CC_C_O
dnl couldn't use AM_PROG_LEX as it doesn't support header files like the
dnl AC_PROG_YACC macros...
dnl
dnl these program checks should probably be deleted
dnl
dnl check bison version
AC_PROG_LEX
if test "x$LEX" != xflex; then
LEX="$SHELL $missing_dir/missing flex"
if test "$USE_MAINTAINER_MODE" = yes; then
if test "$YACC" != "bison -y"; then
AC_MSG_CHECKING([bison version])
AC_MSG_RESULT([not bison])
else
AX_PROG_BISON_VERSION([3],
[],
[AC_MSG_ERROR([You need bison version 3.0 or greater, or use --disable-maintainer-mode.])])
fi
AC_PROG_LEX
if test "x$LEX" != xflex; then
LEX="$SHELL $missing_dir/missing flex"
fi
fi
##########################################################################
# check for ONIGURUMA library
##########################################################################
AC_ARG_WITH([oniguruma],
[AS_HELP_STRING([--with-oniguruma=prefix],
[try this for a non-standard install prefix of the oniguruma library])],
[ONIGURUMAPATHSET=1],
[ONIGURUMAPATHSET=0])
if test $ONIGURUMAPATHSET = 1; then
CFLAGS="$CFLAGS -I${with_oniguruma}/include"
LDFLAGS="$LDFLAGS -L${with_oniguruma}/lib"
fi
# check for ONIGURUMA library
HAVE_ONIGURUMA=0
AC_CHECK_HEADER("oniguruma.h",
AC_CHECK_LIB([onig],[onig_version],[LIBS="$LIBS -lonig"; HAVE_ONIGURUMA=1;]))
# handle check results
if test $HAVE_ONIGURUMA != 1; then
AC_MSG_NOTICE([Oniguruma was not found.])
AC_MSG_NOTICE([ Try setting the location using '--with-oniguruma=PREFIX' ])
else
AC_DEFINE([HAVE_ONIGURUMA],1,[Define to 1 if Oniguruma is installed])
fi
@@ -31,18 +79,41 @@ AC_CHECK_PROGS(valgrind_cmd, valgrind)
if test "x$valgrind_cmd" = "x" ; then
AC_MSG_WARN([valgrind is required to test jq.])
fi
AC_CHECK_FUNCS(memmem)
AC_CHECK_FUNCS(mkstemp)
dnl Running tests with Valgrind is slow. It is faster to iterate on
dnl code without Valgrind until tests pass, then enable Valgrind and
dnl fix leaks.
AC_ARG_ENABLE([valgrind],
AC_HELP_STRING([--disable-valgrind], [do not run tests under Valgrind]))
dnl Code coverage
AC_ARG_ENABLE([gcov],
AC_HELP_STRING([--enable-gcov], [enable gcov code coverage tool]))
dnl Don't attempt to build docs if there's no Ruby lying around
AC_ARG_ENABLE([docs],
AC_HELP_STRING([--disable-docs], [don't build docs]))
dnl Don't attempt to build the error injection object (if there is no LD_PRELOAD support)
AC_ARG_ENABLE([error-injection],
AC_HELP_STRING([--enable-error-injection], [build and test with error injection]))
dnl Enable building all static
AC_ARG_ENABLE([all-static],
AC_HELP_STRING([--enable-all-static], [link jq with static libraries only]))
AS_IF([test "x$enable_docs" != "xno"],[
AC_CHECK_PROGS(bundle_cmd, bundle)
AS_IF([test "x$bundle_cmd" = "x" || \
! ( cd ${srcdir}/docs; "$bundle_cmd" check 2>/dev/null )],[
AC_MSG_WARN([no bundler])
cat <<EOF
AC_CACHE_CHECK([for Ruby dependencies], [jq_cv_ruby_deps],
[jq_cv_ruby_deps=yes;
AS_IF([test "x$bundle_cmd" = "x" || \
! bmsg="`cd ${srcdir}/docs; "$bundle_cmd" check 2>/dev/null`"],[
AC_MSG_WARN([$bmsg])
cat <<EOF
*****************************************************************
* Ruby dependencies for building jq documentation not found. *
* You can still build, install and hack on jq, but the manpage *
@@ -50,16 +121,100 @@ AS_IF([test "x$enable_docs" != "xno"],[
* See docs/README.md for how to install the docs dependencies. *
*****************************************************************
EOF
enable_docs=no
])
jq_cv_ruby_deps=no
])])
if test "x$jq_cv_ruby_deps" != "xyes"; then
enable_docs=no
fi
])
AM_CONDITIONAL([ENABLE_VALGRIND], [test "x$enable_valgrind" != xno])
AM_CONDITIONAL([ENABLE_GCOV], [test "x$enable_gcov" = xyes])
AM_CONDITIONAL([ENABLE_DOCS], [test "x$enable_docs" != xno])
AM_CONDITIONAL([ENABLE_ERROR_INJECTION], [test "x$enable_error_injection" = xyes])
AM_CONDITIONAL([ENABLE_ALL_STATIC], [test "x$enable_all_static" = xyes])
AC_FUNC_ALLOCA
AC_FIND_FUNC([isatty], [c], [#include <unistd.h>], [0])
AC_FIND_FUNC([_isatty], [c], [#include <io.h>], [0])
AC_FIND_FUNC([strptime], [c], [#include <time.h>], [0, 0, 0])
AC_FIND_FUNC([strftime], [c], [#include <time.h>], [0, 0, 0, 0])
AC_FIND_FUNC([timegm], [c], [#include <time.h>], [0])
AC_FIND_FUNC([gmtime_r], [c], [#include <time.h>], [0, 0])
AC_FIND_FUNC([gmtime], [c], [#include <time.h>], [0])
AC_FIND_FUNC([gettimeofday], [c], [#include <time.h>], [0, 0])
AC_CHECK_MEMBER([struct tm.tm_gmtoff], [AC_DEFINE([HAVE_TM_TM_GMT_OFF],1,[Define to 1 if the system has the tm_gmt_off field in struct tm])],
[], [[#include <time.h>]])
AC_CHECK_MEMBER([struct tm.__tm_gmtoff], [AC_DEFINE([HAVE_TM___TM_GMT_OFF],1,[Define to 1 if the system has the __tm_gmt_off field in struct tm])],
[], [[#include <time.h>]])
AC_ARG_ENABLE([pthread-tls],
[AC_HELP_STRING([--enable-pthread-tls],
[Enable use of pthread thread local storage])],
[],
[enable_pthread_tls=no])
if test $enable_pthread_tls = yes; then
AC_FIND_FUNC([pthread_key_create], [pthread], [#include <pthread.h>], [NULL, NULL])
AC_FIND_FUNC([pthread_once], [pthread], [#include <pthread.h>], [NULL, NULL])
AC_FIND_FUNC([atexit], [pthread], [#include <stdlib.h>], [NULL])
fi
dnl libm math.h functions
AC_CHECK_MATH_FUNC(acos, [.5])
AC_CHECK_MATH_FUNC(acosh, [.5])
AC_CHECK_MATH_FUNC(asin, [.5])
AC_CHECK_MATH_FUNC(asinh, [.5])
AC_CHECK_MATH_FUNC(atan, [.5])
AC_CHECK_MATH_FUNC(atanh, [.5])
AC_CHECK_MATH_FUNC(cbrt, [.5])
AC_CHECK_MATH_FUNC(cos, [.5])
AC_CHECK_MATH_FUNC(cosh, [.5])
AC_CHECK_MATH_FUNC(exp2, [.5])
AC_CHECK_MATH_FUNC(exp, [.5])
AC_CHECK_MATH_FUNC(floor, [.5])
AC_CHECK_MATH_FUNC(j0, [.5])
AC_CHECK_MATH_FUNC(j1, [.5])
AC_CHECK_MATH_FUNC(log10, [.5])
AC_CHECK_MATH_FUNC(log2, [.5])
AC_CHECK_MATH_FUNC(log, [.5])
AC_CHECK_MATH_FUNC(sin, [.5])
AC_CHECK_MATH_FUNC(sinh, [.5])
AC_CHECK_MATH_FUNC(sqrt, [.5])
AC_CHECK_MATH_FUNC(tan, [.5])
AC_CHECK_MATH_FUNC(tanh, [.5])
AC_CHECK_MATH_FUNC(tgamma, [.5])
AC_CHECK_MATH_FUNC(y0, [.5])
AC_CHECK_MATH_FUNC(y1, [.5])
AC_CHECK_MATH_FUNC(pow, [2,2])
AC_CHECK_MATH_FUNC(atan2, [.5,.5])
AC_CHECK_MATH_FUNC(hypot, [.5,.5])
AC_CHECK_MATH_FUNC(remainder, [3,2])
dnl Thread local storage
have___thread=no
AC_MSG_CHECKING(for thread-local storage)
AC_LINK_IFELSE([AC_LANG_SOURCE([
static __thread int x ;
int main () { x = 123; return x; }
])], have___thread=yes)
if test $have___thread = yes; then
AC_DEFINE([HAVE___THREAD],1,[Define to 1 if the system supports __thread])
fi
AC_MSG_RESULT($have___thread)
AC_C_BIGENDIAN(
AC_DEFINE([IEEE_MC68k], 1, [machine is bigendian]),
AC_DEFINE([IEEE_8087], 1, [machine is littleendian]),
AC_MSG_ERROR(unknown endianess),
AC_MSG_ERROR(universial endianess not supported)
)
AC_SUBST([BUNDLER], ["$bundle_cmd"])
dnl AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS(config.h)
AM_INIT_AUTOMAKE([-Wall])
AC_CONFIG_MACRO_DIR([config/m4])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
+1
View File
@@ -4,3 +4,4 @@ gem "rake"
gem "bonsai"
gem "maruku"
gem "ronn"
gem "mustache", "<1.0" # to support ruby <2.0
+30 -30
View File
@@ -1,15 +1,14 @@
GEM
remote: https://rubygems.org/
specs:
POpen4 (0.1.4)
Platform (>= 0.4.0)
open4
Platform (0.4.0)
activesupport (3.2.12)
i18n (~> 0.6)
multi_json (~> 1.0)
addressable (2.3.4)
bonsai (1.4.8)
activesupport (4.2.3)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.3.8)
bonsai (1.4.9)
activesupport (>= 3.0.3)
builder (>= 3.0.0)
i18n (>= 0.5.0)
@@ -22,36 +21,36 @@ GEM
tilt (>= 1.3)
watch (>= 0.1.0)
yui-compressor
builder (3.2.0)
builder (3.2.2)
hpricot (0.8.6)
i18n (0.6.4)
launchy (2.3.0)
i18n (0.7.0)
json (1.8.3)
launchy (2.4.3)
addressable (~> 2.3)
liquid (2.5.0)
maruku (0.6.1)
syntax (>= 1.0.0)
multi_json (1.7.3)
mustache (0.99.4)
open4 (1.3.0)
rack (1.5.2)
rack-protection (1.5.0)
liquid (3.0.6)
maruku (0.7.2)
minitest (5.8.0)
mustache (0.99.8)
rack (1.6.4)
rack-protection (1.5.3)
rack
rake (10.0.3)
rdiscount (2.0.7.2)
rake (10.4.2)
rdiscount (2.1.8)
ronn (0.7.3)
hpricot (>= 0.8.2)
mustache (>= 0.7.0)
rdiscount (>= 1.5.8)
sass (3.2.8)
sinatra (1.4.2)
rack (~> 1.5, >= 1.5.2)
sass (3.4.16)
sinatra (1.4.6)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
syntax (1.0.0)
tilt (1.4.0)
tilt (>= 1.3, < 3)
thread_safe (0.3.5)
tilt (2.0.1)
tzinfo (1.2.2)
thread_safe (~> 0.1)
watch (0.1.0)
yui-compressor (0.9.6)
POpen4 (>= 0.1.4)
yui-compressor (0.12.0)
PLATFORMS
ruby
@@ -59,5 +58,6 @@ PLATFORMS
DEPENDENCIES
bonsai
maruku
mustache (< 1.0)
rake
ronn
+1 -1
View File
@@ -13,7 +13,7 @@ RVM and Ruby 1.9.3 like so:
After that finishes installing, you'll need to make sure RVM is on
your path by doing `source $HOME/.rvm/scripts/rvm`, or just opening a
new shell. See <http://rvm.io> for more info on RVM.
new shell. See <https://rvm.io> for more info on RVM.
Once RVM is installed, you can install all the dependencies for jq's
documentation build by running this from the `docs` directory:
+1 -2
View File
@@ -75,7 +75,7 @@ $BINARIES = {
$BINARIES.each do |name, args|
file "../build/#{name}" do |t|
sh "MAKEFLAGS=-j4 ../scripts/crosscompile #{name} #{args}"
sh "../scripts/crosscompile -j4 #{name} #{args}"
end
task :binaries => ["../build/#{name}"]
end
@@ -87,7 +87,6 @@ task :binaries => ["output/download"] do
end
def load_manual
YAML::ENGINE.yamler = 'syck'
YAML::load(File.open("content/3.manual/manual.yml"))
end
+261 -175
View File
@@ -2,124 +2,212 @@ headline: Tutorial
body:
- text: |
Twitter has a JSON API, so let's play with that. This URL gets
us the last 5 tweets about JSON:
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true'"
GitHub has a JSON API, so let's play with that. This URL gets us the last
5 commits from the jq repo.
- command: "curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5'"
result: |
{"completed_in":0.108,"max_id":247677287108067328,"max_id_str":"247677287108067328","next_page":"?page=2&max_id=247677287108067328&q=json&rpp=5&include_entities=1","page":1,"query":"json","refresh_url":"?since_id=247677287108067328&q=json&include_entities=1","results":[{"created_at":"Mon, 17 Sep 2012 12:44:01 +0000","entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/XRvh1ZVw","expanded_url":"http:\/\/jase.im\/Ri7I0M","display_url":"jase.im\/Ri7I0M","indices":[112,132]}],"user_mentions":[{"screen_name":"imagemechanics","name":"Jason Cotterell","id":57271393,"id_str":"57271393","indices":[3,18]}]},"from_user":"_AaronNg","from_user_id":79771704,"from_user_id_str":"79771704","from_user_name":"NgChenChong","geo":null,"id":247677287108067328,"id_str":"247677287108067328","iso_language_code":"en","metadata":{"result_type":"recent"},"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2523558403\/ek8mo4j4beq84iw28gjl_normal.jpeg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2523558403\/ek8mo4j4beq84iw28gjl_normal.jpeg","source":"&lt;a href=&quot;http:\/\/twitter.com\/&quot;&gt;web&lt;\/a&gt;","text":"RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt;.\nhttp:\/\/t.co\/XRvh1ZVw","to_user":null,"to_user_id":0,"to_user_id_str":"0","to_user_name":null}, ...
[
{
"sha": "d25341478381063d1c76e81b3a52e0592a7c997f",
"commit": {
"author": {
"name": "Stephen Dolan",
"email": "mu@netsoc.tcd.ie",
"date": "2013-06-22T16:30:59Z"
},
"committer": {
"name": "Stephen Dolan",
"email": "mu@netsoc.tcd.ie",
"date": "2013-06-22T16:30:59Z"
},
"message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
"tree": {
"sha": "6ab697a8dfb5a96e124666bf6d6213822599fb40",
"url": "https://api.github.com/repos/stedolan/jq/git/trees/6ab697a8dfb5a96e124666bf6d6213822599fb40"
},
"url": "https://api.github.com/repos/stedolan/jq/git/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
"comment_count": 0
},
"url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
"html_url": "https://github.com/stedolan/jq/commit/d25341478381063d1c76e81b3a52e0592a7c997f",
"comments_url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f/comments",
"author": {
"login": "stedolan",
...
- text: |
There's lots of info and no whitespace, so to make it a bit more
legible we pipe it through jq, telling jq to just spit the input
back at us using the expression `.`:
GitHub returns nicely formatted JSON. For servers that don't, it can be
helpful to pipe the response through jq to pretty-print it. The simplest
jq program is the expression `.`, which takes the input and produces it
unchanged as output.
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true' | jq '.'"
- command: "curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.'"
result: |
{
"since_id_str": "0",
"since_id": 0,
"results_per_page": 5,
"completed_in": 0.108,
"max_id": 247677287108067330,
"max_id_str": "247677287108067328",
"next_page": "?page=2&max_id=247677287108067328&q=json&rpp=5&include_entities=1",
"page": 1,
"query": "json",
"refresh_url": "?since_id=247677287108067328&q=json&include_entities=1",
"results": [
{
"from_user_name": "NgChenChong",
"from_user_id_str": "79771704",
"from_user_id": 79771704,
"from_user": "_AaronNg",
"iso_language_code": "en",
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt;.\nhttp://t.co/XRvh1ZVw",
"to_user": null
/* lots more fields... */
[
{
"sha": "d25341478381063d1c76e81b3a52e0592a7c997f",
"commit": {
"author": {
"name": "Stephen Dolan",
"email": "mu@netsoc.tcd.ie",
"date": "2013-06-22T16:30:59Z"
},
"committer": {
"name": "Stephen Dolan",
"email": "mu@netsoc.tcd.ie",
"date": "2013-06-22T16:30:59Z"
},
"message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
"tree": {
"sha": "6ab697a8dfb5a96e124666bf6d6213822599fb40",
"url": "https://api.github.com/repos/stedolan/jq/git/trees/6ab697a8dfb5a96e124666bf6d6213822599fb40"
},
"url": "https://api.github.com/repos/stedolan/jq/git/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
"comment_count": 0
},
/* lots more results... */
"url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
"html_url": "https://github.com/stedolan/jq/commit/d25341478381063d1c76e81b3a52e0592a7c997f",
"comments_url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f/comments",
"author": {
"login": "stedolan",
...
- text: |
We can use jq to extract just the first commit.
- command: "curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.[0]'"
result: |
{
"sha": "d25341478381063d1c76e81b3a52e0592a7c997f",
"commit": {
"author": {
"name": "Stephen Dolan",
"email": "mu@netsoc.tcd.ie",
"date": "2013-06-22T16:30:59Z"
},
"committer": {
"name": "Stephen Dolan",
"email": "mu@netsoc.tcd.ie",
"date": "2013-06-22T16:30:59Z"
},
"message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
"tree": {
"sha": "6ab697a8dfb5a96e124666bf6d6213822599fb40",
"url": "https://api.github.com/repos/stedolan/jq/git/trees/6ab697a8dfb5a96e124666bf6d6213822599fb40"
},
"url": "https://api.github.com/repos/stedolan/jq/git/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
"comment_count": 0
},
"url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
"html_url": "https://github.com/stedolan/jq/commit/d25341478381063d1c76e81b3a52e0592a7c997f",
"comments_url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f/comments",
"author": {
"login": "stedolan",
"id": 79765,
"avatar_url": "https://avatars.githubusercontent.com/u/79765?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/stedolan",
"html_url": "https://github.com/stedolan",
"followers_url": "https://api.github.com/users/stedolan/followers",
"following_url": "https://api.github.com/users/stedolan/following{/other_user}",
"gists_url": "https://api.github.com/users/stedolan/gists{/gist_id}",
"starred_url": "https://api.github.com/users/stedolan/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/stedolan/subscriptions",
"organizations_url": "https://api.github.com/users/stedolan/orgs",
"repos_url": "https://api.github.com/users/stedolan/repos",
"events_url": "https://api.github.com/users/stedolan/events{/privacy}",
"received_events_url": "https://api.github.com/users/stedolan/received_events",
"type": "User",
"site_admin": false
},
"committer": {
"login": "stedolan",
"id": 79765,
"avatar_url": "https://avatars.githubusercontent.com/u/79765?v=3",
"gravatar_id": "",
"url": "https://api.github.com/users/stedolan",
"html_url": "https://github.com/stedolan",
"followers_url": "https://api.github.com/users/stedolan/followers",
"following_url": "https://api.github.com/users/stedolan/following{/other_user}",
"gists_url": "https://api.github.com/users/stedolan/gists{/gist_id}",
"starred_url": "https://api.github.com/users/stedolan/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/stedolan/subscriptions",
"organizations_url": "https://api.github.com/users/stedolan/orgs",
"repos_url": "https://api.github.com/users/stedolan/repos",
"events_url": "https://api.github.com/users/stedolan/events{/privacy}",
"received_events_url": "https://api.github.com/users/stedolan/received_events",
"type": "User",
"site_admin": false
},
"parents": [
{
"sha": "54b9c9bdb225af5d886466d72f47eafc51acb4f7",
"url": "https://api.github.com/repos/stedolan/jq/commits/54b9c9bdb225af5d886466d72f47eafc51acb4f7",
"html_url": "https://github.com/stedolan/jq/commit/54b9c9bdb225af5d886466d72f47eafc51acb4f7"
},
{
"sha": "8b1b503609c161fea4b003a7179b3fbb2dd4345a",
"url": "https://api.github.com/repos/stedolan/jq/commits/8b1b503609c161fea4b003a7179b3fbb2dd4345a",
"html_url": "https://github.com/stedolan/jq/commit/8b1b503609c161fea4b003a7179b3fbb2dd4345a"
}
]
}
- text: |
Let's pull out the first tweet:
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true' | jq '.results[0]'"
For the rest of the examples, I'll leave out the `curl` command - it's not
going to change.
There's a lot of info we don't care about there, so we'll restrict it down
to the most interesting fields.
- command: "jq '.[0] | {message: .commit.message, name: .commit.committer.name}'"
result: |
{
"from_user_name": "NgChenChong",
"from_user_id_str": "79771704",
"from_user_id": 79771704,
"from_user": "_AaronNg",
"iso_language_code": "en",
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt;.\nhttp://t.co/XRvh1ZVw",
"to_user": null
/* lots more fields... */
},
"message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
"name": "Stephen Dolan"
}
- text: |
For the rest of the examples, I'll leave out the `curl` command - it's not going to change.
The `|` operator in jq feeds the output of one filter (`.[0]` which gets
the first element of the array in the response) into the input of another
(`{...}` which builds an object out of those fields). You can access
nested attributes, such as `.commit.message`.
There's still a lot of info we don't care about there, so we'll
restrict it down to the most interesting fields.
Now let's get the rest of the commits.
- command: "jq '.results[0] | {from_user, text}'"
- command: "jq '.[] | {message: .commit.message, name: .commit.committer.name}'"
result: |
{
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt;.\nhttp://t.co/XRvh1ZVw",
"from_user": "_AaronNg"
"message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
"name": "Stephen Dolan"
}
{
"message": "Reject all overlong UTF8 sequences.",
"name": "Stephen Dolan"
}
{
"message": "Fix various UTF8 parsing bugs.\n\nIn particular, parse bad UTF8 by replacing the broken bits with U+FFFD\nand resychronise correctly after broken sequences.",
"name": "Stephen Dolan"
}
{
"message": "Fix example in manual for `floor`. See #155.",
"name": "Stephen Dolan"
}
{
"message": "Document floor",
"name": "Nicolas Williams"
}
- text: |
The `|` operator in jq feeds the output of one filter
(`.results[0]` which gets the first element of the results
array) into the input of another (`{from_user, text}` which
builds an object of those two fields).
Now let's get the rest of the tweets:
- command: "jq '.results[] | {from_user, text}'"
result: |
{
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt;.\nhttp://t.co/XRvh1ZVw",
"from_user": "_AaronNg"
}
{
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt; -- http://t.co/Lhp92IqD",
"from_user": "blouerat"
}
{
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
"from_user": "cebu_iphone"
}
{
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and &lt;canvas&gt; http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
"from_user": "dieswaytoofast"
}
{
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
"from_user": "Leolik"
}
- text: |
`.results[]` returns each element of the results array, one at a
time, which are all fed into `{from_user, text}`.
`.[]` returns each element of the array returned in the response, one at a
time, which are all fed into
`{message: .commit.message, name: .commit.committer.name}`.
Data in jq is represented as streams of JSON values - every jq
expression runs for each value in its input stream, and can
@@ -128,114 +216,112 @@ body:
Streams are serialised by just separating JSON values with
whitespace. This is a `cat`-friendly format - you can just join
two JSON streams together and get a valid JSON stream.
If you want to get the output as a single array, you can tell jq to
"collect" all of the answers by wrapping the filter in square
brackets:
- command: "jq '[.results[] | {from_user, text}]'"
- command: "jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'"
result: |
[
{
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt;.\nhttp://t.co/XRvh1ZVw",
"from_user": "_AaronNg"
"message": "Merge pull request #163 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
"name": "Stephen Dolan"
},
{
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt; -- http://t.co/Lhp92IqD",
"from_user": "blouerat"
"message": "Reject all overlong UTF8 sequences.",
"name": "Stephen Dolan"
},
{
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
"from_user": "cebu_iphone"
"message": "Fix various UTF8 parsing bugs.\n\nIn particular, parse bad UTF8 by replacing the broken bits with U+FFFD\nand resychronise correctly after broken sequences.",
"name": "Stephen Dolan"
},
{
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and &lt;canvas&gt; http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
"from_user": "dieswaytoofast"
"message": "Fix example in manual for `floor`. See #155.",
"name": "Stephen Dolan"
},
{
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
"from_user": "Leolik"
"message": "Document floor",
"name": "Nicolas Williams"
}
]
- text: |
- - -
Next, let's try getting the URLs out of those API results as
well. In each tweet, the Twitter API includes a field called
"entities" which looks like this:
{
"user_mentions": [],
"urls": [{
"indices": [83, 103],
"display_url": "bit.ly/StniqT",
"expanded_url": "http://bit.ly/StniqT",
"url": "http://t.co/28Jesbio"
}],
"hashtags": [
{"indices": [108, 114], "text": "Apple" },
{"indices": [121, 129], "text": "Awesome"}
]
}
Next, let's try getting the URLs of the parent commits out of the
API results as well. In each commit, the GitHub API includes information
about "parent" commits. There can be one or many.
We want to pull out all of the "url" fields inside that array of url
objects, and make a simple list of strings to go along with the
"from_user" and "text" fields we already have.
"parents": [
{
"sha": "54b9c9bdb225af5d886466d72f47eafc51acb4f7",
"url": "https://api.github.com/repos/stedolan/jq/commits/54b9c9bdb225af5d886466d72f47eafc51acb4f7",
"html_url": "https://github.com/stedolan/jq/commit/54b9c9bdb225af5d886466d72f47eafc51acb4f7"
},
{
"sha": "8b1b503609c161fea4b003a7179b3fbb2dd4345a",
"url": "https://api.github.com/repos/stedolan/jq/commits/8b1b503609c161fea4b003a7179b3fbb2dd4345a",
"html_url": "https://github.com/stedolan/jq/commit/8b1b503609c161fea4b003a7179b3fbb2dd4345a"
}
]
- command: "jq '.results[] | {from_user, text, urls: [.entities.urls[].url]}'"
We want to pull out all of the "html_url" fields inside that array of parent
commits and make a simple list of strings to go along with the
"message" and "author" fields we already have.
- command: "jq '[.[] | {message: .commit.message, name: .commit.committer.name, parents: [.parents[].html_url]}]'"
result: |
{
"urls": [
"http://t.co/XRvh1ZVw"
],
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt;.\nhttp://t.co/XRvh1ZVw",
"from_user": "_AaronNg"
}
{
"urls": [
"http://t.co/Lhp92IqD"
],
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and &lt;canvas&gt; -- http://t.co/Lhp92IqD",
"from_user": "blouerat"
}
{
"urls": [
"http://t.co/7KALdWaX"
],
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
"from_user": "cebu_iphone"
}
{
"urls": [
"http://t.co/28Jesbio"
],
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and &lt;canvas&gt; http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
"from_user": "dieswaytoofast"
}
{
"urls": [
"http://t.co/M70snaIf"
],
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
"from_user": "Leolik"
}
[
{
"message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
"name": "Stephen Dolan",
"parents": [
"https://github.com/stedolan/jq/commit/54b9c9bdb225af5d886466d72f47eafc51acb4f7",
"https://github.com/stedolan/jq/commit/8b1b503609c161fea4b003a7179b3fbb2dd4345a"
]
},
{
"message": "Reject all overlong UTF8 sequences.",
"name": "Stephen Dolan",
"parents": [
"https://github.com/stedolan/jq/commit/ff48bd6ec538b01d1057be8e93b94eef6914e9ef"
]
},
{
"message": "Fix various UTF8 parsing bugs.\n\nIn particular, parse bad UTF8 by replacing the broken bits with U+FFFD\nand resychronise correctly after broken sequences.",
"name": "Stephen Dolan",
"parents": [
"https://github.com/stedolan/jq/commit/54b9c9bdb225af5d886466d72f47eafc51acb4f7"
]
},
{
"message": "Fix example in manual for `floor`. See #155.",
"name": "Stephen Dolan",
"parents": [
"https://github.com/stedolan/jq/commit/3dcdc582ea993afea3f5503a78a77675967ecdfa"
]
},
{
"message": "Document floor",
"name": "Nicolas Williams",
"parents": [
"https://github.com/stedolan/jq/commit/7c4171d414f647ab08bcd20c76a4d8ed68d9c602"
]
}
]
- text: |
Here we're making an object as before, but this time the urls
field is being set to `[.entities.urls[].url]`, which collects
all of the URLs defined in the entities object.
Here we're making an object as before, but this time the `parents`
field is being set to `[.parents[].html_url]`, which collects
all of the parent commit URLs defined in the parents object.
- text: |
- - -
Here endeth the tutorial! There's lots more to play with, go
Here endeth the tutorial! There's lots more to play with. Go
read [the manual](../manual/) if you're interested, and [download
jq](../download/) if you haven't already.
jq](../download/) if you haven't already.
+50 -23
View File
@@ -16,7 +16,8 @@ body:
### Linux
* Binaries for [64-bit](linux64/jq) or [32-bit](linux32/jq) systems.
* jq 1.4 binaries for [64-bit](linux64/jq) or [32-bit](linux32/jq) systems.
* jq 1.3 binaries for [64-bit](linux64/jq-1.3/jq) or [32-bit](linux32/jq-1.3/jq) systems.
* For Arch users, a PKGBUILD for jq-1.1 is in the
[AUR](https://aur.archlinux.org/packages.php?ID=63849), as
@@ -27,22 +28,42 @@ body:
manually by following instructions on [Arch Linux's
Wiki](https://wiki.archlinux.org/index.php/Arch_UseRepository).
* jq 1.2 is [in Debian](http://packages.debian.org/jq)
* jq 1.4 is in the official [Debian](https://packages.debian.org/jq) and
[Ubuntu](http://packages.ubuntu.com/jq) repositories. Install using
`sudo apt-get install jq`.
* jq 1.4 is [in Debian](http://packages.debian.org/jq)
* jq 1.3.2 is in the official Fedora repository. You can install using
`sudo yum install jq`.
### OS X
* `brew install jq` using [homebrew](http://mxcl.github.com/homebrew/)
* Or, grab prebuilt [64-bit binaries](osx64/jq) or [32-bit
* Or, grab prebuilt jq 1.4 [64-bit binaries](osx64/jq) or [32-bit
binaries](osx32/jq)
* Or, grab prebuilt jq 1.3 [64-bit binaries](osx64/jq-1.3/jq) or [32-bit
binaries](osx32/jq-1.3/jq)
### Solaris
* `pkgutil -i jq` in [OpenCSW](http://www.opencsw.org/p/jq) for Solaris 10+, Sparc and x86
* jq 1.4 executables for Solaris 11 [64-bit](solaris11-64/jq) or [32-bit](solaris11-32/jq)
### Windows
* Executables for [64-bit](win64/jq.exe) or [32-bit](win32/jq.exe)
* `chocolatey install jq` using [Chocolatey NuGet](https://chocolatey.org/)
### From source on Linux or OS X
* jq 1.4 executables for [64-bit](win64/jq.exe) or [32-bit](win32/jq.exe)
* [Source tarball for jq $JQ_VERSION](source/jq-$JQ_VERSION.tar.gz)
* jq 1.3 executables for [64-bit](win64/jq-1.3/jq-1.3.exe) or [32-bit](win32/jq-1.3/jq-1.3.exe)
### From source on Linux, OS X, Cygwin, and other POSIX-like operating systems
* [Source tarball for jq 1.4](source/jq-1.4.tar.gz)
You can build it using the usual `./configure && make && sudo
make install` rigmarole.
@@ -51,7 +72,7 @@ body:
git clone https://github.com/stedolan/jq.git
cd jq
autoreconf
autoreconf -i
./configure
make
sudo make install
@@ -59,32 +80,38 @@ body:
To build it from a git clone, you'll need to install a few
packages first:
* [Flex](http://www.gnu.org/software/flex/)
* [Bison](http://www.gnu.org/software/bison/)
* [GCC](http://gcc.gnu.org)
* [Make](http://www.gnu.org/software/make)
* [Autotools](http://www.gnu.org/software/automake)
* [Flex](http://flex.sourceforge.net/)
* [Bison](https://www.gnu.org/software/bison/)
* [GCC](https://gcc.gnu.org)
* [Make](https://www.gnu.org/software/make/)
* [Autotools](https://www.gnu.org/software/automake/)
For Linux systems, these will all be in your system's package
manager, and if you do development on the machine they're most
likely already installed.
On OS X, these are all included in Apple's command line tools, which
can be installed from [Xcode](http://developer.apple.com/technologies/tools/).
However, you may find that you need a newer version of Bison than the one provided
by Apple. This can be found in [Homebrew](http://mxcl.github.com/homebrew/)
or [MacPorts](http://macports.org/).
On OS X, these are all included in Apple's command line tools, which can
be installed from [Xcode](https://developer.apple.com/xcode/). However,
you may find that you need a newer version of Bison than the one provided
by Apple. This can be found in [Homebrew](http://brew.sh) or
[MacPorts](https://macports.org/).
`flex` and `bison` are used to generate the lexer and parser for
jq, and some python scripts generate the UTF8 encoding tables
needed for JSON parsing.
jq. For jq 1.5, neither is required if you use `./configure
--disable-maintainer-mode` instead of `./configure`. This flag says to use
the pre-generated lexer and parser that come with the code.
#### Building the documentation
jq's documentation is compiled into static HTML using
[Bonsai](http://www.tinytree.info). To view the documentation
locally, run `rake serve` from the docs/ subdirectory. You'll
need a few Ruby dependencies, which can be installed by
following the instructions in `docs/README.md`.
[Bonsai](http://www.tinytree.info). To view the documentation
locally, run `rake serve` (or `bundle exec rake serve`) from the
docs/ subdirectory. To build the docs just `rake build` from the
docs subdirectory. You'll need a few Ruby dependencies, which can
be installed by following the instructions in `docs/README.md`.
The man page is built by `make jq.1`, or just `make`, also from
the YAML docs, and you'll still need the Ruby dependencies to
build the manpage.
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+23 -6
View File
@@ -1,9 +1,9 @@
headline: jq
blurb: |
jq is a lightweight and flexible command-line JSON processor.
body1: |
jq is like `sed` for JSON data - you can use it to slice and filter
@@ -14,21 +14,38 @@ body2: |
jq is written in portable C, and it has zero runtime
dependencies. You can download a single binary, `scp` it to a far away
machine, and expect it to work.
machine of the same type, and expect it to work.
body3: |
jq can mangle the data format that you have into the one that you
want with very little effort, and the program to do so is often
shorter and simpler than you'd expect.
tail: |
Go read the [tutorial](tutorial/) for more, or the [manual](manual/)
for *way* more.
Ask questions on [stackoverflow](https://stackoverflow.com/) using the [jq
tag](https://stackoverflow.com/questions/tagged/jq), or on the
[#jq](http://irc.lc/freenode/%23jq/) channel on
[Freenode](https://webchat.freenode.net/).
news:
- date: 2015-01-01
body: |
jq 1.5rc1 Get it on the
[releases](https://github.com/stedolan/jq/releases) page.
- date: 2014-06-08
body: |
jq 1.4 (finally) released! Get it on the [download](download/) page.
- date: 2013-05-19
body: |
jq 1.3 (finally) released! Get it on the [download](download/) page.
jq 1.3 released.
+2 -2
View File
@@ -9,8 +9,8 @@ reducing and otherwise mangling JSON documents.
This version of `jq` was built without a manual, so this manpage is a
stub. For full documentation of the `jq` language, see:
http://stedolan.github.com/jq
https://stedolan.github.io/jq
## BUGS
Presumably. Report them or discuss them at:
+1 -1
View File
@@ -4,7 +4,7 @@
# This line is modified by the Makefile. To change the version number,
# edit the Autoconf version number at the top of configure.ac
jq_version: "1.3"
jq_version: "1.4-2-g15c4a7f-dirty"
root: '/jq'
footer: |
+10 -1
View File
@@ -10,6 +10,7 @@
<img src="{{root}}/jq.png" style="width: 400px; height: 220px; float: left; margin-right: 60px">
<div id="blurb">
{{blurb | markdownify}}
<div class="btn-group" style="float:right">
<a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" href="#">
Download jq-{{jq_version}}
@@ -18,10 +19,18 @@
<ul class="dropdown-menu">
<li><a href="{{root}}/download/linux64/jq">Linux (64-bit)</a></li>
<li><a href="{{root}}/download/osx64/jq">OS X (64-bit)</a></li>
<li><a href="{{root}}/download/">Other platforms and source</a></li>
<li><a href="{{root}}/download/solaris11-64/jq">Solaris (64-bit)</a></li>
<li><a href="{{root}}/download/win64/jq.exe">Windows (64-bit)</a></li>
<li><a href="{{root}}/download/">Other platforms, older versions, and source</a></li>
</ul>
</div>
<div class="btn-group" style="float:right">
<a class="btn btn-primary" href="https://jqplay.org">
Try online at jqplay.org!
</a>
</div>
</div>
<div style="clear:both;"></div>
</div>
+15 -3
View File
@@ -35,6 +35,17 @@
}
});
});
// add "Run" button to execute examples on jqplay.org
$(function() {
$.each($('table.manual-example'), function(index, value) {
$value = $(value)
var j = $value.find('tr:nth-child(2) td:first').text();
var q = $value.find('.jqprogram').text().replace(/^jq /, '').replace(/^'(.+)'$/, '$1');
var url = 'https://jqplay.org/jq?q=' + encodeURIComponent(q) +'&j=' + encodeURIComponent(j)
var $last_tr = $value.find('tr:last');
$last_tr.after('<tr><th><a href="' + url + '" class="btn btn-primary btn-small">Run</a></th><th></th></tr><tr><th></th><th></th></tr>');
});
});
</script>
<input type="text"
class="input-medium search-query"
@@ -46,6 +57,7 @@
</div>
<div class="span9">
<h1>{{headline}}</h1>
{{ history | markdownify }}
{{ body | markdownify }}
{% for section in sections %}
<section id="{{section.title | sanitize}}">
@@ -70,8 +82,8 @@
{% for example in entry.examples %}
<table class="manual-example">
<tr><th></th><td class="jqprogram">jq '{{example.program}}'</td></tr>
<tr><th>Input</th><td>{{example.input}}</td></tr>
<tr><th></th><td class="jqprogram">jq '{{example.program | escape}}'</td></tr>
<tr><th>Input</th><td>{{example.input | escape}}</td></tr>
{% unless example.output[0] %}
<tr>
<th>Output</th>
@@ -85,7 +97,7 @@
{% else %}
<th></th>
{% endif %}
<td>{{output}}</td>
<td>{{output | escape}}</td>
</tr>
{% endfor %}
+2
View File
@@ -17,6 +17,8 @@
{% endfor %}
<li><a href="https://github.com/stedolan/jq/issues">Issues</a></li>
<li><a href="https://github.com/stedolan/jq">Source</a></li>
<li><a href="https://jqplay.org">Try online!</a></li>
<li><a href="https://raw.githubusercontent.com/stedolan/jq/master/NEWS">News</a></li>
</ul>
</div>
</div>
+112
View File
@@ -0,0 +1,112 @@
#ifndef EXEC_STACK_H
#define EXEC_STACK_H
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "jv_alloc.h"
/*
* The stack is a directed forest of variably sized blocks. Each block has a
* "next" block which is at a higher memory address, or 0 if the block has no
* "next" block. More than one block may have no "next" block. A block may be
* the "next" block of more than one other block. Pushed blocks are added at
* the low-address end of the stack.
*
* Stack pointers are negative integers that are offsets relative to "mem_end",
* the end of the allocated region. The stack "bound" is the stack pointer of
* the last block that would be able to fit in the currently allocated region.
* The stack "limit" is the stack pointer of the last block currently in the
* stack. The stack pointer of the "next" block is stored directly below each
* block.
*
* <- mem_end = 0x100
* 0xF8 +------------+
* 0xF0 | |
* 0xE8 +------------+ <- stack_ptr1 = -0x18
* 0xE0 next = 0
* 0xD8 +------------+
* 0xD0 | |
* 0xC8 | |
* 0xC0 +------------+ <- stack_ptr2 = limit = -0x40
* 0xB8 next = -0x18
* 0xB0
* 0xA8 <- bound = -0x58
* 0xA0
*/
struct determine_alignment {
char x;
union { int i; double d; uint64_t u64; size_t sz; void* ptr; } u;
};
enum {ALIGNMENT = offsetof(struct determine_alignment, u)};
static size_t align_round_up(size_t sz) {
return ((sz + (ALIGNMENT - 1)) / ALIGNMENT) * ALIGNMENT;
}
typedef int stack_ptr;
struct stack {
char* mem_end; // one-past-the-end of allocated region
stack_ptr bound;
stack_ptr limit; // 0 - stack is empty
};
static void stack_init(struct stack* s) {
s->mem_end = 0;
s->bound = ALIGNMENT;
s->limit = 0;
}
static void stack_reset(struct stack* s) {
assert(s->limit == 0 && "stack freed while not empty");
char* mem_start = s->mem_end - ( -s->bound + ALIGNMENT);
free(mem_start);
stack_init(s);
}
static int stack_pop_will_free(struct stack* s, stack_ptr p) {
return p == s->limit;
}
static void* stack_block(struct stack* s, stack_ptr p) {
return (void*)(s->mem_end + p);
}
static stack_ptr* stack_block_next(struct stack* s, stack_ptr p) {
return &((stack_ptr*)stack_block(s, p))[-1];
}
static void stack_reallocate(struct stack* s, size_t sz) {
int old_mem_length = -(s->bound) + ALIGNMENT;
char* old_mem_start = s->mem_end - old_mem_length;
int new_mem_length = align_round_up((old_mem_length + sz + 256) * 2);
char* new_mem_start = jv_mem_realloc(old_mem_start, new_mem_length);
memmove(new_mem_start + (new_mem_length - old_mem_length),
new_mem_start, old_mem_length);
s->mem_end = new_mem_start + new_mem_length;
s->bound = -(new_mem_length - ALIGNMENT);
}
static stack_ptr stack_push_block(struct stack* s, stack_ptr p, size_t sz) {
int alloc_sz = align_round_up(sz) + ALIGNMENT;
stack_ptr r = s->limit - alloc_sz;
if (r < s->bound) {
stack_reallocate(s, alloc_sz);
}
s->limit = r;
*stack_block_next(s, r) = p;
return r;
}
static stack_ptr stack_pop_block(struct stack* s, stack_ptr p, size_t sz) {
stack_ptr r = *stack_block_next(s, p);
if (p == s->limit) {
int alloc_sz = align_round_up(sz) + ALIGNMENT;
s->limit += alloc_sz;
}
return r;
}
#endif
+725 -196
View File
File diff suppressed because it is too large. Load diff
-20
View File
@@ -1,20 +0,0 @@
#ifndef EXECUTE_H
#define EXECUTE_H
#include "bytecode.h"
struct bytecode* jq_compile(const char* str);
/* args must be an array of the form [{name:"foo", value:"thing"}, {name:"bar",value:3}] */
struct bytecode* jq_compile_args(const char* str, jv args);
typedef struct jq_state jq_state;
enum {JQ_DEBUG_TRACE = 1};
void jq_init(struct bytecode* bc, jv value, jq_state **, int flags);
jv jq_next(jq_state *);
void jq_teardown(jq_state **);
#endif
-172
View File
@@ -1,172 +0,0 @@
#ifndef FORKABLE_STACK_H
#define FORKABLE_STACK_H
#include <stddef.h>
#include <assert.h>
#include <string.h>
#include "jv_alloc.h"
struct forkable_stack_header {
/* distance in bytes between this header and the header
of the next object on the stack */
int next_delta;
};
#define FORKABLE_STACK_HEADER struct forkable_stack_header fk_header_
struct forkable_stack {
// Stack grows down from stk+length
char* stk;
// stk+length is just past end of allocated area
// stk = jv_mem_alloc(length)
int length;
// stk+pos is header of top object, or stk+length if empty
int pos;
// everything after-or-including stk+savedlimit must be preserved
int savedlimit;
};
static void forkable_stack_check(struct forkable_stack* s) {
assert(s->stk);
assert(s->length > 0);
assert(s->pos >= 0 && s->pos <= s->length);
assert(s->savedlimit >= 0 && s->savedlimit <= s->length);
}
static int forkable_stack_empty(struct forkable_stack* s) {
return s->pos == s->length;
}
static void forkable_stack_init(struct forkable_stack* s, size_t sz) {
s->stk = jv_mem_alloc(sz);
s->length = sz;
s->pos = s->length;
s->savedlimit = s->length;
forkable_stack_check(s);
}
static void forkable_stack_free(struct forkable_stack* s) {
assert(forkable_stack_empty(s));
assert(s->savedlimit == s->length);
jv_mem_free(s->stk);
s->stk = 0;
}
static void* forkable_stack_push(struct forkable_stack* s, size_t sz_size) {
assert(sz_size > 0 && sz_size % sizeof(struct forkable_stack_header) == 0);
int size = (int)sz_size;
forkable_stack_check(s);
int curr = s->pos < s->savedlimit ? s->pos : s->savedlimit;
if (curr - size < 0) {
int oldlen = s->length;
s->length = (size + oldlen + 1024) * 2;
s->stk = jv_mem_realloc(s->stk, s->length);
int shift = s->length - oldlen;
memmove(s->stk + shift, s->stk, oldlen);
s->pos += shift;
s->savedlimit += shift;
curr += shift;
}
int newpos = curr - size;
assert(newpos < s->pos);
void* ret = (void*)(s->stk + newpos);
((struct forkable_stack_header*)ret)->next_delta = s->pos - newpos;
s->pos = newpos;
forkable_stack_check(s);
return ret;
}
static void* forkable_stack_peek(struct forkable_stack* s) {
assert(!forkable_stack_empty(s));
forkable_stack_check(s);
return (void*)(s->stk + s->pos);
}
static void* forkable_stack_peek_next(struct forkable_stack* s, void* top) {
forkable_stack_check(s);
struct forkable_stack_header* elem = top;
int elempos = (char*)top - s->stk;
assert(elempos >= 0 && elempos < s->length);
assert(elempos + elem->next_delta <= s->length);
if (elempos + elem->next_delta < s->length) {
return (void*)(s->stk + elempos + elem->next_delta);
} else {
return 0;
}
}
// Returns 1 if the next forkable_stack_pop will permanently remove an
// object from the stack (i.e. the top object was not saved with a fork)
static int forkable_stack_pop_will_free(struct forkable_stack* s) {
return s->pos < s->savedlimit;
}
static void forkable_stack_pop(struct forkable_stack* s) {
forkable_stack_check(s);
struct forkable_stack_header* elem = forkable_stack_peek(s);
int reclaim_upto = s->pos + elem->next_delta < s->savedlimit ?
s->pos + elem->next_delta : s->savedlimit;
assert(reclaim_upto <= s->length);
int reclaimed = reclaim_upto > s->pos ? reclaim_upto - s->pos : 0;
assert(0 <= reclaimed && s->pos + reclaimed <= s->length);
// s->pos <= i < reclaim_upto means that position i is to be freed
assert((reclaimed > 0) == forkable_stack_pop_will_free(s));
int new_pos = s->pos + elem->next_delta;
jv_mem_invalidate(elem, reclaimed);
s->pos = new_pos;
}
struct forkable_stack_state {
// We save the previous pos, savedlimit as
// length-pos, length-savedlimit since these
// values are stable across stack reallocations.
int prev_pos_delta, prev_limit_delta;
};
static void forkable_stack_save(struct forkable_stack* s, struct forkable_stack_state* state) {
forkable_stack_check(s);
state->prev_pos_delta = s->length - s->pos;
state->prev_limit_delta = s->length - s->savedlimit;
if (s->pos < s->savedlimit) s->savedlimit = s->pos;
}
static void forkable_stack_switch(struct forkable_stack* s, struct forkable_stack_state* state) {
forkable_stack_check(s);
int curr_pos = s->pos;
s->pos = s->length - state->prev_pos_delta;
state->prev_pos_delta = s->length - curr_pos;
int curr_limit = s->savedlimit;
if (curr_pos < curr_limit) s->savedlimit = curr_pos;
//state->prevlimit = curr_limit; FIXME clean up
forkable_stack_check(s);
}
static void forkable_stack_restore(struct forkable_stack* s, struct forkable_stack_state* state) {
forkable_stack_check(s);
assert(s->savedlimit <= s->length - state->prev_pos_delta);
assert(s->savedlimit <= s->length - state->prev_limit_delta);
s->pos = s->length - state->prev_pos_delta;
s->savedlimit = s->length - state->prev_limit_delta;
forkable_stack_check(s);
}
typedef int stack_idx;
static stack_idx forkable_stack_to_idx(struct forkable_stack* s, void* ptr) {
char* item = ptr;
int pos = item - s->stk;
assert(pos >= 0 && pos < s->length);
return s->length - pos;
}
static void* forkable_stack_from_idx(struct forkable_stack* s, stack_idx idx) {
assert(idx >= 1 && idx <= s->length);
return &s->stk[s->length - idx];
}
#endif
-104
View File
@@ -1,104 +0,0 @@
#ifndef FRAME_LAYOUT_H
#include "forkable_stack.h"
#include "bytecode.h"
struct closure {
struct bytecode* bc;
stack_idx env;
};
struct continuation {
struct bytecode* bc;
stack_idx env;
uint16_t* retaddr;
};
typedef union frame_elem {
FORKABLE_STACK_HEADER;
struct continuation cont;
struct closure closure;
jv jsonval;
} *frame_ptr;
/*
* Frame layout
* fr[0] - FORKABLE_STACK_HEADER (next pointer)
* fr[1] - self (used to store return addresses, etc)
* fr[2...nclosures+2] - closure params
* fr[nclosures+2..nclosures+nlocals+2] - local variables
*/
static int frame_size(struct bytecode* bc) {
return sizeof(union frame_elem) * (bc->nclosures + bc->nlocals + 2);
}
static struct continuation* frame_self(frame_ptr fr) {
return &fr[1].cont;
}
static struct closure* frame_closure_arg(frame_ptr fr, int closure) {
assert(closure >= 0);
assert(closure < frame_self(fr)->bc->nclosures);
return &fr[2+closure].closure;
}
static jv* frame_local_var(frame_ptr fr, int var) {
assert(var >= 0);
assert(var < frame_self(fr)->bc->nlocals);
return &fr[2 + frame_self(fr)->bc->nclosures + var].jsonval;
}
static frame_ptr frame_current(struct forkable_stack* stk) {
frame_ptr fp = forkable_stack_peek(stk);
if (forkable_stack_peek_next(stk, fp)) {
struct bytecode* bc = frame_self(forkable_stack_peek_next(stk, fp))->bc;
assert(frame_self(fp)->retaddr >= bc->code && frame_self(fp)->retaddr < bc->code + bc->codelen);
} else {
assert(frame_self(fp)->retaddr == 0);
}
return fp;
}
static struct bytecode* frame_current_bytecode(struct forkable_stack* stk) {
return frame_self(frame_current(stk))->bc;
}
static uint16_t** frame_current_retaddr(struct forkable_stack* stk) {
return &frame_self(frame_current(stk))->retaddr;
}
static frame_ptr frame_get_parent(struct forkable_stack* stk, frame_ptr fr) {
return forkable_stack_from_idx(stk, frame_self(fr)->env);
}
static frame_ptr frame_get_level(struct forkable_stack* stk, frame_ptr fr, int level) {
for (int i=0; i<level; i++) {
fr = frame_get_parent(stk, fr);
}
return fr;
}
static frame_ptr frame_push(struct forkable_stack* stk, struct closure cl, uint16_t* retaddr) {
frame_ptr fp = forkable_stack_push(stk, frame_size(cl.bc));
struct continuation* cc = frame_self(fp);
cc->bc = cl.bc;
cc->env = cl.env;
cc->retaddr = retaddr;
for (int i=0; i<cl.bc->nlocals; i++) {
*frame_local_var(fp, i) = jv_invalid();
}
return fp;
}
static void frame_pop(struct forkable_stack* stk) {
frame_ptr fp = frame_current(stk);
if (forkable_stack_pop_will_free(stk)) {
int nlocals = frame_self(fp)->bc->nlocals;
for (int i=0; i<nlocals; i++) {
jv_free(*frame_local_var(fp, i));
}
}
forkable_stack_pop(stk);
}
#endif
+112
View File
@@ -0,0 +1,112 @@
#define _GNU_SOURCE /* for RTLD_NEXT */
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static FILE *fail;
static FILE *fail_read;
static FILE *fail_write;
static FILE *fail_close;
static int error;
static FILE * (*real_fopen)(const char *, const char *);
static int (*real_fclose)(FILE *);
static int (*real_ferror)(FILE *);
static void (*real_clearerr)(FILE *);
static char * (*real_fgets)(char *, int, FILE *);
static size_t (*real_fread)(void *, size_t, size_t, FILE *);
static size_t (*real_fwrite)(const void *, size_t, size_t, FILE *);
#define GET_REAL(sym) \
do { \
if (real_ ## sym == 0) { \
real_ ## sym = dlsym(RTLD_NEXT, #sym); \
assert(real_ ## sym != 0); \
} \
} while (0)
#define dbg_write(msg) (void)write(2, msg, sizeof(msg) - 1)
#define dbg() \
do { \
dbg_write("here: "); \
dbg_write(__func__); \
dbg_write("!\n"); \
} while (0)
FILE *fopen(const char *path, const char *mode) {
GET_REAL(fopen);
fail = fail_read = fail_write = fail_close = 0;
FILE *f = real_fopen(path, mode);
error = EIO;
if (strcmp(path, "fail_read") == 0) {
fail = fail_read = f;
} else if (strncmp(path, "fail_write", sizeof("fail_write") - 1) == 0) {
// Not that jq opens files for write anyways...
fail = fail_write = f;
if (strcmp(path, "fail_write_enospc") == 0)
error = ENOSPC;
} else if (strncmp(path, "fail_close", sizeof("fail_close") - 1) == 0) {
fail = fail_close = f;
if (strcmp(path, "fail_close_enospc") == 0)
error = ENOSPC;
}
return f;
}
int fclose(FILE *f) {
GET_REAL(fclose);
int res = real_fclose(f);
if (fail_close == f) {
fail = fail_read = fail_write = fail_close = 0;
return EOF;
}
return res;
}
char * fgets(char *buf, int len, FILE *f) {
GET_REAL(fgets);
char *res = real_fgets(buf, len, f);
if (fail_read == f)
return 0;
return res;
}
size_t fread(void *buf, size_t sz, size_t nemb, FILE *f) {
GET_REAL(fread);
size_t res = real_fread(buf, sz, nemb, f);
if (fail_read == f)
return 0;
return res;
}
size_t fwrite(const void *buf, size_t sz, size_t nemb, FILE *f) {
GET_REAL(fwrite);
size_t res = real_fwrite(buf, sz, nemb, f);
if (fail_write == f)
return 0;
return res;
}
int ferror(FILE *f) {
GET_REAL(ferror);
int res = real_ferror(f);
if (fail == f) {
errno = error;
return 1;
}
return res;
}
void clearerr(FILE *f) {
GET_REAL(clearerr);
real_clearerr(f);
if (fail == f) {
fail = fail_read = fail_write = fail_close = 0;
error = 0;
}
}
+2 -2
View File
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "JQ" "1" "May 2013" "" ""
.TH "JQ" "1" "August 2015" "" ""
.
.SH "NAME"
\fBjq\fR \- Command\-line JSON processor
@@ -16,7 +16,7 @@ This version of \fBjq\fR was built without a manual, so this manpage is a stub\.
.
.nf
http://stedolan\.github\.com/jq
https://stedolan\.github\.io/jq
.
.fi
.
+3075
View File
File diff suppressed because it is too large. Load diff
+60
View File
@@ -0,0 +1,60 @@
#ifndef JQ_H
#define JQ_H
#include <stdio.h>
#include <jv.h>
enum {JQ_DEBUG_TRACE = 1};
typedef struct jq_state jq_state;
typedef void (*jq_msg_cb)(void *, jv);
jq_state *jq_init(void);
void jq_set_error_cb(jq_state *, jq_msg_cb, void *);
void jq_get_error_cb(jq_state *, jq_msg_cb *, void **);
void jq_set_nomem_handler(jq_state *, void (*)(void *), void *);
jv jq_format_error(jv msg);
void jq_report_error(jq_state *, jv);
int jq_compile(jq_state *, const char*);
int jq_compile_args(jq_state *, const char*, jv);
void jq_dump_disassembly(jq_state *, int);
void jq_start(jq_state *, jv value, int);
jv jq_next(jq_state *);
void jq_teardown(jq_state **);
typedef jv (*jq_input_cb)(jq_state *, void *);
void jq_set_input_cb(jq_state *, jq_input_cb, void *);
void jq_get_input_cb(jq_state *, jq_input_cb *, void **);
void jq_set_debug_cb(jq_state *, jq_msg_cb, void *);
void jq_get_debug_cb(jq_state *, jq_msg_cb *, void **);
void jq_set_attrs(jq_state *, jv);
jv jq_get_attrs(jq_state *);
jv jq_get_jq_origin(jq_state *);
jv jq_get_prog_origin(jq_state *);
jv jq_get_lib_dirs(jq_state *);
void jq_set_attr(jq_state *, jv, jv);
jv jq_get_attr(jq_state *, jv);
/*
* We use char * instead of jf for filenames here because filenames
* should be in the process' locale's codeset, which may not be UTF-8,
* whereas jv string values must be in UTF-8. This way the caller
* doesn't have to perform any codeset conversions.
*/
typedef struct jq_util_input_state jq_util_input_state;
typedef void (*jq_util_msg_cb)(void *, const char *);
jq_util_input_state *jq_util_input_init(jq_util_msg_cb, void *);
void jq_util_input_set_parser(jq_util_input_state *, jv_parser *, int);
void jq_util_input_free(jq_util_input_state **);
void jq_util_input_add_input(jq_util_input_state *, const char *);
int jq_util_input_errors(jq_util_input_state *);
jv jq_util_input_next_input(jq_util_input_state *);
jv jq_util_input_next_input_cb(jq_state *, void *);
jv jq_util_input_get_position(jq_state*);
jv jq_util_input_get_current_filename(jq_state*);
jv jq_util_input_get_current_line(jq_state*);
#endif /* !JQ_H */
+8 -3
View File
@@ -5,7 +5,7 @@ Name: jq
Version: %{myver}
Release: %{myrel}%{?dist}
Source0: jq-%{myver}.tar.gz
URL: https://github.com/stedolan/jq
URL: https://stedolan.github.io/jq
License: BSD
AutoReqProv: no
#BuildPrereq: autoconf, libtool, automake, flex, bison, python
@@ -52,11 +52,16 @@ rm -rf %{buildroot}
%endif
%{_datadir}/doc/%{name}/AUTHORS
%{_datadir}/doc/%{name}/COPYING
%{_datadir}/doc/%{name}/INSTALL
%{_datadir}/doc/%{name}/NEWS
%{_datadir}/doc/%{name}/README
%{_datadir}/doc/%{name}/README.md
%{_datadir}/man/man1/jq.1
%{_includedir}/jq.h
%{_includedir}/jv.h
%{_prefix}/lib/libjq.a
%{_prefix}/lib/libjq.la
%{_prefix}/lib/libjq.so
%{_prefix}/lib/libjq.so.1
%{_prefix}/lib/libjq.so.1.0.4
%changelog
+2
View File
@@ -1,5 +1,7 @@
#ifndef JQ_PARSER_H
#define JQ_PARSER_H
#include "locfile.h"
#include "compile.h"
int jq_parse(struct locfile* source, block* answer);
int jq_parse_library(struct locfile* locations, block* answer);
+143 -38
View File
@@ -3,15 +3,23 @@
#include <string.h>
#include <stdlib.h>
#include "jv.h"
#include "execute.h"
#include "jq.h"
static void jv_test();
static void run_jq_tests();
static void run_jq_tests(jv, int, FILE *);
int jq_testsuite(int argc, char* argv[]) {
int jq_testsuite(jv libdirs, int verbose, int argc, char* argv[]) {
FILE *testdata = stdin;
jv_test();
run_jq_tests(stdin);
if (argc > 0) {
testdata = fopen(argv[0], "r");
if (!testdata) {
perror("fopen");
exit(1);
}
}
run_jq_tests(libdirs, verbose, testdata);
return 0;
}
@@ -22,36 +30,123 @@ static int skipline(const char* buf) {
return 0;
}
static void run_jq_tests(FILE *testdata) {
static int checkerrormsg(const char* buf) {
return strcmp(buf, "%%FAIL\n") == 0;
}
static int checkfail(const char* buf) {
return strcmp(buf, "%%FAIL\n") == 0 || strcmp(buf, "%%FAIL IGNORE MSG\n") == 0;
}
struct err_data {
char buf[4096];
};
static void test_err_cb(void *data, jv e) {
struct err_data *err_data = data;
if (jv_get_kind(e) != JV_KIND_STRING)
e = jv_dump_string(e, JV_PRINT_INVALID);
if (!strncmp(jv_string_value(e), "jq: error", sizeof("jq: error") - 1))
snprintf(err_data->buf, sizeof(err_data->buf), "%s", jv_string_value(e));
if (strchr(err_data->buf, '\n'))
*(strchr(err_data->buf, '\n')) = '\0';
jv_free(e);
}
static void run_jq_tests(jv lib_dirs, int verbose, FILE *testdata) {
char prog[4096];
char buf[4096];
struct err_data err_msg;
int tests = 0, passed = 0, invalid = 0;
unsigned int lineno = 0;
int must_fail = 0;
int check_msg = 0;
jq_state *jq = NULL;
jq = jq_init();
assert(jq);
if (jv_get_kind(lib_dirs) == JV_KIND_NULL)
lib_dirs = jv_array();
jq_set_attr(jq, jv_string("JQ_LIBRARY_PATH"), lib_dirs);
while (1) {
if (!fgets(buf, sizeof(buf), testdata)) break;
if (skipline(buf)) continue;
if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
printf("Testing %s\n", buf);
if (!fgets(prog, sizeof(prog), testdata)) break;
lineno++;
if (skipline(prog)) continue;
if (checkfail(prog)) {
must_fail = 1;
check_msg = checkerrormsg(prog);
jq_set_error_cb(jq, test_err_cb, &err_msg);
continue;
}
if (prog[strlen(prog)-1] == '\n') prog[strlen(prog)-1] = 0;
printf("Testing '%s' at line number %u\n", prog, lineno);
int pass = 1;
tests++;
struct bytecode* bc = jq_compile(buf);
if (!bc) {invalid++; continue;}
printf("Disassembly:\n");
dump_disassembly(2, bc);
printf("\n");
fgets(buf, sizeof(buf), testdata);
int compiled = jq_compile(jq, prog);
if (must_fail) {
jq_set_error_cb(jq, NULL, NULL);
if (!fgets(buf, sizeof(buf), testdata)) { invalid++; break; }
lineno++;
if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
if (compiled) {
printf("*** Test program compiled that should not have at line %u: %s\n", lineno, prog);
must_fail = 0;
check_msg = 0;
invalid++;
continue;
}
if (check_msg && strcmp(buf, err_msg.buf) != 0) {
printf("*** Erroneous test program failed with wrong message (%s) at line %u: %s\n", err_msg.buf, lineno, prog);
invalid++;
} else {
passed++;
}
must_fail = 0;
check_msg = 0;
continue;
}
if (!compiled) {
printf("*** Test program failed to compile at line %u: %s\n", lineno, prog);
invalid++;
// skip past test data
while (fgets(buf, sizeof(buf), testdata)) {
lineno++;
if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n'))
break;
}
continue;
}
if (verbose) {
printf("Disassembly:\n");
jq_dump_disassembly(jq, 2);
printf("\n");
}
if (!fgets(buf, sizeof(buf), testdata)) { invalid++; break; }
lineno++;
jv input = jv_parse(buf);
if (!jv_is_valid(input)){ invalid++; continue; }
jq_init(bc, input, &jq, JQ_DEBUG_TRACE);
if (!jv_is_valid(input)) {
printf("*** Input is invalid on line %u: %s\n", lineno, buf);
invalid++;
continue;
}
jq_start(jq, input, verbose ? JQ_DEBUG_TRACE : 0);
while (fgets(buf, sizeof(buf), testdata)) {
lineno++;
if (skipline(buf)) break;
jv expected = jv_parse(buf);
if (!jv_is_valid(expected)){ invalid++; continue; }
if (!jv_is_valid(expected)) {
printf("*** Expected result is invalid on line %u: %s\n", lineno, buf);
invalid++;
continue;
}
jv actual = jq_next(jq);
if (!jv_is_valid(actual)) {
jv_free(actual);
printf("*** Insufficient results\n");
printf("*** Insufficient results for test at line number %u: %s\n", lineno, prog);
pass = 0;
break;
} else if (!jv_equal(jv_copy(expected), jv_copy(actual))) {
@@ -59,10 +154,10 @@ static void run_jq_tests(FILE *testdata) {
jv_dump(jv_copy(expected), 0);
printf(", but got ");
jv_dump(jv_copy(actual), 0);
printf("\n");
printf(" for test at line number %u: %s\n", lineno, prog);
pass = 0;
}
jv as_string = jv_dump_string(jv_copy(expected), rand() & ~JV_PRINT_COLOUR);
jv as_string = jv_dump_string(jv_copy(expected), rand() & ~(JV_PRINT_COLOUR|JV_PRINT_REFCOUNT));
jv reparsed = jv_parse_sized(jv_string_value(as_string), jv_string_length_bytes(jv_copy(as_string)));
assert(jv_equal(jv_copy(expected), jv_copy(reparsed)));
jv_free(as_string);
@@ -75,29 +170,36 @@ static void run_jq_tests(FILE *testdata) {
if (jv_is_valid(extra)) {
printf("*** Superfluous result: ");
jv_dump(extra, 0);
printf("\n");
printf(" for test at line number %u, %s\n", lineno, prog);
pass = 0;
} else {
jv_free(extra);
}
}
jq_teardown(&jq);
bytecode_free(bc);
passed+=pass;
}
jq_teardown(&jq);
printf("%d of %d tests passed (%d malformed)\n", passed,tests,invalid);
if (passed != tests) exit(1);
}
static void jv_test() {
/// JSON parser regression tests
{
jv v = jv_parse("{\"a':\"12\"}");
assert(jv_get_kind(v) == JV_KIND_INVALID);
v = jv_invalid_get_msg(v);
assert(strcmp(jv_string_value(v), "Expected separator between values at line 1, column 9 (while parsing '{\"a':\"12\"}')") == 0);
jv_free(v);
}
/// Arrays and numbers
{
jv a = jv_array();
assert(jv_get_kind(a) == JV_KIND_ARRAY);
assert(jv_array_length(jv_copy(a)) == 0);
assert(jv_array_length(jv_copy(a)) == 0);
a = jv_array_append(a, jv_number(42));
assert(jv_array_length(jv_copy(a)) == 1);
assert(jv_number_value(jv_array_get(jv_copy(a), 0)) == 42);
@@ -115,9 +217,9 @@ static void jv_test() {
jv_free(a2);
assert(a.val.nontrivial.ptr->count == 1);
assert(jv_get_refcnt(a) == 1);
a = jv_array_append(a, jv_copy(a));
assert(a.val.nontrivial.ptr->count == 1);
assert(jv_get_refcnt(a) == 1);
assert(jv_array_length(jv_copy(a)) == 2);
assert(jv_number_value(jv_array_get(jv_copy(a), 0)) == 42);
@@ -150,9 +252,9 @@ static void jv_test() {
jv_free(subarray);
void* before = sub2.val.nontrivial.ptr;
void* before = sub2.u.ptr;
sub2 = jv_array_append(sub2, jv_number(200));
void* after = sub2.val.nontrivial.ptr;
void* after = sub2.u.ptr;
assert(before == after);
jv_free(sub2);
@@ -172,8 +274,10 @@ static void jv_test() {
a4 = jv_array_slice(a4, 0, 1);
assert(jv_array_length(jv_copy(a4)) == 1);
a4 = jv_array_append(a4, jv_number(4));
assert(jv_array_length(a4) == 2);
assert(jv_array_length(a5) == 2);
assert(jv_array_length(jv_copy(a4)) == 2);
assert(jv_array_length(jv_copy(a5)) == 2);
jv_free(a4);
jv_free(a5);
assert(jv_array_length(jv_copy(a)) == 2);
@@ -181,7 +285,7 @@ static void jv_test() {
assert(jv_array_length(jv_array_get(jv_copy(a), 1)) == 1);
jv_dump(jv_copy(a), 0); printf("\n");
//jv_dump(jv_copy(a), 0); printf("\n");
jv_free(a);
}
@@ -191,16 +295,18 @@ static void jv_test() {
assert(jv_equal(jv_string("foo"), jv_string_sized("foo", 3)));
char nasty[] = "foo\0";
jv shortstr = jv_string(nasty), longstr = jv_string_sized(nasty, sizeof(nasty));
assert(jv_string_length_bytes(shortstr) == (int)strlen(nasty));
assert(jv_string_length_bytes(longstr) == (int)sizeof(nasty));
assert(jv_string_length_bytes(jv_copy(shortstr)) == (int)strlen(nasty));
assert(jv_string_length_bytes(jv_copy(longstr)) == (int)sizeof(nasty));
jv_free(shortstr);
jv_free(longstr);
char a1s[] = "hello", a2s[] = "hello", bs[] = "goodbye";
jv a1 = jv_string(a1s), a2 = jv_string(a2s), b = jv_string(bs);
assert(jv_equal(jv_copy(a1), jv_copy(a2)));
assert(jv_equal(jv_copy(a2), jv_copy(a1)));
assert(!jv_equal(jv_copy(a1), jv_copy(b)));
assert(jv_string_hash(jv_copy(a1)) == jv_string_hash(jv_copy(a1)));
assert(jv_string_hash(jv_copy(a1)) == jv_string_hash(jv_copy(a2)));
assert(jv_string_hash(jv_copy(b)) != jv_string_hash(jv_copy(a1)));
@@ -234,8 +340,7 @@ static void jv_test() {
jv_free(o1);
assert(jv_number_value(jv_object_get(jv_copy(o2), jv_string("bar"))) == 240);
jv_dump(jv_copy(o2), 0); printf("\n");
//jv_dump(jv_copy(o2), 0); printf("\n");
jv_free(o2);
}
}
+576 -289
View File
File diff suppressed because it is too large. Load diff
+111 -29
View File
@@ -1,11 +1,9 @@
#ifndef JV_H
#define JV_H
#include <stdarg.h>
#include <stdint.h>
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
typedef enum {
JV_KIND_INVALID,
@@ -18,21 +16,19 @@ typedef enum {
JV_KIND_OBJECT
} jv_kind;
typedef struct {
size_t count;
} jv_refcnt;
typedef struct{
jv_refcnt* ptr;
int i[2];
} jv_nontrivial;
struct jv_refcnt;
/* All of the fields of this struct are private.
Really. Do not play with them. */
typedef struct {
jv_kind kind;
unsigned char kind_flags;
unsigned char pad_;
unsigned short offset; /* array offsets */
int size;
union {
struct jv_refcnt* ptr;
double number;
jv_nontrivial nontrivial;
} val;
} u;
} jv;
/*
@@ -47,24 +43,28 @@ static int jv_is_valid(jv x) { return jv_get_kind(x) != JV_KIND_INVALID; }
jv jv_copy(jv);
void jv_free(jv);
int jv_get_refcnt(jv);
int jv_equal(jv, jv);
int jv_identical(jv, jv);
int jv_contains(jv, jv);
jv jv_invalid();
jv jv_invalid(void);
jv jv_invalid_with_msg(jv);
jv jv_invalid_get_msg(jv);
int jv_invalid_has_msg(jv);
jv jv_null();
jv jv_true();
jv jv_false();
jv jv_null(void);
jv jv_true(void);
jv jv_false(void);
jv jv_bool(int);
jv jv_number(double);
double jv_number_value(jv);
int jv_is_integer(jv);
jv jv_array();
jv jv_array(void);
jv jv_array_sized(int);
int jv_array_length(jv);
jv jv_array_get(jv, int);
@@ -72,6 +72,7 @@ jv jv_array_set(jv, int, jv);
jv jv_array_append(jv, jv);
jv jv_array_concat(jv, jv);
jv jv_array_slice(jv, int, int);
jv jv_array_indexes(jv, jv);
#define jv_array_foreach(a, i, x) \
for (int jv_len__ = jv_array_length(jv_copy(a)), i=0, jv_j__ = 1; \
jv_j__; jv_j__ = 0) \
@@ -80,23 +81,53 @@ jv jv_array_slice(jv, int, int);
(x = jv_array_get(jv_copy(a), i), 1) : 0; \
i++)
#define JV_ARRAY_1(e) (jv_array_append(jv_array(),e))
#define JV_ARRAY_2(e1,e2) (jv_array_append(JV_ARRAY_1(e1),e2))
#define JV_ARRAY_3(e1,e2,e3) (jv_array_append(JV_ARRAY_2(e1,e2),e3))
#define JV_ARRAY_4(e1,e2,e3,e4) (jv_array_append(JV_ARRAY_3(e1,e2,e3),e4))
#define JV_ARRAY_5(e1,e2,e3,e4,e5) (jv_array_append(JV_ARRAY_4(e1,e2,e3,e4),e5))
#define JV_ARRAY_6(e1,e2,e3,e4,e5,e6) (jv_array_append(JV_ARRAY_5(e1,e2,e3,e4,e5),e6))
#define JV_ARRAY_7(e1,e2,e3,e4,e5,e6,e7) (jv_array_append(JV_ARRAY_6(e1,e2,e3,e4,e5,e6),e7))
#define JV_ARRAY_8(e1,e2,e3,e4,e5,e6,e7,e8) (jv_array_append(JV_ARRAY_7(e1,e2,e3,e4,e5,e6,e7),e8))
#define JV_ARRAY_9(e1,e2,e3,e4,e5,e6,e7,e8,e9) (jv_array_append(JV_ARRAY_8(e1,e2,e3,e4,e5,e6,e7,e8),e9))
#define JV_ARRAY_IDX(_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME
#define JV_ARRAY(...) \
JV_ARRAY_IDX(__VA_ARGS__, JV_ARRAY_9, JV_ARRAY_8, JV_ARRAY_7, JV_ARRAY_6, JV_ARRAY_5, JV_ARRAY_4, JV_ARRAY_3, JV_ARRAY_2, JV_ARRAY_1)(__VA_ARGS__)
#ifdef __GNUC__
#define JV_PRINTF_LIKE(fmt_arg_num, args_num) \
__attribute__ ((__format__( __printf__, fmt_arg_num, args_num)))
#define JV_VPRINTF_LIKE(fmt_arg_num) \
__attribute__ ((__format__( __printf__, fmt_arg_num, 0)))
#endif
jv jv_string(const char*);
jv jv_string_sized(const char*, int);
jv jv_string_empty(int len);
int jv_string_length_bytes(jv);
int jv_string_length_codepoints(jv);
uint32_t jv_string_hash(jv);
unsigned long jv_string_hash(jv);
const char* jv_string_value(jv);
jv jv_string_indexes(jv j, jv k);
jv jv_string_slice(jv j, int start, int end);
jv jv_string_concat(jv, jv);
jv jv_string_fmt(const char*, ...);
jv jv_string_vfmt(const char*, va_list) JV_VPRINTF_LIKE(1);
jv jv_string_fmt(const char*, ...) JV_PRINTF_LIKE(1, 2);
jv jv_string_append_codepoint(jv a, uint32_t c);
jv jv_string_append_buf(jv a, const char* buf, int len);
jv jv_string_append_str(jv a, const char* str);
jv jv_string_split(jv j, jv sep);
jv jv_string_explode(jv j);
jv jv_string_implode(jv j);
jv jv_object();
jv jv_object(void);
jv jv_object_get(jv object, jv key);
jv jv_object_set(jv object, jv key, jv value);
jv jv_object_delete(jv object, jv key);
int jv_object_length(jv object);
jv jv_object_merge(jv, jv);
jv jv_object_merge_recursive(jv, jv);
int jv_object_iter(jv);
int jv_object_iter_next(jv, int);
@@ -112,25 +143,76 @@ jv jv_object_iter_value(jv, int);
1) \
: 0; \
jv_i__ = jv_object_iter_next(t, jv_i__)) \
#define JV_OBJECT_1(k) (jv_object_set(jv_object(),(k),jv_null()))
#define JV_OBJECT_2(k1,v1) (jv_object_set(jv_object(),(k1),(v1)))
#define JV_OBJECT_3(k1,v1,k2) (jv_object_set(JV_OBJECT_2(k1,v1),k2,jv_null()))
#define JV_OBJECT_4(k1,v1,k2,v2) (jv_object_set(JV_OBJECT_2(k1,v1),k2,v2))
#define JV_OBJECT_5(k1,v1,k2,v2,k3) (jv_object_set(JV_OBJECT_4(k1,v1,k2,v2),k3,jv_null))
#define JV_OBJECT_6(k1,v1,k2,v2,k3,v3) (jv_object_set(JV_OBJECT_4(k1,v1,k2,v2),k3,v3))
#define JV_OBJECT_7(k1,v1,k2,v2,k3,v3,k4) (jv_object_set(JV_OBJECT_6(k1,v1,k2,v2,k3,v3),k4,jv_null()))
#define JV_OBJECT_8(k1,v1,k2,v2,k3,v3,k4,v4) (jv_object_set(JV_OBJECT_6(k1,v1,k2,v2,k3,v3),k4,v4))
#define JV_OBJECT_IDX(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define JV_OBJECT(...) \
JV_OBJECT_IDX(__VA_ARGS__, JV_OBJECT_8, JV_OBJECT_7, JV_OBJECT_6, JV_OBJECT_5, JV_OBJECT_4, JV_OBJECT_3, JV_OBJECT_2, JV_OBJECT_1)(__VA_ARGS__)
int jv_get_refcnt(jv);
enum { JV_PRINT_PRETTY = 1, JV_PRINT_ASCII = 2, JV_PRINT_COLOUR = 4 };
enum jv_print_flags {
JV_PRINT_PRETTY = 1,
JV_PRINT_ASCII = 2,
JV_PRINT_COLOUR = 4,
JV_PRINT_SORTED = 8,
JV_PRINT_INVALID = 16,
JV_PRINT_REFCOUNT = 32,
JV_PRINT_TAB = 64,
JV_PRINT_ISATTY = 128,
JV_PRINT_SPACE0 = 256,
JV_PRINT_SPACE1 = 512,
JV_PRINT_SPACE2 = 1024,
};
#define JV_PRINT_INDENT_FLAGS(n) \
((n) < 0 || (n) > 7 ? JV_PRINT_TAB | JV_PRINT_PRETTY : (n) == 0 ? 0 : (n) << 8 | JV_PRINT_PRETTY)
void jv_dumpf(jv, FILE *f, int flags);
void jv_dump(jv, int flags);
void jv_show(jv, int flags);
jv jv_dump_string(jv, int flags);
char *jv_dump_string_trunc(jv x, char *outbuf, size_t bufsize);
enum {
JV_PARSE_SEQ = 1,
JV_PARSE_STREAMING = 2,
JV_PARSE_STREAM_ERRORS = 4,
};
jv jv_parse(const char* string);
jv jv_parse_sized(const char* string, int length);
typedef void (*jv_nomem_handler_f)(void *);
void jv_nomem_handler(jv_nomem_handler_f, void *);
jv jv_load_file(const char *, int);
typedef struct jv_parser jv_parser;
jv_parser* jv_parser_new(int);
void jv_parser_set_buf(jv_parser*, const char*, int, int);
int jv_parser_remaining(jv_parser*);
jv jv_parser_next(jv_parser*);
void jv_parser_free(jv_parser*);
jv jv_get(jv, jv);
jv jv_set(jv, jv, jv);
jv jv_has(jv, jv);
jv jv_setpath(jv, jv, jv);
jv jv_getpath(jv, jv);
jv jv_delpaths(jv, jv);
jv jv_keys(jv /*object or array*/);
jv jv_keys_unsorted(jv /*object or array*/);
int jv_cmp(jv, jv);
jv jv_group(jv, jv);
jv jv_sort(jv, jv);
#endif
+142
View File
@@ -1,12 +1,123 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "jv_alloc.h"
struct nomem_handler {
jv_nomem_handler_f handler;
void *data;
};
#if !defined(HAVE_PTHREAD_KEY_CREATE) || \
!defined(HAVE_PTHREAD_ONCE) || \
!defined(HAVE_ATEXIT)
/* Try thread-local storage? */
#ifdef _MSC_VER
/* Visual C++: yes */
static __declspec(thread) struct nomem_handler nomem_handler;
#define USE_TLS
#else
#ifdef HAVE___THREAD
/* GCC and friends: yes */
static __thread struct nomem_handler nomem_handler;
#define USE_TLS
#endif /* HAVE___THREAD */
#endif /* _MSC_VER */
#endif /* !HAVE_PTHREAD_KEY_CREATE */
#ifdef USE_TLS
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
nomem_handler.handler = handler;
}
static void memory_exhausted() {
if (nomem_handler.handler)
nomem_handler.handler(nomem_handler.data); // Maybe handler() will longjmp() to safety
// Or not
fprintf(stderr, "error: cannot allocate memory\n");
abort();
}
#else /* USE_TLS */
#ifdef HAVE_PTHREAD_KEY_CREATE
#include <pthread.h>
pthread_key_t nomem_handler_key;
pthread_once_t mem_once = PTHREAD_ONCE_INIT;
static void tsd_fini(void) {
struct nomem_handler *nomem_handler;
nomem_handler = pthread_getspecific(nomem_handler_key);
if (nomem_handler) {
(void) pthread_setspecific(nomem_handler_key, NULL);
free(nomem_handler);
}
}
static void tsd_init(void) {
if (pthread_key_create(&nomem_handler_key, NULL) != 0) {
fprintf(stderr, "error: cannot create thread specific key");
abort();
}
if (atexit(tsd_fini) != 0) {
fprintf(stderr, "error: cannot set an exit handler");
abort();
}
struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler));
if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {
fprintf(stderr, "error: cannot set thread specific data");
abort();
}
}
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
pthread_once(&mem_once, tsd_init); // cannot fail
struct nomem_handler *nomem_handler;
nomem_handler = pthread_getspecific(nomem_handler_key);
if (nomem_handler == NULL) {
handler(data);
fprintf(stderr, "error: cannot allocate memory\n");
abort();
}
nomem_handler->handler = handler;
nomem_handler->data = data;
}
static void memory_exhausted() {
struct nomem_handler *nomem_handler;
pthread_once(&mem_once, tsd_init);
nomem_handler = pthread_getspecific(nomem_handler_key);
if (nomem_handler)
nomem_handler->handler(nomem_handler->data); // Maybe handler() will longjmp() to safety
// Or not
fprintf(stderr, "error: cannot allocate memory\n");
abort();
}
#else
/* No thread-local storage of any kind that we know how to handle */
static struct nomem_handler nomem_handler;
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
nomem_handler.handler = handler;
nomem_handler.data = data;
}
static void memory_exhausted() {
fprintf(stderr, "error: cannot allocate memory\n");
abort();
}
#endif /* HAVE_PTHREAD_KEY_CREATE */
#endif /* USE_TLS */
void* jv_mem_alloc(size_t sz) {
void* p = malloc(sz);
if (!p) {
@@ -15,6 +126,34 @@ void* jv_mem_alloc(size_t sz) {
return p;
}
void* jv_mem_alloc_unguarded(size_t sz) {
return malloc(sz);
}
void* jv_mem_calloc(size_t nemb, size_t sz) {
void* p = calloc(nemb, sz);
if (!p) {
memory_exhausted();
}
return p;
}
void* jv_mem_calloc_unguarded(size_t nemb, size_t sz) {
return calloc(nemb, sz);
}
char* jv_mem_strdup(const char *s) {
char *p = strdup(s);
if (!p) {
memory_exhausted();
}
return p;
}
char* jv_mem_strdup_unguarded(const char *s) {
return strdup(s);
}
void jv_mem_free(void* p) {
free(p);
}
@@ -30,8 +169,11 @@ void* jv_mem_realloc(void* p, size_t sz) {
#ifndef NDEBUG
volatile char jv_mem_uninitialised;
__attribute__((constructor)) void jv_mem_uninit_setup(){
// ignore warning that this reads uninitialized memory - that's the point!
#ifndef __clang_analyzer__
char* p = malloc(1);
jv_mem_uninitialised = *p;
free(p);
#endif
}
#endif
+6
View File
@@ -2,6 +2,7 @@
#define JV_ALLOC_H
#include <stddef.h>
#include "jv.h"
#ifndef NDEBUG
extern volatile char jv_mem_uninitialised;
@@ -15,6 +16,11 @@ static void jv_mem_invalidate(void* mem, size_t n) {
}
void* jv_mem_alloc(size_t);
void* jv_mem_alloc_unguarded(size_t);
void* jv_mem_calloc(size_t, size_t);
void* jv_mem_calloc_unguarded(size_t, size_t);
char* jv_mem_strdup(const char *);
char* jv_mem_strdup_unguarded(const char *);
void jv_mem_free(void*);
__attribute__((warn_unused_result)) void* jv_mem_realloc(void*, size_t);
+97 -43
View File
@@ -1,17 +1,25 @@
#include "jv_aux.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "jv_alloc.h"
static int parse_slice(jv array, jv slice, int* pstart, int* pend) {
static int parse_slice(jv j, jv slice, int* pstart, int* pend) {
// Array slices
int len = jv_array_length(jv_copy(array));
jv start_jv = jv_object_get(jv_copy(slice), jv_string("start"));
jv end_jv = jv_object_get(slice, jv_string("end"));
if (jv_get_kind(start_jv) == JV_KIND_NULL) {
jv_free(start_jv);
start_jv = jv_number(0);
}
int len;
if (jv_get_kind(j) == JV_KIND_ARRAY) {
len = jv_array_length(j);
} else if (jv_get_kind(j) == JV_KIND_STRING) {
len = jv_string_length_codepoints(j);
} else {
jv_free(j);
return 0;
}
if (jv_get_kind(end_jv) == JV_KIND_NULL) {
jv_free(end_jv);
end_jv = jv_number(len);
@@ -22,13 +30,18 @@ static int parse_slice(jv array, jv slice, int* pstart, int* pend) {
jv_free(end_jv);
return 0;
} else {
int start = (int)jv_number_value(start_jv);
int end = (int)jv_number_value(end_jv);
if (start < 0) start = len + start;
if (end < 0) end = len + end;
double dstart = jv_number_value(start_jv);
double dend = jv_number_value(end_jv);
if (dstart < 0) dstart += len;
if (dend < 0) dend += len;
if (dstart < 0) dstart = 0;
if (dstart > len) dstart = len;
int start = (int)dstart;
int end = (dend > len) ? len : (int)dend;
// Ends are exclusive but e.g. 1 < 1.5 so :1.5 should be :2 not :1
if(end < dend) end += 1;
if (start < 0) start = 0;
if (start > len) start = len;
if (end > len) end = len;
if (end < start) end = start;
assert(0 <= start && start <= end && end <= len);
@@ -47,31 +60,60 @@ jv jv_get(jv t, jv k) {
v = jv_null();
}
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) {
// FIXME: don't do lookup for noninteger index
v = jv_array_get(t, (int)jv_number_value(k));
if (!jv_is_valid(v)) {
jv_free(v);
if(jv_is_integer(k)){
int idx = (int)jv_number_value(k);
if (idx < 0)
idx += jv_array_length(jv_copy(t));
v = jv_array_get(t, idx);
if (!jv_is_valid(v)) {
jv_free(v);
v = jv_null();
}
} else {
jv_free(t);
jv_free(k);
v = jv_null();
}
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_OBJECT) {
int start, end;
if (parse_slice(t, k, &start, &end)) {
if (parse_slice(jv_copy(t), k, &start, &end)) {
v = jv_array_slice(t, start, end);
} else {
jv_free(t);
v = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an array slice must be numbers"));
}
} else if (jv_get_kind(t) == JV_KIND_STRING && jv_get_kind(k) == JV_KIND_OBJECT) {
int start, end;
if (parse_slice(jv_copy(t), k, &start, &end)) {
v = jv_string_slice(t, start, end);
} else {
v = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an string slice must be numbers"));
jv_free(t);
}
} else if (jv_get_kind(t) == JV_KIND_NULL &&
(jv_get_kind(k) == JV_KIND_STRING ||
jv_get_kind(k) == JV_KIND_NUMBER ||
} else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_ARRAY) {
v = jv_array_indexes(t, k);
} else if (jv_get_kind(t) == JV_KIND_NULL &&
(jv_get_kind(k) == JV_KIND_STRING ||
jv_get_kind(k) == JV_KIND_NUMBER ||
jv_get_kind(k) == JV_KIND_OBJECT)) {
jv_free(t);
jv_free(k);
v = jv_null();
} else {
v = jv_invalid_with_msg(jv_string_fmt("Cannot index %s with %s",
jv_kind_name(jv_get_kind(t)),
jv_kind_name(jv_get_kind(k))));
/*
* If k is a short string it's probably from a jq .foo expression or
* similar, in which case putting it in the invalid msg may help the
* user. The length 30 is arbitrary.
*/
if (jv_get_kind(k) == JV_KIND_STRING && jv_string_length_bytes(jv_copy(k)) < 30) {
v = jv_invalid_with_msg(jv_string_fmt("Cannot index %s with string \"%s\"",
jv_kind_name(jv_get_kind(t)),
jv_string_value(k)));
} else {
v = jv_invalid_with_msg(jv_string_fmt("Cannot index %s with %s",
jv_kind_name(jv_get_kind(t)),
jv_kind_name(jv_get_kind(k))));
}
jv_free(t);
jv_free(k);
}
@@ -85,7 +127,7 @@ jv jv_set(jv t, jv k, jv v) {
return v;
}
int isnull = jv_get_kind(t) == JV_KIND_NULL;
if (jv_get_kind(k) == JV_KIND_STRING &&
if (jv_get_kind(k) == JV_KIND_STRING &&
(jv_get_kind(t) == JV_KIND_OBJECT || isnull)) {
if (isnull) t = jv_object();
t = jv_object_set(t, k, v);
@@ -97,7 +139,7 @@ jv jv_set(jv t, jv k, jv v) {
(jv_get_kind(t) == JV_KIND_ARRAY || isnull)) {
if (isnull) t = jv_array();
int start, end;
if (parse_slice(t, k, &start, &end)) {
if (parse_slice(jv_copy(t), k, &start, &end)) {
if (jv_get_kind(v) == JV_KIND_ARRAY) {
int array_len = jv_array_length(jv_copy(t));
assert(0 <= start && start <= end && end <= array_len);
@@ -128,7 +170,6 @@ jv jv_set(jv t, jv k, jv v) {
}
} else {
jv_free(t);
jv_free(k);
jv_free(v);
t = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an array slice must be numbers"));
}
@@ -176,7 +217,7 @@ jv jv_has(jv t, jv k) {
jv jv_dels(jv t, jv keys) {
assert(jv_get_kind(keys) == JV_KIND_ARRAY);
assert(jv_is_valid(t));
if (jv_get_kind(t) == JV_KIND_NULL || jv_array_length(jv_copy(keys)) == 0) {
// no change
} else if (jv_get_kind(t) == JV_KIND_ARRAY) {
@@ -190,12 +231,11 @@ jv jv_dels(jv t, jv keys) {
keys = jv_array_append(keys, key);
} else if (jv_get_kind(key) == JV_KIND_OBJECT) {
int start, end;
if (parse_slice(t, key, &start, &end)) {
if (parse_slice(jv_copy(t), key, &start, &end)) {
starts = jv_array_append(starts, jv_number(start));
ends = jv_array_append(ends, jv_number(end));
} else {
jv_free(new_array);
jv_free(key);
new_array = jv_invalid_with_msg(jv_string_fmt("Start and end indices of an array slice must be numbers"));
goto arr_out;
}
@@ -247,7 +287,7 @@ jv jv_dels(jv t, jv keys) {
jv_free(k);
break;
}
t = jv_object_delete(t, k);
t = jv_object_delete(t, k);
}
} else {
jv err = jv_invalid_with_msg(jv_string_fmt("Cannot delete fields from %s",
@@ -278,7 +318,7 @@ jv jv_setpath(jv root, jv path, jv value) {
}
jv pathcurr = jv_array_get(jv_copy(path), 0);
jv pathrest = jv_array_slice(path, 1, jv_array_length(jv_copy(path)));
return jv_set(root, pathcurr,
return jv_set(root, pathcurr,
jv_setpath(jv_get(jv_copy(root), jv_copy(pathcurr)), pathrest, value));
}
@@ -344,7 +384,7 @@ static jv delpaths_sorted(jv object, jv paths, int start) {
jv_free(paths);
if (jv_is_valid(object))
object = jv_dels(object, delkeys);
else
else
jv_free(delkeys);
return object;
}
@@ -388,6 +428,18 @@ static int string_cmp(const void* pa, const void* pb){
return r;
}
jv jv_keys_unsorted(jv x) {
if (jv_get_kind(x) != JV_KIND_OBJECT)
return jv_keys(x);
jv answer = jv_array_sized(jv_object_length(jv_copy(x)));
jv_object_foreach(x, key, value) {
answer = jv_array_append(answer, key);
jv_free(value);
}
jv_free(x);
return answer;
}
jv jv_keys(jv x) {
if (jv_get_kind(x) == JV_KIND_OBJECT) {
int nkeys = jv_object_length(jv_copy(x));
@@ -438,7 +490,7 @@ int jv_cmp(jv a, jv b) {
case JV_KIND_NUMBER: {
double da = jv_number_value(a), db = jv_number_value(b);
// handle NaN as though it were null
if (da != da) r = jv_cmp(jv_null(), jv_number(db));
else if (db != db) r = jv_cmp(jv_number(da), jv_null());
@@ -545,21 +597,23 @@ jv jv_group(jv objects, jv keys) {
int n = jv_array_length(jv_copy(objects));
struct sort_entry* entries = sort_items(objects, keys);
jv ret = jv_array();
jv curr_key = entries[0].key;
jv group = jv_array_append(jv_array(), entries[0].object);
for (int i = 1; i < n; i++) {
if (jv_equal(jv_copy(curr_key), jv_copy(entries[i].key))) {
jv_free(entries[i].key);
} else {
jv_free(curr_key);
curr_key = entries[i].key;
ret = jv_array_append(ret, group);
group = jv_array();
if (n > 0) {
jv curr_key = entries[0].key;
jv group = jv_array_append(jv_array(), entries[0].object);
for (int i = 1; i < n; i++) {
if (jv_equal(jv_copy(curr_key), jv_copy(entries[i].key))) {
jv_free(entries[i].key);
} else {
jv_free(curr_key);
curr_key = entries[i].key;
ret = jv_array_append(ret, group);
group = jv_array();
}
group = jv_array_append(group, entries[i].object);
}
group = jv_array_append(group, entries[i].object);
jv_free(curr_key);
ret = jv_array_append(ret, group);
}
jv_free(curr_key);
ret = jv_array_append(ret, group);
jv_mem_free(entries);
return ret;
}
-20
View File
@@ -1,20 +0,0 @@
#ifndef JV_AUX_H
#define JV_AUX_H
#include "jv.h"
jv jv_get(jv t, jv k);
jv jv_set(jv t, jv k, jv v);
jv jv_has(jv t, jv k);
jv jv_setpath(jv root, jv path, jv value);
jv jv_getpath(jv root, jv path);
jv jv_delpaths(jv root, jv paths);
jv jv_keys(jv /*object or array*/);
int jv_cmp(jv, jv);
jv jv_group(jv objects, jv keys);
jv jv_sort(jv objects, jv keys);
#endif
+2 -3
View File
@@ -187,7 +187,6 @@
* used for input more than STRTOD_DIGLIM digits long (default 40).
*/
#define IEEE_8087
#define NO_ERRNO
#define NO_HEX_FP
#define No_Hex_NaN
@@ -526,7 +525,7 @@ void jvp_dtoa_context_init(struct dtoa_context* C) {
}
C->p5s = 0;
}
static Bigint *
Balloc(struct dtoa_context* C, int k)
{
@@ -4225,7 +4224,7 @@ jvp_dtoa
while((*b++ = *s++));
goto done0;
}
if (decpt <= -4 || decpt > se - s + 5) {
if (decpt <= -4 || decpt > se - s + 15) {
*b++ = *s++;
if (*s) {
*b++ = '.';
+1 -1
View File
@@ -17,6 +17,6 @@ double jvp_strtod(struct dtoa_context* C, const char* s, char** se);
char* jvp_dtoa(struct dtoa_context* C, double dd, int mode, int ndigits, int *decpt, int *sign, char **rve);
void jvp_freedtoa(struct dtoa_context* C, char *s);
#define JVP_DTOA_FMT_MAX_LEN 32
#define JVP_DTOA_FMT_MAX_LEN 64
char* jvp_dtoa_fmt(struct dtoa_context* C, register char *b, double x);
#endif
+49
View File
@@ -0,0 +1,49 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jv.h"
jv jv_load_file(const char* filename, int raw) {
FILE* file = fopen(filename, "r");
struct jv_parser* parser;
jv data;
if (!file) {
return jv_invalid_with_msg(jv_string_fmt("Could not open %s: %s",
filename,
strerror(errno)));
}
if (raw) {
data = jv_string("");
} else {
data = jv_array();
parser = jv_parser_new(0);
}
while (!feof(file) && !ferror(file)) {
char buf[4096];
size_t n = fread(buf, 1, sizeof(buf), file);
if (raw) {
data = jv_string_concat(data, jv_string_sized(buf, (int)n));
} else {
jv_parser_set_buf(parser, buf, n, !feof(file));
jv value;
while (jv_is_valid((value = jv_parser_next(parser))))
data = jv_array_append(data, value);
if (jv_invalid_has_msg(jv_copy(value))) {
jv_free(data);
data = value;
break;
}
}
}
if (!raw)
jv_parser_free(parser);
int badread = ferror(file);
if (fclose(file) != 0 || badread) {
jv_free(data);
return jv_invalid_with_msg(jv_string_fmt("Error reading from %s",
filename));
}
return data;
}
+437 -31
View File
@@ -1,11 +1,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "jv.h"
#include "jv_dtoa.h"
#include "jv_parse.h"
#include "jv_unicode.h"
#include "jv_alloc.h"
#include "jv_dtoa.h"
typedef const char* presult;
@@ -16,32 +17,118 @@ typedef const char* presult;
#define pfunc presult
#endif
void jv_parser_init(struct jv_parser* p) {
enum last_seen {
JV_LAST_NONE = 0,
JV_LAST_OPEN_ARRAY = '[',
JV_LAST_OPEN_OBJECT = '{',
JV_LAST_COLON = ':',
JV_LAST_COMMA = ',',
JV_LAST_VALUE = 'V',
};
struct jv_parser {
const char* curr_buf;
int curr_buf_length;
int curr_buf_pos;
int curr_buf_is_partial;
int eof;
unsigned bom_strip_position;
int flags;
jv* stack; // parser
int stackpos; // parser
int stacklen; // both (optimization; it's really pathlen for streaming)
jv path; // streamer
enum last_seen last_seen; // streamer
jv output; // streamer
jv next; // both
char* tokenbuf;
int tokenpos;
int tokenlen;
int line, column;
struct dtoa_context dtoa;
enum {
JV_PARSER_NORMAL,
JV_PARSER_STRING,
JV_PARSER_STRING_ESCAPE,
JV_PARSER_WAITING_FOR_RS // parse error, waiting for RS
} st;
unsigned int last_ch_was_ws:1;
};
static void parser_init(struct jv_parser* p, int flags) {
p->flags = flags;
if ((p->flags & JV_PARSE_STREAMING)) {
p->path = jv_array();
} else {
p->path = jv_invalid();
p->flags &= ~(JV_PARSE_STREAM_ERRORS);
}
p->stack = 0;
p->stacklen = p->stackpos = 0;
p->last_seen = JV_LAST_NONE;
p->output = jv_invalid();
p->next = jv_invalid();
p->tokenbuf = 0;
p->tokenlen = p->tokenpos = 0;
p->st = JV_PARSER_NORMAL;
if ((p->flags & JV_PARSE_SEQ))
p->st = JV_PARSER_WAITING_FOR_RS;
else
p->st = JV_PARSER_NORMAL;
p->eof = 0;
p->curr_buf = 0;
p->curr_buf_length = p->curr_buf_pos = p->curr_buf_is_partial = 0;
p->bom_strip_position = 0;
p->last_ch_was_ws = 0;
p->line = 1;
p->column = 0;
jvp_dtoa_context_init(&p->dtoa);
}
void jv_parser_free(struct jv_parser* p) {
static void parser_reset(struct jv_parser* p) {
if ((p->flags & JV_PARSE_STREAMING)) {
jv_free(p->path);
p->path = jv_array();
p->stacklen = 0;
}
p->last_seen = JV_LAST_NONE;
jv_free(p->output);
p->output = jv_invalid();
jv_free(p->next);
for (int i=0; i<p->stackpos; i++)
p->next = jv_invalid();
for (int i=0; i<p->stackpos; i++)
jv_free(p->stack[i]);
p->stackpos = 0;
p->tokenpos = 0;
p->st = JV_PARSER_NORMAL;
}
static void parser_free(struct jv_parser* p) {
parser_reset(p);
jv_free(p->path);
jv_free(p->output);
jv_mem_free(p->stack);
jv_mem_free(p->tokenbuf);
jvp_dtoa_context_free(&p->dtoa);
}
static pfunc value(struct jv_parser* p, jv val) {
if (jv_is_valid(p->next)) return "Expected separator between values";
if ((p->flags & JV_PARSE_STREAMING)) {
if (jv_is_valid(p->next) || p->last_seen == JV_LAST_VALUE)
return "Expected separator between values";
if (p->stacklen > 0)
p->last_seen = JV_LAST_VALUE;
else
p->last_seen = JV_LAST_NONE;
} else {
if (jv_is_valid(p->next)) return "Expected separator between values";
}
jv_free(p->next);
p->next = val;
return 0;
@@ -57,7 +144,7 @@ static void push(struct jv_parser* p, jv v) {
p->stack[p->stackpos++] = v;
}
static pfunc token(struct jv_parser* p, char ch) {
static pfunc parse_token(struct jv_parser* p, char ch) {
switch (ch) {
case '[':
if (jv_is_valid(p->next)) return "Expected separator between values";
@@ -70,7 +157,7 @@ static pfunc token(struct jv_parser* p, char ch) {
break;
case ':':
if (!jv_is_valid(p->next))
if (!jv_is_valid(p->next))
return "Expected string key before ':'";
if (p->stackpos == 0 || jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_OBJECT)
return "':' not as part of an object";
@@ -90,7 +177,7 @@ static pfunc token(struct jv_parser* p, char ch) {
p->next = jv_invalid();
} else if (jv_get_kind(p->stack[p->stackpos-1]) == JV_KIND_STRING) {
assert(p->stackpos > 1 && jv_get_kind(p->stack[p->stackpos-2]) == JV_KIND_OBJECT);
p->stack[p->stackpos-2] = jv_object_set(p->stack[p->stackpos-2],
p->stack[p->stackpos-2] = jv_object_set(p->stack[p->stackpos-2],
p->stack[p->stackpos-1], p->next);
p->stackpos--;
p->next = jv_invalid();
@@ -123,7 +210,7 @@ static pfunc token(struct jv_parser* p, char ch) {
if (jv_get_kind(p->stack[p->stackpos-1]) != JV_KIND_STRING)
return "Objects must consist of key:value pairs";
assert(p->stackpos > 1 && jv_get_kind(p->stack[p->stackpos-2]) == JV_KIND_OBJECT);
p->stack[p->stackpos-2] = jv_object_set(p->stack[p->stackpos-2],
p->stack[p->stackpos-2] = jv_object_set(p->stack[p->stackpos-2],
p->stack[p->stackpos-1], p->next);
p->stackpos--;
p->next = jv_invalid();
@@ -140,6 +227,159 @@ static pfunc token(struct jv_parser* p, char ch) {
return 0;
}
static pfunc stream_token(struct jv_parser* p, char ch) {
jv_kind k;
jv last;
switch (ch) {
case '[':
if (jv_is_valid(p->next))
return "Expected a separator between values";
p->path = jv_array_append(p->path, jv_number(0)); // push
p->last_seen = JV_LAST_OPEN_ARRAY;
p->stacklen++;
break;
case '{':
if (p->last_seen == JV_LAST_VALUE)
return "Expected a separator between values";
// Push object key: null, since we don't know it yet
p->path = jv_array_append(p->path, jv_null()); // push
p->last_seen = JV_LAST_OPEN_OBJECT;
p->stacklen++;
break;
case ':':
if (p->stacklen == 0 || jv_get_kind(jv_array_get(jv_copy(p->path), p->stacklen - 1)) == JV_KIND_NUMBER)
return "':' not as part of an object";
if (!jv_is_valid(p->next) || p->last_seen == JV_LAST_NONE)
return "Expected string key before ':'";
if (jv_get_kind(p->next) != JV_KIND_STRING)
return "Object keys must be strings";
if (p->last_seen != JV_LAST_VALUE)
return "':' should follow a key";
p->last_seen = JV_LAST_COLON;
p->path = jv_array_set(p->path, p->stacklen - 1, p->next);
p->next = jv_invalid();
break;
case ',':
if (p->last_seen != JV_LAST_VALUE)
return "Expected value before ','";
if (p->stacklen == 0)
return "',' not as part of an object or array";
last = jv_array_get(jv_copy(p->path), p->stacklen - 1);
k = jv_get_kind(last);
if (k == JV_KIND_NUMBER) {
int idx = jv_number_value(last);
if (jv_is_valid(p->next)) {
p->output = JV_ARRAY(jv_copy(p->path), p->next);
p->next = jv_invalid();
}
p->path = jv_array_set(p->path, p->stacklen - 1, jv_number(idx + 1));
p->last_seen = JV_LAST_COMMA;
} else if (k == JV_KIND_STRING) {
if (jv_is_valid(p->next)) {
p->output = JV_ARRAY(jv_copy(p->path), p->next);
p->next = jv_invalid();
}
p->path = jv_array_set(p->path, p->stacklen - 1, jv_true()); // ready for another name:value pair
p->last_seen = JV_LAST_COMMA;
} else {
assert(k == JV_KIND_NULL);
// this case hits on input like {,}
// make sure to handle input like {"a", "b"} and {"a":, ...}
jv_free(last);
return "Objects must consist of key:value pairs";
}
jv_free(last);
break;
case ']':
if (p->stacklen == 0)
return "Unmatched ']' at the top-level";
if (p->last_seen == JV_LAST_COMMA)
return "Expected another array element";
if (p->last_seen == JV_LAST_OPEN_ARRAY)
assert(!jv_is_valid(p->next));
last = jv_array_get(jv_copy(p->path), p->stacklen - 1);
k = jv_get_kind(last);
jv_free(last);
if (k != JV_KIND_NUMBER)
return "Unmatched ']' in the middle of an object";
if (jv_is_valid(p->next)) {
p->output = JV_ARRAY(jv_copy(p->path), p->next, jv_true());
p->next = jv_invalid();
} else if (p->last_seen != JV_LAST_OPEN_ARRAY) {
p->output = JV_ARRAY(jv_copy(p->path));
}
p->path = jv_array_slice(p->path, 0, --(p->stacklen)); // pop
//assert(!jv_is_valid(p->next));
jv_free(p->next);
p->next = jv_invalid();
if (p->last_seen == JV_LAST_OPEN_ARRAY)
p->output = JV_ARRAY(jv_copy(p->path), jv_array()); // Empty arrays are leaves
if (p->stacklen == 0)
p->last_seen = JV_LAST_NONE;
else
p->last_seen = JV_LAST_VALUE;
break;
case '}':
if (p->stacklen == 0)
return "Unmatched '}' at the top-level";
if (p->last_seen == JV_LAST_COMMA)
return "Expected another key:value pair";
if (p->last_seen == JV_LAST_OPEN_OBJECT)
assert(!jv_is_valid(p->next));
last = jv_array_get(jv_copy(p->path), p->stacklen - 1);
k = jv_get_kind(last);
jv_free(last);
if (k == JV_KIND_NUMBER)
return "Unmatched '}' in the middle of an array";
if (jv_is_valid(p->next)) {
if (k != JV_KIND_STRING)
return "Objects must consist of key:value pairs";
p->output = JV_ARRAY(jv_copy(p->path), p->next, jv_true());
p->next = jv_invalid();
} else {
// Perhaps {"a":[]}
if (p->last_seen == JV_LAST_COLON)
// Looks like {"a":}
return "Missing value in key:value pair";
if (p->last_seen == JV_LAST_COMMA)
// Looks like {"a":0,}
return "Expected another key-value pair";
if (p->last_seen == JV_LAST_OPEN_ARRAY)
return "Unmatched '}' in the middle of an array";
if (p->last_seen != JV_LAST_VALUE && p->last_seen != JV_LAST_OPEN_OBJECT)
return "Unmatched '}'";
if (p->last_seen != JV_LAST_OPEN_OBJECT)
p->output = JV_ARRAY(jv_copy(p->path));
}
p->path = jv_array_slice(p->path, 0, --(p->stacklen)); // pop
jv_free(p->next);
p->next = jv_invalid();
if (p->last_seen == JV_LAST_OPEN_OBJECT)
p->output = JV_ARRAY(jv_copy(p->path), jv_object()); // Empty arrays are leaves
if (p->stacklen == 0)
p->last_seen = JV_LAST_NONE;
else
p->last_seen = JV_LAST_VALUE;
break;
}
return 0;
}
static void tokenadd(struct jv_parser* p, char c) {
assert(p->tokenpos <= p->tokenlen);
@@ -170,7 +410,7 @@ static pfunc found_string(struct jv_parser* p) {
char* in = p->tokenbuf;
char* out = p->tokenbuf;
char* end = p->tokenbuf + p->tokenpos;
while (in < end) {
char c = *in++;
if (c == '\\') {
@@ -207,7 +447,8 @@ static pfunc found_string(struct jv_parser* p) {
codepoint = 0x10000 + (((codepoint - 0xD800) << 10)
|(surrogate - 0xDC00));
}
// FIXME assert valid codepoint
if (codepoint > 0x10FFFF)
codepoint = 0xFFFD; // U+FFFD REPLACEMENT CHARACTER
out += jvp_utf8_encode(codepoint, out);
break;
@@ -215,6 +456,8 @@ static pfunc found_string(struct jv_parser* p) {
return "Invalid escape";
}
} else {
if (c > 0 && c < 0x001f)
return "Invalid string: control characters from U+0000 through U+001F must be escaped";
*out++ = c;
}
}
@@ -236,7 +479,7 @@ static pfunc check_literal(struct jv_parser* p) {
}
if (pattern) {
if (p->tokenpos != plen) return "Invalid literal";
for (int i=0; i<plen; i++)
for (int i=0; i<plen; i++)
if (p->tokenbuf[i] != pattern[i])
return "Invalid literal";
TRY(value(p, v));
@@ -285,7 +528,7 @@ static chclass classify(char c) {
static const presult OK = "output produced";
static int check_done(struct jv_parser* p, jv* out) {
static int parse_check_done(struct jv_parser* p, jv* out) {
if (p->stackpos == 0 && jv_is_valid(p->next)) {
*out = p->next;
p->next = jv_invalid();
@@ -295,15 +538,85 @@ static int check_done(struct jv_parser* p, jv* out) {
}
}
static int stream_check_done(struct jv_parser* p, jv* out) {
if (p->stacklen == 0 && jv_is_valid(p->next)) {
*out = JV_ARRAY(jv_copy(p->path),p->next);
p->next = jv_invalid();
return 1;
} else if (jv_is_valid(p->output)) {
if (jv_array_length(jv_copy(p->output)) > 2) {
// At end of an array or object, necessitating one more output by
// which to indicate this
*out = jv_array_slice(jv_copy(p->output), 0, 2);
p->output = jv_array_slice(p->output, 0, 1); // arrange one more output
} else {
// No further processing needed
*out = p->output;
p->output = jv_invalid();
}
return 1;
} else {
return 0;
}
}
static int parse_check_truncation(struct jv_parser* p) {
return ((p->flags & JV_PARSE_SEQ) && !p->last_ch_was_ws && (p->stackpos > 0 || p->tokenpos > 0 || jv_get_kind(p->next) == JV_KIND_NUMBER));
}
static int stream_check_truncation(struct jv_parser* p) {
jv_kind k = jv_get_kind(p->next);
return (p->stacklen > 0 || k == JV_KIND_NUMBER || k == JV_KIND_TRUE || k == JV_KIND_FALSE || k == JV_KIND_NULL);
}
static int parse_is_top_num(struct jv_parser* p) {
return (p->stackpos == 0 && jv_get_kind(p->next) == JV_KIND_NUMBER);
}
static int stream_is_top_num(struct jv_parser* p) {
return (p->stacklen == 0 && jv_get_kind(p->next) == JV_KIND_NUMBER);
}
#define check_done(p, o) \
(((p)->flags & JV_PARSE_STREAMING) ? stream_check_done((p), (o)) : parse_check_done((p), (o)))
#define token(p, ch) \
(((p)->flags & JV_PARSE_STREAMING) ? stream_token((p), (ch)) : parse_token((p), (ch)))
#define check_truncation(p) \
(((p)->flags & JV_PARSE_STREAMING) ? stream_check_truncation((p)) : parse_check_truncation((p)))
#define is_top_num(p) \
(((p)->flags & JV_PARSE_STREAMING) ? stream_is_top_num((p)) : parse_is_top_num((p)))
static pfunc scan(struct jv_parser* p, char ch, jv* out) {
p->column++;
if (ch == '\n') {
p->line++;
p->column = 0;
}
if (ch == '\036' /* ASCII RS; see draft-ietf-json-sequence-07 */) {
if (check_truncation(p)) {
if (check_literal(p) == 0 && is_top_num(p))
return "Potentially truncated top-level numeric value";
return "Truncated value";
}
TRY(check_literal(p));
if (p->st == JV_PARSER_NORMAL && check_done(p, out))
return OK;
// shouldn't happen?
assert(!jv_is_valid(*out));
parser_reset(p);
jv_free(*out);
*out = jv_invalid();
return OK;
}
presult answer = 0;
p->last_ch_was_ws = 0;
if (p->st == JV_PARSER_NORMAL) {
chclass cls = classify(ch);
if (cls == WHITESPACE)
p->last_ch_was_ws = 1;
if (cls != LITERAL) {
TRY(check_literal(p));
if (check_done(p, out)) answer = OK;
@@ -341,12 +654,30 @@ static pfunc scan(struct jv_parser* p, char ch, jv* out) {
return answer;
}
struct jv_parser* jv_parser_new(int flags) {
struct jv_parser* p = jv_mem_alloc(sizeof(struct jv_parser));
parser_init(p, flags);
p->flags = flags;
return p;
}
void jv_parser_free(struct jv_parser* p) {
parser_free(p);
jv_mem_free(p);
}
static const unsigned char UTF8_BOM[] = {0xEF,0xBB,0xBF};
int jv_parser_remaining(struct jv_parser* p) {
if (p->curr_buf == 0)
return 0;
return (p->curr_buf_length - p->curr_buf_pos);
}
void jv_parser_set_buf(struct jv_parser* p, const char* buf, int length, int is_partial) {
assert((p->curr_buf == 0 || p->curr_buf_pos == p->curr_buf_length)
&& "previous buffer not exhausted");
while (p->bom_strip_position < sizeof(UTF8_BOM)) {
while (length > 0 && p->bom_strip_position < sizeof(UTF8_BOM)) {
if ((unsigned char)*buf == UTF8_BOM[p->bom_strip_position]) {
// matched a BOM character
buf++;
@@ -368,43 +699,118 @@ void jv_parser_set_buf(struct jv_parser* p, const char* buf, int length, int is_
p->curr_buf_is_partial = is_partial;
}
static jv make_error(struct jv_parser*, const char *, ...) JV_PRINTF_LIKE(2, 3);
static jv make_error(struct jv_parser* p, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
jv e = jv_string_vfmt(fmt, ap);
va_end(ap);
if ((p->flags & JV_PARSE_STREAM_ERRORS))
return JV_ARRAY(e, jv_copy(p->path));
return jv_invalid_with_msg(e);
}
jv jv_parser_next(struct jv_parser* p) {
assert(p->curr_buf && "a buffer must be provided");
if (p->bom_strip_position == 0xff) return jv_invalid_with_msg(jv_string("Malformed BOM"));
jv value;
if (p->eof)
return jv_invalid();
if (!p->curr_buf)
return jv_invalid(); // Need a buffer
if (p->bom_strip_position == 0xff) {
if (!(p->flags & JV_PARSE_SEQ))
return jv_invalid_with_msg(jv_string("Malformed BOM"));
p->st =JV_PARSER_WAITING_FOR_RS;
parser_reset(p);
}
jv value = jv_invalid();
if ((p->flags & JV_PARSE_STREAMING) && stream_check_done(p, &value))
return value;
char ch;
presult msg = 0;
while (!msg && p->curr_buf_pos < p->curr_buf_length) {
char ch = p->curr_buf[p->curr_buf_pos++];
ch = p->curr_buf[p->curr_buf_pos++];
if (p->st == JV_PARSER_WAITING_FOR_RS) {
if (ch == '\n') {
p->line++;
p->column = 0;
} else {
p->column++;
}
if (ch == '\036')
p->st = JV_PARSER_NORMAL;
continue; // need to resync, wait for RS
}
msg = scan(p, ch, &value);
}
if (msg == OK) {
return value;
} else if (msg) {
return jv_invalid_with_msg(jv_string_fmt("%s at line %d, column %d", msg, p->line, p->column));
jv_free(value);
if (ch != '\036' && (p->flags & JV_PARSE_SEQ)) {
// Skip to the next RS
p->st = JV_PARSER_WAITING_FOR_RS;
value = make_error(p, "%s at line %d, column %d (need RS to resync)", msg, p->line, p->column);
parser_reset(p);
return value;
}
value = make_error(p, "%s at line %d, column %d", msg, p->line, p->column);
parser_reset(p);
if (!(p->flags & JV_PARSE_SEQ)) {
// We're not parsing a JSON text sequence; throw this buffer away.
// XXX We should fail permanently here.
p->curr_buf = 0;
p->curr_buf_pos = 0;
} // Else ch must be RS; don't clear buf so we can start parsing again after this ch
return value;
} else if (p->curr_buf_is_partial) {
assert(p->curr_buf_pos == p->curr_buf_length);
// need another buffer
return jv_invalid();
} else {
assert(p->curr_buf_pos == p->curr_buf_length);
// at EOF
if (p->st != JV_PARSER_NORMAL)
return jv_invalid_with_msg(jv_string("Unfinished string"));
if ((msg = check_literal(p)))
return jv_invalid_with_msg(jv_string(msg));
if (p->stackpos != 0)
return jv_invalid_with_msg(jv_string("Unfinished JSON term"));
// p->next is either invalid (nothing here but no syntax error)
p->eof = 1;
assert(p->curr_buf_pos == p->curr_buf_length);
jv_free(value);
if (p->st == JV_PARSER_WAITING_FOR_RS)
return make_error(p, "Unfinished abandoned text at EOF at line %d, column %d", p->line, p->column);
if (p->st != JV_PARSER_NORMAL) {
value = make_error(p, "Unfinished string at EOF at line %d, column %d", p->line, p->column);
parser_reset(p);
p->st = JV_PARSER_WAITING_FOR_RS;
return value;
}
if ((msg = check_literal(p))) {
value = make_error(p, "%s at EOF at line %d, column %d", msg, p->line, p->column);
parser_reset(p);
p->st = JV_PARSER_WAITING_FOR_RS;
return value;
}
if (((p->flags & JV_PARSE_STREAMING) && p->stacklen != 0) ||
(!(p->flags & JV_PARSE_STREAMING) && p->stackpos != 0)) {
value = make_error(p, "Unfinished JSON term at EOF at line %d, column %d", p->line, p->column);
parser_reset(p);
p->st = JV_PARSER_WAITING_FOR_RS;
return value;
}
// p->next is either invalid (nothing here, but no syntax error)
// or valid (this is the value). either way it's the thing to return
value = p->next;
if ((p->flags & JV_PARSE_STREAMING) && jv_is_valid(p->next)) {
value = JV_ARRAY(jv_copy(p->path), p->next); // except in streaming mode we've got to make it [path,value]
} else {
value = p->next;
}
p->next = jv_invalid();
if ((p->flags & JV_PARSE_SEQ) && !p->last_ch_was_ws && jv_get_kind(value) == JV_KIND_NUMBER) {
jv_free(value);
return make_error(p, "Potentially truncated top-level numeric value at EOF at line %d, column %d", p->line, p->column);
}
return value;
}
}
jv jv_parse_sized(const char* string, int length) {
struct jv_parser parser;
jv_parser_init(&parser);
parser_init(&parser, 0);
jv_parser_set_buf(&parser, string, length, 0);
jv value = jv_parser_next(&parser);
if (jv_is_valid(value)) {
@@ -429,7 +835,7 @@ jv jv_parse_sized(const char* string, int length) {
jv_free(value);
value = jv_invalid_with_msg(jv_string("Expected JSON value"));
}
jv_parser_free(&parser);
parser_free(&parser);
if (!jv_is_valid(value) && jv_invalid_has_msg(jv_copy(value))) {
jv msg = jv_invalid_get_msg(value);
-37
View File
@@ -1,37 +0,0 @@
#ifndef JV_PARSE_H
#define JV_PARSE_H
#include "jv_dtoa.h"
struct jv_parser {
const char* curr_buf;
int curr_buf_length;
int curr_buf_pos;
int curr_buf_is_partial;
unsigned bom_strip_position;
jv* stack;
int stackpos;
int stacklen;
jv next;
char* tokenbuf;
int tokenpos;
int tokenlen;
int line, column;
struct dtoa_context dtoa;
enum {
JV_PARSER_NORMAL,
JV_PARSER_STRING,
JV_PARSER_STRING_ESCAPE
} st;
};
void jv_parser_init(struct jv_parser* p);
void jv_parser_free(struct jv_parser* p);
void jv_parser_set_buf(struct jv_parser* p, const char* buf, int length, int is_partial);
jv jv_parser_next(struct jv_parser* p);
#endif
+177 -78
View File
@@ -1,8 +1,15 @@
#include "jv.h"
#include <assert.h>
#include <stdio.h>
#include <float.h>
#include <string.h>
#ifdef WIN32
#include <windows.h>
#include <io.h>
#include <fileapi.h>
#endif
#include "jv.h"
#include "jv_dtoa.h"
#include "jv_unicode.h"
@@ -10,77 +17,90 @@
#define COL(c) (ESC "[" c "m")
#define COLRESET (ESC "[0m")
// Colour table. See http://en.wikipedia.org/wiki/ANSI_escape_code#Colors
// Colour table. See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
// for how to choose these.
static const jv_kind colour_kinds[] =
static const jv_kind colour_kinds[] =
{JV_KIND_NULL, JV_KIND_FALSE, JV_KIND_TRUE, JV_KIND_NUMBER,
JV_KIND_STRING, JV_KIND_ARRAY, JV_KIND_OBJECT};
static const char* const colours[] =
{COL("30;1"), COL("0"), COL("0"), COL("0"),
COL("32"), COL("37"), COL("37")};
{COL("1;30"), COL("0;39"), COL("0;39"), COL("0;39"),
COL("0;32"), COL("1;39"), COL("1;39")};
#define FIELD_COLOUR COL("34;1")
static void put_buf(const char* s, int len, FILE* fout, jv* strout) {
static void put_buf(const char *s, int len, FILE *fout, jv *strout, int is_tty) {
if (strout) {
*strout = jv_string_append_buf(*strout, s, len);
} else {
#ifdef WIN32
/* See util.h */
if (is_tty)
WriteFile((HANDLE)_get_osfhandle(fileno(fout)), s, len, NULL, NULL);
else
fwrite(s, 1, len, fout);
#else
fwrite(s, 1, len, fout);
#endif
}
}
static void put_char(char c, FILE* fout, jv* strout) {
put_buf(&c, 1, fout, strout);
static void put_char(char c, FILE* fout, jv* strout, int T) {
put_buf(&c, 1, fout, strout, T);
}
static void put_str(const char* s, FILE* fout, jv* strout) {
put_buf(s, strlen(s), fout, strout);
static void put_str(const char* s, FILE* fout, jv* strout, int T) {
put_buf(s, strlen(s), fout, strout, T);
}
static void put_space(int n, FILE* fout, jv* strout) {
while (n--) {
put_char(' ', fout, strout);
static void put_indent(int n, int flags, FILE* fout, jv* strout, int T) {
if (flags & JV_PRINT_TAB) {
while (n--)
put_char('\t', fout, strout, T);
} else {
n *= ((flags & (JV_PRINT_SPACE0 | JV_PRINT_SPACE1 | JV_PRINT_SPACE2)) >> 8);
while (n--)
put_char(' ', fout, strout, T);
}
}
static void jvp_dump_string(jv str, int ascii_only, FILE* F, jv* S) {
static void jvp_dump_string(jv str, int ascii_only, FILE* F, jv* S, int T) {
assert(jv_get_kind(str) == JV_KIND_STRING);
const char* i = jv_string_value(str);
const char* end = i + jv_string_length_bytes(jv_copy(str));
const char* cstart;
int c = 0;
char buf[32];
put_char('"', F, S);
put_char('"', F, S, T);
while ((i = jvp_utf8_next((cstart = i), end, &c))) {
assert(c != -1);
int unicode_escape = 0;
if (0x20 <= c && c <= 0x7E) {
// printable ASCII
if (c == '"' || c == '\\') {
put_char('\\', F, S);
put_char('\\', F, S, T);
}
put_char(c, F, S);
put_char(c, F, S, T);
} else if (c < 0x20 || c == 0x7F) {
// ASCII control character
switch (c) {
case '\b':
put_char('\\', F, S);
put_char('b', F, S);
put_char('\\', F, S, T);
put_char('b', F, S, T);
break;
case '\t':
put_char('\\', F, S);
put_char('t', F, S);
put_char('\\', F, S, T);
put_char('t', F, S, T);
break;
case '\r':
put_char('\\', F, S);
put_char('r', F, S);
put_char('\\', F, S, T);
put_char('r', F, S, T);
break;
case '\n':
put_char('\\', F, S);
put_char('n', F, S);
put_char('\\', F, S, T);
put_char('n', F, S, T);
break;
case '\f':
put_char('\\', F, S);
put_char('f', F, S);
put_char('\\', F, S, T);
put_char('f', F, S, T);
break;
default:
unicode_escape = 1;
@@ -90,7 +110,7 @@ static void jvp_dump_string(jv str, int ascii_only, FILE* F, jv* S) {
if (ascii_only) {
unicode_escape = 1;
} else {
put_buf(cstart, i - cstart, F, S);
put_buf(cstart, i - cstart, F, S, T);
}
}
if (unicode_escape) {
@@ -98,27 +118,34 @@ static void jvp_dump_string(jv str, int ascii_only, FILE* F, jv* S) {
sprintf(buf, "\\u%04x", c);
} else {
c -= 0x10000;
sprintf(buf, "\\u%04x\\u%04x",
sprintf(buf, "\\u%04x\\u%04x",
0xD800 | ((c & 0xffc00) >> 10),
0xDC00 | (c & 0x003ff));
}
put_str(buf, F, S);
put_str(buf, F, S, T);
}
}
assert(c != -1);
put_char('"', F, S);
put_char('"', F, S, T);
}
enum { INDENT = 2 };
static void put_refcnt(struct dtoa_context* C, int refcnt, FILE *F, jv* S, int T){
char buf[JVP_DTOA_FMT_MAX_LEN];
put_char(' ', F, S, T);
put_char('(', F, S, T);
put_str(jvp_dtoa_fmt(C, buf, refcnt), F, S, T);
put_char(')', F, S, T);
}
static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FILE* F, jv* S) {
char buf[JVP_DTOA_FMT_MAX_LEN];
const char* colour = 0;
double refcnt = (flags & JV_PRINT_REFCOUNT) ? jv_get_refcnt(x) - 1 : -1;
if (flags & JV_PRINT_COLOUR) {
for (unsigned i=0; i<sizeof(colour_kinds)/sizeof(colour_kinds[0]); i++) {
if (jv_get_kind(x) == colour_kinds[i]) {
colour = colours[i];
put_str(colour, F, S);
put_str(colour, F, S, flags & JV_PRINT_ISATTY);
break;
}
}
@@ -126,119 +153,175 @@ static void jv_dump_term(struct dtoa_context* C, jv x, int flags, int indent, FI
switch (jv_get_kind(x)) {
default:
case JV_KIND_INVALID:
assert(0 && "Invalid value");
if (flags & JV_PRINT_INVALID) {
jv msg = jv_invalid_get_msg(jv_copy(x));
if (jv_get_kind(msg) == JV_KIND_STRING) {
put_str("<invalid:", F, S, flags & JV_PRINT_ISATTY);
jvp_dump_string(msg, flags | JV_PRINT_ASCII, F, S, flags & JV_PRINT_ISATTY);
put_str(">", F, S, flags & JV_PRINT_ISATTY);
} else {
put_str("<invalid>", F, S, flags & JV_PRINT_ISATTY);
}
} else {
assert(0 && "Invalid value");
}
break;
case JV_KIND_NULL:
put_str("null", F, S);
put_str("null", F, S, flags & JV_PRINT_ISATTY);
break;
case JV_KIND_FALSE:
put_str("false", F, S);
put_str("false", F, S, flags & JV_PRINT_ISATTY);
break;
case JV_KIND_TRUE:
put_str("true", F, S);
put_str("true", F, S, flags & JV_PRINT_ISATTY);
break;
case JV_KIND_NUMBER: {
double d = jv_number_value(x);
if (d != d) {
// JSON doesn't have NaN, so we'll render it as "null"
put_str("null", F, S);
put_str("null", F, S, flags & JV_PRINT_ISATTY);
} else {
// Normalise infinities to something we can print in valid JSON
if (d > DBL_MAX) d = DBL_MAX;
if (d < -DBL_MAX) d = -DBL_MAX;
put_str(jvp_dtoa_fmt(C, buf, d), F, S);
put_str(jvp_dtoa_fmt(C, buf, d), F, S, flags & JV_PRINT_ISATTY);
}
break;
}
case JV_KIND_STRING:
jvp_dump_string(x, flags & JV_PRINT_ASCII, F, S);
jvp_dump_string(x, flags & JV_PRINT_ASCII, F, S, flags & JV_PRINT_ISATTY);
if (flags & JV_PRINT_REFCOUNT)
put_refcnt(C, refcnt, F, S, flags & JV_PRINT_ISATTY);
break;
case JV_KIND_ARRAY: {
if (jv_array_length(jv_copy(x)) == 0) {
put_str("[]", F, S);
put_str("[]", F, S, flags & JV_PRINT_ISATTY);
break;
}
put_str("[", F, S);
put_str("[", F, S, flags & JV_PRINT_ISATTY);
if (flags & JV_PRINT_PRETTY) {
put_char('\n', F, S);
put_space(indent+INDENT, F, S);
put_char('\n', F, S, flags & JV_PRINT_ISATTY);
put_indent(indent + 1, flags, F, S, flags & JV_PRINT_ISATTY);
}
jv_array_foreach(x, i, elem) {
if (i!=0) {
if (flags & JV_PRINT_PRETTY) {
put_str(",\n", F, S);
put_space(indent+INDENT, F, S);
put_str(",\n", F, S, flags & JV_PRINT_ISATTY);
put_indent(indent + 1, flags, F, S, flags & JV_PRINT_ISATTY);
} else {
put_str(",", F, S);
put_str(",", F, S, flags & JV_PRINT_ISATTY);
}
}
jv_dump_term(C, elem, flags, indent + INDENT, F, S);
if (colour) put_str(colour, F, S);
jv_dump_term(C, elem, flags, indent + 1, F, S);
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY);
}
if (flags & JV_PRINT_PRETTY) {
put_char('\n', F, S);
put_space(indent, F, S);
put_char('\n', F, S, flags & JV_PRINT_ISATTY);
put_indent(indent, flags, F, S, flags & JV_PRINT_ISATTY);
}
if (colour) put_str(colour, F, S);
put_char(']', F, S);
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY);
put_char(']', F, S, flags & JV_PRINT_ISATTY);
if (flags & JV_PRINT_REFCOUNT)
put_refcnt(C, refcnt, F, S, flags & JV_PRINT_ISATTY);
break;
}
case JV_KIND_OBJECT: {
if (jv_object_length(jv_copy(x)) == 0) {
put_str("{}", F, S);
put_str("{}", F, S, flags & JV_PRINT_ISATTY);
break;
}
put_char('{', F, S);
put_char('{', F, S, flags & JV_PRINT_ISATTY);
if (flags & JV_PRINT_PRETTY) {
put_char('\n', F, S);
put_space(indent+INDENT, F, S);
put_char('\n', F, S, flags & JV_PRINT_ISATTY);
put_indent(indent + 1, flags, F, S, flags & JV_PRINT_ISATTY);
}
int first = 1;
jv_object_foreach(x, key, value) {
int i = 0;
jv keyset = jv_null();
while (1) {
jv key, value;
if (flags & JV_PRINT_SORTED) {
if (first) {
keyset = jv_keys(jv_copy(x));
i = 0;
} else {
i++;
}
if (i >= jv_array_length(jv_copy(keyset))) {
jv_free(keyset);
break;
}
key = jv_array_get(jv_copy(keyset), i);
value = jv_object_get(jv_copy(x), jv_copy(key));
} else {
if (first) {
i = jv_object_iter(x);
} else {
i = jv_object_iter_next(x, i);
}
if (!jv_object_iter_valid(x, i)) break;
key = jv_object_iter_key(x, i);
value = jv_object_iter_value(x, i);
}
if (!first) {
if (flags & JV_PRINT_PRETTY){
put_str(",\n", F, S);
put_space(indent+INDENT, F, S);
put_str(",\n", F, S, flags & JV_PRINT_ISATTY);
put_indent(indent + 1, flags, F, S, flags & JV_PRINT_ISATTY);
} else {
put_str(",", F, S);
put_str(",", F, S, flags & JV_PRINT_ISATTY);
}
}
if (colour) put_str(COLRESET, F, S);
if (colour) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY);
first = 0;
if (colour) put_str(FIELD_COLOUR, F, S);
jvp_dump_string(key, flags & JV_PRINT_ASCII, F, S);
if (colour) put_str(FIELD_COLOUR, F, S, flags & JV_PRINT_ISATTY);
jvp_dump_string(key, flags & JV_PRINT_ASCII, F, S, flags & JV_PRINT_ISATTY);
jv_free(key);
if (colour) put_str(COLRESET, F, S);
if (colour) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY);
if (colour) put_str(colour, F, S);
put_str((flags & JV_PRINT_PRETTY) ? ": " : ":", F, S);
if (colour) put_str(COLRESET, F, S);
jv_dump_term(C, value, flags, indent + INDENT, F, S);
if (colour) put_str(colour, F, S);
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY);
put_str((flags & JV_PRINT_PRETTY) ? ": " : ":", F, S, flags & JV_PRINT_ISATTY);
if (colour) put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY);
jv_dump_term(C, value, flags, indent + 1, F, S);
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY);
}
if (flags & JV_PRINT_PRETTY) {
put_char('\n', F, S);
put_space(indent, F, S);
put_char('\n', F, S, flags & JV_PRINT_ISATTY);
put_indent(indent, flags, F, S, flags & JV_PRINT_ISATTY);
}
if (colour) put_str(colour, F, S);
put_char('}', F, S);
if (colour) put_str(colour, F, S, flags & JV_PRINT_ISATTY);
put_char('}', F, S, flags & JV_PRINT_ISATTY);
if (flags & JV_PRINT_REFCOUNT)
put_refcnt(C, refcnt, F, S, flags & JV_PRINT_ISATTY);
}
}
jv_free(x);
if (colour) {
put_str(COLRESET, F, S);
put_str(COLRESET, F, S, flags & JV_PRINT_ISATTY);
}
}
void jv_dump(jv x, int flags) {
void jv_dumpf(jv x, FILE *f, int flags) {
struct dtoa_context C;
jvp_dtoa_context_init(&C);
jv_dump_term(&C, x, flags, 0, stdout, 0);
jv_dump_term(&C, x, flags, 0, f, 0);
jvp_dtoa_context_free(&C);
}
void jv_dump(jv x, int flags) {
jv_dumpf(x, stdout, flags);
}
/* This one is nice for use in debuggers */
void jv_show(jv x, int flags) {
if (flags == -1)
flags = JV_PRINT_PRETTY | JV_PRINT_COLOUR | JV_PRINT_INDENT_FLAGS(2);
jv_dumpf(jv_copy(x), stderr, flags | JV_PRINT_INVALID);
fflush(stderr);
}
jv jv_dump_string(jv x, int flags) {
struct dtoa_context C;
jvp_dtoa_context_init(&C);
@@ -247,3 +330,19 @@ jv jv_dump_string(jv x, int flags) {
jvp_dtoa_context_free(&C);
return s;
}
char *jv_dump_string_trunc(jv x, char *outbuf, size_t bufsize) {
x = jv_dump_string(x,0);
const char* p = jv_string_value(x);
const size_t len = strlen(p);
strncpy(outbuf, p, bufsize);
outbuf[bufsize - 1] = 0;
if (len > bufsize - 1 && bufsize >= 4) {
// Indicate truncation with '...'
outbuf[bufsize - 2]='.';
outbuf[bufsize - 3]='.';
outbuf[bufsize - 4]='.';
}
jv_free(x);
return outbuf;
}
+48 -16
View File
@@ -3,35 +3,67 @@
#include "jv_unicode.h"
#include "jv_utf8_tables.h"
const char* jvp_utf8_next(const char* in, const char* end, int* codepoint) {
const char* jvp_utf8_next(const char* in, const char* end, int* codepoint_ret) {
assert(in <= end);
if (in == end) {
codepoint = 0;
return 0;
}
int codepoint = -1;
unsigned char first = (unsigned char)in[0];
int length = utf8_coding_length[first];
if (length == 0 || length == UTF8_CONTINUATION_BYTE || in + length > end) {
*codepoint = -1;
return 0;
}
*codepoint = ((unsigned)in[0]) & utf8_coding_bits[first];
for (int i=1; i<length; i++) {
int ch = (unsigned char)in[i];
if (utf8_coding_length[(unsigned char)in[i]] != UTF8_CONTINUATION_BYTE){
*codepoint = -1;
return 0;
if ((first & 0x80) == 0) {
/* Fast-path for ASCII */
codepoint = first;
length = 1;
} else if (length == 0 || length == UTF8_CONTINUATION_BYTE) {
/* Bad single byte - either an invalid byte or an out-of-place continuation byte */
length = 1;
} else if (in + length > end) {
/* String ends before UTF8 sequence ends */
length = end - in;
} else {
codepoint = ((unsigned)in[0]) & utf8_coding_bits[first];
for (int i=1; i<length; i++) {
unsigned ch = (unsigned char)in[i];
if (utf8_coding_length[ch] != UTF8_CONTINUATION_BYTE){
/* Invalid UTF8 sequence - not followed by the right number of continuation bytes */
codepoint = -1;
length = i;
break;
}
codepoint = (codepoint << 6) | (ch & 0x3f);
}
if (codepoint < utf8_first_codepoint[length]) {
/* Overlong UTF8 sequence */
codepoint = -1;
}
if (0xD800 <= codepoint && codepoint <= 0xDFFF) {
/* Surrogate codepoints can't be encoded in UTF8 */
codepoint = -1;
}
if (codepoint > 0x10FFFF) {
/* Outside Unicode range */
codepoint = -1;
}
*codepoint = (*codepoint << 6) | (ch & 0x3f);
}
assert(length > 0);
*codepoint_ret = codepoint;
return in + length;
}
int jvp_utf8_verify(const char* in, const char* end) {
int codepoint = 0;
int jvp_utf8_is_valid(const char* in, const char* end) {
int codepoint;
while ((in = jvp_utf8_next(in, end, &codepoint))) {
if (codepoint == -1) return 0;
}
return codepoint != -1;
return 1;
}
int jvp_utf8_decode_length(char startchar) {
if ((startchar & 0x80) == 0) return 1;
else if ((startchar & 0xC0) == 0xC0) return 2;
else if ((startchar & 0xE0) == 0xE0) return 3;
else return 4;
}
int jvp_utf8_encode_length(int codepoint) {
+1 -1
View File
@@ -2,7 +2,7 @@
#define JV_UNICODE_H
const char* jvp_utf8_next(const char* in, const char* end, int* codepoint);
int jvp_utf8_is_valid(const char* in, const char* end);
int jvp_utf8_decode_length(char startchar);
+2
View File
@@ -33,3 +33,5 @@ static const unsigned char utf8_coding_bits[] =
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const int utf8_first_codepoint[] =
{0x00, 0x00, 0x80, 0x800, 0x10000};
+2442
View File
File diff suppressed because it is too large. Load diff
+362
View File
@@ -0,0 +1,362 @@
#ifndef jq_yyHEADER_H
#define jq_yyHEADER_H 1
#define jq_yyIN_HEADER 1
#line 6 "lexer.h"
#line 8 "lexer.h"
#define YY_INT_ALIGNED short int
/* A lexical scanner generated by flex */
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
#define YY_FLEX_SUBMINOR_VERSION 35
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
/* First, we deal with platform-specific or compiler-specific issues. */
/* begin standard C headers. */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
/* end standard C headers. */
/* flex integer type definitions */
#ifndef FLEXINT_H
#define FLEXINT_H
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
* if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN (-128)
#endif
#ifndef INT16_MIN
#define INT16_MIN (-32767-1)
#endif
#ifndef INT32_MIN
#define INT32_MIN (-2147483647-1)
#endif
#ifndef INT8_MAX
#define INT8_MAX (127)
#endif
#ifndef INT16_MAX
#define INT16_MAX (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
#ifndef UINT8_MAX
#define UINT8_MAX (255U)
#endif
#ifndef UINT16_MAX
#define UINT16_MAX (65535U)
#endif
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
#endif /* ! C99 */
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST
#else /* ! __cplusplus */
/* C99 requires __STDC__ to be defined as 1. */
#if defined (__STDC__)
#define YY_USE_CONST
#endif /* defined (__STDC__) */
#endif /* ! __cplusplus */
#ifdef YY_USE_CONST
#define yyconst const
#else
#define yyconst
#endif
/* An opaque pointer. */
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
/* For convenience, these vars (plus the bison vars far below)
are macros in the reentrant scanner. */
#define yyin yyg->yyin_r
#define yyout yyg->yyout_r
#define yyextra yyg->yyextra_r
#define yyleng yyg->yyleng_r
#define yytext yyg->yytext_r
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k.
* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
* Ditto for the __ia64__ case accordingly.
*/
#define YY_BUF_SIZE 32768
#else
#define YY_BUF_SIZE 16384
#endif /* __ia64__ */
#endif
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
{
FILE *yy_input_file;
char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
yy_size_t yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
int yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
* delete it.
*/
int yy_is_our_buffer;
/* Whether this is an "interactive" input source; if so, and
* if we're using stdio for input, then we want to use getc()
* instead of fread(), to make sure we stop fetching input after
* each newline.
*/
int yy_is_interactive;
/* Whether we're considered to be at the beginning of a line.
* If so, '^' rules will be active on the next match, otherwise
* not.
*/
int yy_at_bol;
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
int yy_buffer_status;
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
void jq_yyrestart (FILE *input_file ,yyscan_t yyscanner );
void jq_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
YY_BUFFER_STATE jq_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
void jq_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
void jq_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
void jq_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
void jq_yypop_buffer_state (yyscan_t yyscanner );
YY_BUFFER_STATE jq_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE jq_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
YY_BUFFER_STATE jq_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
void *jq_yyalloc (yy_size_t ,yyscan_t yyscanner );
void *jq_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
void jq_yyfree (void * ,yyscan_t yyscanner );
/* Begin user sect3 */
#define jq_yywrap(n) 1
#define YY_SKIP_YYWRAP
#define yytext_ptr yytext_r
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
#define INITIAL 0
#define IN_PAREN 1
#define IN_BRACKET 2
#define IN_BRACE 3
#define IN_QQINTERP 4
#define IN_QQSTRING 5
#endif
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
* down here because we want the user's section 1 to have been scanned first.
* The user has a chance to override it with an option.
*/
#include <unistd.h>
#endif
#define YY_EXTRA_TYPE int
int jq_yylex_init (yyscan_t* scanner);
int jq_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
int jq_yylex_destroy (yyscan_t yyscanner );
int jq_yyget_debug (yyscan_t yyscanner );
void jq_yyset_debug (int debug_flag ,yyscan_t yyscanner );
YY_EXTRA_TYPE jq_yyget_extra (yyscan_t yyscanner );
void jq_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
FILE *jq_yyget_in (yyscan_t yyscanner );
void jq_yyset_in (FILE * in_str ,yyscan_t yyscanner );
FILE *jq_yyget_out (yyscan_t yyscanner );
void jq_yyset_out (FILE * out_str ,yyscan_t yyscanner );
int jq_yyget_leng (yyscan_t yyscanner );
char *jq_yyget_text (yyscan_t yyscanner );
int jq_yyget_lineno (yyscan_t yyscanner );
void jq_yyset_lineno (int line_number ,yyscan_t yyscanner );
YYSTYPE * jq_yyget_lval (yyscan_t yyscanner );
void jq_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
YYLTYPE *jq_yyget_lloc (yyscan_t yyscanner );
void jq_yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int jq_yywrap (yyscan_t yyscanner );
#else
extern int jq_yywrap (yyscan_t yyscanner );
#endif
#endif
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
#endif
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
#endif
#ifndef YY_NO_INPUT
#endif
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#ifdef __ia64__
/* On IA-64, the buffer size is 16k, not 8k */
#define YY_READ_BUF_SIZE 16384
#else
#define YY_READ_BUF_SIZE 8192
#endif /* __ia64__ */
#endif
/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
extern int jq_yylex \
(YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
#define YY_DECL int jq_yylex \
(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
#endif /* !YY_DECL */
/* yy_get_previous_state - get the state just before the EOB char was reached */
#undef YY_NEW_FILE
#undef YY_FLUSH_BUFFER
#undef yy_set_bol
#undef yy_new_buffer
#undef yy_set_interactive
#undef YY_DO_BEFORE_ACTION
#ifdef YY_DECL_IS_OURS
#undef YY_DECL_IS_OURS
#undef YY_DECL
#endif
#line 129 "lexer.l"
#line 361 "lexer.h"
#undef jq_yyIN_HEADER
#endif /* jq_yyHEADER_H */
+16 -3
View File
@@ -1,4 +1,5 @@
%{
#include <assert.h>
#include "jv_alloc.h"
#include "compile.h"
@@ -41,6 +42,9 @@ struct lexer_param;
"!=" { return NEQ; }
"==" { return EQ; }
"as" { return AS; }
"import" { return IMPORT; }
"include" { return INCLUDE; }
"module" { return MODULE; }
"def" { return DEF; }
"if" { return IF; }
"then" { return THEN; }
@@ -50,16 +54,24 @@ struct lexer_param;
"or" { return OR; }
"end" { return END; }
"reduce" { return REDUCE; }
"foreach" { return FOREACH; }
"//" { return DEFINEDOR; }
"try" { return TRY; }
"catch" { return CATCH; }
"label" { return LABEL; }
"break" { return BREAK; }
"__loc__" { return LOC; }
"|=" { return SETPIPE; }
"+=" { return SETPLUS; }
"-=" { return SETMINUS; }
"*=" { return SETMULT; }
"/=" { return SETDIV; }
"%=" { return SETMOD; }
"//=" { return SETDEFINEDOR; }
"<=" { return LESSEQ; }
">=" { return GREATEREQ; }
"."|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"\$"|"<"|">" { return yytext[0];}
".." { return REC; }
"."|"?"|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"%"|"\$"|"<"|">" { return yytext[0];}
"["|"{"|"(" {
return enter(yytext[0], YY_START, yyscanner);
@@ -92,7 +104,7 @@ struct lexer_param;
}
(\\[^u(]|\\u[a-zA-Z0-9]{0,4})+ {
/* pass escapes to the json parser */
jv escapes = jv_string_fmt("\"%.*s\"", yyleng, yytext);
jv escapes = jv_string_fmt("\"%.*s\"", (int)yyleng, yytext);
yylval->literal = jv_parse_sized(jv_string_value(escapes), jv_string_length_bytes(jv_copy(escapes)));
jv_free(escapes);
return QQSTRING_TEXT;
@@ -107,7 +119,8 @@ struct lexer_param;
}
[a-zA-Z_][a-zA-Z_0-9]* { yylval->literal = jv_string(yytext); return IDENT;}
([a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]* { yylval->literal = jv_string(yytext); return IDENT;}
\.[a-zA-Z_][a-zA-Z_0-9]* { yylval->literal = jv_string(yytext+1); return FIELD;}
[ \n\t]+ {}
+160
View File
@@ -0,0 +1,160 @@
#ifdef HAVE_ACOS
LIBM_DD(acos)
#else
LIBM_DD_NO(acos)
#endif
#ifdef HAVE_ACOSH
LIBM_DD(acosh)
#else
LIBM_DD_NO(acosh)
#endif
#ifdef HAVE_ASIN
LIBM_DD(asin)
#else
LIBM_DD_NO(asin)
#endif
#ifdef HAVE_ASINH
LIBM_DD(asinh)
#else
LIBM_DD_NO(asinh)
#endif
#ifdef HAVE_ATAN
LIBM_DD(atan)
#else
LIBM_DD_NO(atan)
#endif
#ifdef HAVE_ATANH
LIBM_DD(atanh)
#else
LIBM_DD_NO(atanh)
#endif
#ifdef HAVE_CBRT
LIBM_DD(cbrt)
#else
LIBM_DD_NO(cbrt)
#endif
#ifdef HAVE_COS
LIBM_DD(cos)
#else
LIBM_DD_NO(cos)
#endif
#ifdef HAVE_COSH
LIBM_DD(cosh)
#else
LIBM_DD_NO(cosh)
#endif
#ifdef HAVE_EXP2
LIBM_DD(exp2)
#else
LIBM_DD_NO(exp2)
#endif
#ifdef HAVE_EXP
LIBM_DD(exp)
#else
LIBM_DD_NO(exp)
#endif
#ifdef HAVE_FLOOR
LIBM_DD(floor)
#else
LIBM_DD_NO(floor)
#endif
#ifdef HAVE_J0
LIBM_DD(j0)
#else
LIBM_DD_NO(j0)
#endif
#ifdef HAVE_J1
LIBM_DD(j1)
#else
LIBM_DD_NO(j1)
#endif
#ifdef HAVE_LOG10
LIBM_DD(log10)
#else
LIBM_DD_NO(log10)
#endif
#ifdef HAVE_LOG2
LIBM_DD(log2)
#else
LIBM_DD_NO(log2)
#endif
#ifdef HAVE_LOG
LIBM_DD(log)
#else
LIBM_DD_NO(log)
#endif
#ifdef HAVE_SIN
LIBM_DD(sin)
#else
LIBM_DD_NO(sin)
#endif
#ifdef HAVE_SINH
LIBM_DD(sinh)
#else
LIBM_DD_NO(sinh)
#endif
#ifdef HAVE_SQRT
LIBM_DD(sqrt)
#else
LIBM_DD_NO(sqrt)
#endif
#ifdef HAVE_TAN
LIBM_DD(tan)
#else
LIBM_DD_NO(tan)
#endif
#ifdef HAVE_TANH
LIBM_DD(tanh)
#else
LIBM_DD_NO(tanh)
#endif
#ifdef HAVE_TGAMMA
LIBM_DD(tgamma)
#else
LIBM_DD_NO(tgamma)
#endif
#ifdef HAVE_Y0
LIBM_DD(y0)
#else
LIBM_DD_NO(y0)
#endif
#ifdef HAVE_Y1
LIBM_DD(y1)
#else
LIBM_DD_NO(y1)
#endif
#ifdef HAVE_POW
LIBM_DDD(pow)
#else
LIBM_DDD_NO(pow)
#endif
#ifdef HAVE_JN
LIBM_DID(jn)
#endif
#ifdef HAVE_YN
LIBM_DID(yn)
#endif
#ifdef HAVE_ATAN2
LIBM_DDD(atan2)
#else
LIBM_DDD_NO(atan2)
#endif
#ifdef HAVE_HYPOT
LIBM_DDD(hypot)
#else
LIBM_DDD_NO(hypot)
#endif
#ifdef HAVE_REMAINDER
LIBM_DDD(remainder)
#else
LIBM_DDD_NO(remainder)
#endif
#if 0
#ifdef HAVE_SCALBN
LIBM_DDI(scalbn)
#endif
#ifdef HAVE_LGAMMA_R
LIBM_DDIP(lgamma_r)
#endif
#endif
+393
View File
@@ -0,0 +1,393 @@
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <libgen.h>
#ifdef WIN32
#include <windows.h>
#include <shlwapi.h>
#endif
#include "jq_parser.h"
#include "locfile.h"
#include "jv.h"
#include "jq.h"
#include "parser.h"
#include "util.h"
#include "compile.h"
struct lib_loading_state {
char **names;
block *defs;
uint64_t ct;
};
static int load_library(jq_state *jq, jv lib_path, int is_data, int raw,
const char *as, block *out_block,
struct lib_loading_state *lib_state);
static int path_is_relative(jv p) {
const char *s = jv_string_value(p);
#ifdef WIN32
int res = PathIsRelativeA(s);
#else
int res = *s != '/';
#endif
jv_free(p);
return res;
}
// Given a lib_path to search first, creates a chain of search paths
// in the following order:
// 1. lib_path
// 2. -L paths passed in on the command line (from jq_state*) or builtin list
static jv build_lib_search_chain(jq_state *jq, jv search_path, jv jq_origin, jv lib_origin) {
assert(jv_get_kind(search_path) == JV_KIND_ARRAY);
jv expanded = jv_array();
jv expanded_elt;
jv err = jv_null();
jv_array_foreach(search_path, i, path) {
if (jv_get_kind(path) != JV_KIND_STRING) {
jv_free(path);
continue;
}
path = expand_path(path);
if (!jv_is_valid(path)) {
err = path;
path = jv_null();
continue;
}
if (strcmp(".",jv_string_value(path)) == 0) {
expanded_elt = jv_copy(path);
} else if (strncmp("$ORIGIN/",jv_string_value(path),sizeof("$ORIGIN/") - 1) == 0) {
expanded_elt = jv_string_fmt("%s/%s",
jv_string_value(jq_origin),
jv_string_value(path) + sizeof ("$ORIGIN/") - 1);
} else if (jv_get_kind(lib_origin) == JV_KIND_STRING &&
path_is_relative(jv_copy(path))) {
expanded_elt = jv_string_fmt("%s/%s",
jv_string_value(lib_origin),
jv_string_value(path));
} else {
expanded_elt = path;
path = jv_invalid();
}
expanded = jv_array_append(expanded, expanded_elt);
jv_free(path);
}
jv_free(jq_origin);
jv_free(lib_origin);
jv_free(search_path);
return JV_ARRAY(expanded, err);
}
// Doesn't actually check that name not be an absolute path, and we
// don't have to: we always append relative paths to others (with a '/'
// in between).
static jv validate_relpath(jv name) {
const char *s = jv_string_value(name);
if (strchr(s, '\\')) {
jv res = jv_invalid_with_msg(jv_string_fmt("Modules must be named by relative paths using '/', not '\\' (%s)", s));
jv_free(name);
return res;
}
jv components = jv_string_split(jv_copy(name), jv_string("/"));
jv rp = jv_array_get(jv_copy(components), 0);
components = jv_array_slice(components, 1, jv_array_length(jv_copy(components)));
jv_array_foreach(components, i, x) {
if (!strcmp(jv_string_value(x), "..")) {
jv_free(x);
jv_free(rp);
jv_free(components);
jv res = jv_invalid_with_msg(jv_string_fmt("Relative paths to modules may not traverse to parent directories (%s)", s));
jv_free(name);
return res;
}
if (i > 0 && jv_equal(jv_copy(x), jv_array_get(jv_copy(components), i - 1))) {
jv_free(x);
jv_free(rp);
jv_free(components);
jv res = jv_invalid_with_msg(jv_string_fmt("module names must not have equal consecutive components: %s",
jv_string_value(name)));
jv_free(name);
return res;
}
rp = jv_string_concat(rp, jv_string_concat(jv_string("/"), x));
}
jv_free(components);
jv_free(name);
return rp;
}
// Assumes name has been validated
static jv jv_basename(jv name) {
const char *s = jv_string_value(name);
const char *p = strrchr(s, '/');
if (!p)
return name;
jv res = jv_string_fmt("%s", p);
jv_free(name);
return res;
}
// Asummes validated relative path to module
static jv find_lib(jq_state *jq, jv rel_path, jv search, const char *suffix, jv jq_origin, jv lib_origin) {
if (jv_get_kind(search) != JV_KIND_ARRAY)
return jv_invalid_with_msg(jv_string_fmt("Module search path must be an array"));
if (jv_get_kind(rel_path) != JV_KIND_STRING)
return jv_invalid_with_msg(jv_string_fmt("Module path must be a string"));
struct stat st;
int ret;
// Ideally we should cache this somewhere
search = build_lib_search_chain(jq, search, jq_origin, lib_origin);
jv err = jv_array_get(jv_copy(search), 1);
search = jv_array_get(search, 0);
jv bname = jv_basename(jv_copy(rel_path));
jv_array_foreach(search, i, spath) {
if (jv_get_kind(spath) == JV_KIND_NULL) {
jv_free(spath);
break;
}
if (jv_get_kind(spath) != JV_KIND_STRING ||
strcmp(jv_string_value(spath), "") == 0) {
jv_free(spath);
continue; /* XXX report non-strings in search path?? */
}
// Try ${search_dir}/${rel_path}.jq
jv testpath = jq_realpath(jv_string_fmt("%s/%s%s",
jv_string_value(spath),
jv_string_value(rel_path),
suffix));
ret = stat(jv_string_value(testpath),&st);
if (ret == -1 && errno == ENOENT) {
jv_free(testpath);
// Try ${search_dir}/$(dirname ${rel_path})/jq/main.jq
testpath = jq_realpath(jv_string_fmt("%s/%s/%s%s",
jv_string_value(spath),
jv_string_value(rel_path),
"jq/main",
suffix));
ret = stat(jv_string_value(testpath),&st);
}
if (ret == -1 && errno == ENOENT) {
jv_free(testpath);
// Try ${search_dir}/${rel_path}/$(basename ${rel_path}).jq
testpath = jq_realpath(jv_string_fmt("%s/%s/%s%s",
jv_string_value(spath),
jv_string_value(rel_path),
jv_string_value(bname),
suffix));
ret = stat(jv_string_value(testpath),&st);
}
if (ret == 0) {
jv_free(err);
jv_free(rel_path);
jv_free(search);
jv_free(bname);
jv_free(spath);
return testpath;
}
jv_free(testpath);
jv_free(spath);
}
jv output;
if (!jv_is_valid(err)) {
err = jv_invalid_get_msg(err);
output = jv_invalid_with_msg(jv_string_fmt("module not found: %s (%s)",
jv_string_value(rel_path),
jv_string_value(err)));
} else {
output = jv_invalid_with_msg(jv_string_fmt("module not found: %s",
jv_string_value(rel_path)));
}
jv_free(err);
jv_free(rel_path);
jv_free(search);
jv_free(bname);
return output;
}
static jv default_search(jq_state *jq, jv value) {
if (!jv_is_valid(value)) {
// dependent didn't say; prepend . to system search path listj
jv_free(value);
return jv_array_concat(JV_ARRAY(jv_string(".")), jq_get_lib_dirs(jq));
}
if (jv_get_kind(value) != JV_KIND_ARRAY)
return JV_ARRAY(value);
return value;
}
// XXX Split this into a util that takes a callback, and then...
static int process_dependencies(jq_state *jq, jv jq_origin, jv lib_origin, block *src_block, struct lib_loading_state *lib_state) {
jv deps = block_take_imports(src_block);
block bk = *src_block;
int nerrors = 0;
const char *as_str = NULL;
jv_array_foreach(deps, i, dep) {
int is_data = jv_get_kind(jv_object_get(jv_copy(dep), jv_string("is_data"))) == JV_KIND_TRUE;
int raw = 0;
jv v = jv_object_get(jv_copy(dep), jv_string("raw"));
if (jv_get_kind(v) == JV_KIND_TRUE)
raw = 1;
jv_free(v);
jv relpath = validate_relpath(jv_object_get(jv_copy(dep), jv_string("relpath")));
jv as = jv_object_get(jv_copy(dep), jv_string("as"));
assert(!jv_is_valid(as) || jv_get_kind(as) == JV_KIND_STRING);
if (jv_get_kind(as) == JV_KIND_STRING)
as_str = jv_string_value(as);
jv search = default_search(jq, jv_object_get(dep, jv_string("search")));
// dep is now freed; do not reuse
// find_lib does a lot of work that could be cached...
jv resolved = find_lib(jq, relpath, search, is_data ? ".json" : ".jq", jv_copy(jq_origin), jv_copy(lib_origin));
// XXX ...move the rest of this into a callback.
if (!jv_is_valid(resolved)) {
jv emsg = jv_invalid_get_msg(resolved);
jq_report_error(jq, jv_string_fmt("jq: error: %s\n",jv_string_value(emsg)));
jv_free(emsg);
jv_free(as);
jv_free(deps);
jv_free(jq_origin);
jv_free(lib_origin);
return 1;
}
uint64_t state_idx = 0;
for (; state_idx < lib_state->ct; ++state_idx) {
if (strcmp(lib_state->names[state_idx],jv_string_value(resolved)) == 0)
break;
}
if (state_idx < lib_state->ct) { // Found
jv_free(resolved);
// Bind the library to the program
bk = block_bind_library(lib_state->defs[state_idx], bk, OP_IS_CALL_PSEUDO, as_str);
} else { // Not found. Add it to the table before binding.
block dep_def_block = gen_noop();
nerrors += load_library(jq, resolved, is_data, raw, as_str, &dep_def_block, lib_state);
// resolved has been freed
if (nerrors == 0) {
// Bind the library to the program
bk = block_bind_library(dep_def_block, bk, OP_IS_CALL_PSEUDO, as_str);
}
}
jv_free(as);
}
jv_free(lib_origin);
jv_free(jq_origin);
jv_free(deps);
return nerrors;
}
// Loads the library at lib_path into lib_state, putting the library's defs
// into *out_block
static int load_library(jq_state *jq, jv lib_path, int is_data, int raw, const char *as, block *out_block, struct lib_loading_state *lib_state) {
int nerrors = 0;
struct locfile* src = NULL;
block program;
jv data;
if (is_data && !raw)
data = jv_load_file(jv_string_value(lib_path), 0);
else
data = jv_load_file(jv_string_value(lib_path), 1);
int state_idx;
if (!jv_is_valid(data)) {
if (jv_invalid_has_msg(jv_copy(data)))
data = jv_invalid_get_msg(data);
else
data = jv_string("unknown error");
jq_report_error(jq, jv_string_fmt("jq: error loading data file %s: %s\n", jv_string_value(lib_path), jv_string_value(data)));
nerrors++;
goto out;
} else if (is_data) {
// import "foo" as $bar;
program = gen_const_global(jv_copy(data), as);
} else {
// import "foo" as bar;
src = locfile_init(jq, jv_string_value(lib_path), jv_string_value(data), jv_string_length_bytes(jv_copy(data)));
nerrors += jq_parse_library(src, &program);
if (nerrors == 0) {
char *lib_origin = strdup(jv_string_value(lib_path));
nerrors += process_dependencies(jq, jq_get_jq_origin(jq),
jv_string(dirname(lib_origin)),
&program, lib_state);
free(lib_origin);
}
}
state_idx = lib_state->ct++;
lib_state->names = realloc(lib_state->names, lib_state->ct * sizeof(const char *));
lib_state->defs = realloc(lib_state->defs, lib_state->ct * sizeof(block));
lib_state->names[state_idx] = strdup(jv_string_value(lib_path));
lib_state->defs[state_idx] = program;
*out_block = program;
if (src)
locfile_free(src);
out:
jv_free(lib_path);
jv_free(data);
return nerrors;
}
// FIXME It'd be nice to have an option to search the same search path
// as we do in process_dependencies.
jv load_module_meta(jq_state *jq, jv mod_relpath) {
// We can't know the caller's origin; we could though, if it was passed in
jv lib_path = find_lib(jq, validate_relpath(mod_relpath), jq_get_lib_dirs(jq), ".jq", jq_get_jq_origin(jq), jv_null());
if (!jv_is_valid(lib_path))
return lib_path;
jv meta = jv_null();
jv data = jv_load_file(jv_string_value(lib_path), 1);
if (jv_is_valid(data)) {
block program;
struct locfile* src = locfile_init(jq, jv_string_value(lib_path), jv_string_value(data), jv_string_length_bytes(jv_copy(data)));
int nerrors = jq_parse_library(src, &program);
if (nerrors == 0) {
meta = block_module_meta(program);
if (jv_get_kind(meta) == JV_KIND_NULL)
meta = jv_object();
meta = jv_object_set(meta, jv_string("deps"), block_take_imports(&program));
}
locfile_free(src);
block_free(program);
}
jv_free(lib_path);
jv_free(data);
return meta;
}
int load_program(jq_state *jq, struct locfile* src, block *out_block) {
int nerrors = 0;
block program;
struct lib_loading_state lib_state = {0,0,0};
nerrors = jq_parse(src, &program);
if (nerrors)
return nerrors;
nerrors = process_dependencies(jq, jq_get_jq_origin(jq), jq_get_prog_origin(jq), &program, &lib_state);
block libs = gen_noop();
for (uint64_t i = 0; i < lib_state.ct; ++i) {
free(lib_state.names[i]);
if (nerrors == 0 && !block_is_const(lib_state.defs[i]))
libs = block_join(libs, lib_state.defs[i]);
else
block_free(lib_state.defs[i]);
}
free(lib_state.names);
free(lib_state.defs);
if (nerrors)
block_free(program);
else
*out_block = block_drop_unreferenced(block_join(libs, program));
return nerrors;
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef LINKER_H
#define LINKER_H
int load_program(jq_state *jq, struct locfile* src, block *out_block);
jv load_module_meta(jq_state *jq, jv modname);
#endif
+91
View File
@@ -0,0 +1,91 @@
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "jq.h"
#include "jv_alloc.h"
#include "locfile.h"
struct locfile* locfile_init(jq_state *jq, const char *fname, const char* data, int length) {
struct locfile* l = jv_mem_alloc(sizeof(struct locfile));
l->jq = jq;
l->fname = jv_string(fname);
l->data = jv_mem_alloc(length);
memcpy((char*)l->data,data,length);
l->length = length;
l->nlines = 1;
l->refct = 1;
for (int i=0; i<length; i++) {
if (data[i] == '\n') l->nlines++;
}
l->linemap = jv_mem_alloc(sizeof(int) * (l->nlines + 1));
l->linemap[0] = 0;
int line = 1;
for (int i=0; i<length; i++) {
if (data[i] == '\n') {
l->linemap[line] = i+1; // at start of line, not of \n
line++;
}
}
l->linemap[l->nlines] = length+1; // virtual last \n
return l;
}
struct locfile* locfile_retain(struct locfile* l) {
l->refct++;
return l;
}
void locfile_free(struct locfile* l) {
if (--(l->refct) == 0) {
jv_free(l->fname);
jv_mem_free(l->linemap);
jv_mem_free((char*)l->data);
jv_mem_free(l);
}
}
int locfile_get_line(struct locfile* l, int pos) {
assert(pos < l->length);
int line = 1;
while (l->linemap[line] <= pos) line++; // == if pos at start (before, never ==, because pos never on \n)
assert(line-1 < l->nlines);
return line-1;
}
static int locfile_line_length(struct locfile* l, int line) {
assert(line < l->nlines);
return l->linemap[line+1] - l->linemap[line] -1; // -1 to omit \n
}
void locfile_locate(struct locfile* l, location loc, const char* fmt, ...) {
va_list fmtargs;
va_start(fmtargs, fmt);
int startline;
int offset;
if (loc.start != -1) {
startline = locfile_get_line(l, loc.start);
offset = l->linemap[startline];
}
jv m1 = jv_string_vfmt(fmt, fmtargs);
if (!jv_is_valid(m1)) {
jq_report_error(l->jq, m1);
return;
}
if (loc.start == -1) {
jq_report_error(l->jq, jv_string_fmt("jq: error: %s\n<unknown location>", jv_string_value(m1)));
jv_free(m1);
return;
}
jv m2 = jv_string_fmt("%s at %s, line %d:\n%.*s%*s", jv_string_value(m1),
jv_string_value(l->fname), startline + 1,
locfile_line_length(l, startline), l->data + offset,
loc.start - offset, "");
jv_free(m1);
jq_report_error(l->jq, m2);
return;
}
+14 -64
View File
@@ -1,10 +1,8 @@
#ifndef _LOCFILE_H
#define _LOCFILE_H
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#include "jv_alloc.h"
#ifndef LOCFILE_H
#define LOCFILE_H
#include "jq.h"
typedef struct {
int start, end;
} location;
@@ -12,68 +10,20 @@ typedef struct {
static const location UNKNOWN_LOCATION = {-1, -1};
struct locfile {
jv fname;
const char* data;
int length;
int* linemap;
int nlines;
char *error;
jq_state *jq;
int refct;
};
static void locfile_init(struct locfile* l, const char* data, int length) {
l->data = data;
l->length = length;
l->nlines = 1;
for (int i=0; i<length; i++) {
if (data[i] == '\n') l->nlines++;
}
l->linemap = jv_mem_alloc(sizeof(int) * (l->nlines + 1));
l->linemap[0] = 0;
int line = 1;
for (int i=0; i<length; i++) {
if (data[i] == '\n') {
l->linemap[line] = i;
line++;
}
}
l->linemap[l->nlines] = length;
}
static void locfile_free(struct locfile* l) {
jv_mem_free(l->linemap);
}
static int locfile_get_line(struct locfile* l, int pos) {
assert(pos < l->length);
int line = 0;
while (l->linemap[line+1] < pos) line++;
assert(line < l->nlines);
return line;
}
static int locfile_line_length(struct locfile* l, int line) {
assert(line < l->nlines);
return l->linemap[line+1] - l->linemap[line];
}
static void locfile_locate(struct locfile* l, location loc, const char* fmt, ...) {
va_list fmtargs;
va_start(fmtargs, fmt);
vfprintf(stderr, fmt, fmtargs);
va_end(fmtargs);
fprintf(stderr, "\n");
if (loc.start == -1) {
fprintf(stderr, "<unknown location>\n");
return;
}
int startline = locfile_get_line(l, loc.start);
int offset = l->linemap[startline];
fprintf(stderr, "%.*s\n", locfile_line_length(l, startline), l->data + offset);
fprintf(stderr, "%*s", loc.start - offset, "");
for (int i = loc.start;
i < loc.end && i < offset + locfile_line_length(l, startline);
i++){
fprintf(stderr, "^");
}
fprintf(stderr, "\n");
}
struct locfile* locfile_init(jq_state *, const char *, const char *, int);
struct locfile* locfile_retain(struct locfile *);
int locfile_get_line(struct locfile *, int);
void locfile_free(struct locfile *);
void locfile_locate(struct locfile *, location, const char *, ...);
#endif
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff. Show more