Compare commits

...
62 Commits
Author SHA1 Message Date
itchyny 5c001b18d7 Fix mktime/0 to allow the last two seconds of 1969 (#3671)
The mktime/0 function failed for 1969-12-31T23:59:59Z with "invalid
gmtime representation", because its result -1 is also the failure value
of timegm(), and for 1969-12-31T23:59:58Z with "mktime not supported on
this platform", because of a leftover check for -2.

Tell a failure apart from the valid result -1 by tm_wday, which is set
to -1 before the conversion and overwritten only on success, and remove
the check for -2. Now `-2, -1 | gmtime | mktime` round-trip to -2 and -1,
as do normalized inputs such as [1970,0,0,23,59,59,0,0], which gives -1.
Inputs that the platform rejects, such as years before 1900 on macOS,
still fail with "invalid gmtime representation".
2026-11-02 16:08:10 +09:00
dependabot[bot] 992db9b7e5 build(deps): bump markdown from 3.11 to 3.11.2 in /docs (#3705) 2026-11-01 21:19:41 +09:00
itchyny 2ec4c2cdb1 Switch Linux runners to Ubuntu 26.04 except for MIPS (#3703)
The i386 build ran on ubuntu-22.04, which is retired on April 17, 2027,
and ubuntu-24.04 lacks fmod and exp10 in the static i386 libm.

Build on ubuntu-26.04 for every architecture except MIPS, whose cross
toolchains Ubuntu 26.04 no longer ships, and move the decnum, oniguruma
and valgrind workflows too. Most release binaries are now built with
GCC 15 and glibc 2.43, and they remain statically linked.
2026-11-01 20:34:20 +09:00
itchyny 77953d8c8d Implement drem with remainder on all platforms (#3704)
The static i386 libm of glibc 2.43 does not define drem, so linking jq
with --enable-all-static on Ubuntu 26.04 failed.

Call remainder for drem wherever it is available, as jq already did on
macOS. drem is an obsolete name for remainder, so the results do not
change, and jq no longer depends on the legacy symbol.
2026-11-01 19:57:43 +09:00
itchyny 58c0d615c7 Switch macOS runner from macos-14 to macos-15 (#3702)
The macOS jobs failed during the macos-14 brownouts, and the image is
retired on November 2, 2026.

Run them on macos-15 and build with the macos14 target triple instead
of deriving it from uname -r, so the binaries still require macOS 14.0
as in jq 1.8.x rather than following the runner to 15. Recent clang
ignores the version in a darwinNN triple and uses the SDK default.
2026-11-01 19:55:38 +09:00
skrmc 70c9dc516f Keep characters after a truncated UTF-8 sequence (#3690)
A multibyte UTF-8 sequence cut short by a non-continuation byte took
every remaining byte of the string, so "a\xf0Zb" became "a\ufffd".

Replace only the lead byte and the continuation bytes that follow it,
the same as an invalid sequence that is not cut short, so "a\xf0Zb"
now becomes "a\ufffdZb". This also changes length and explode on such
strings, which now count the characters that used to be dropped.
2026-11-01 00:59:37 +09:00
Michiel van Slobbe 74c46239b9 ci: update outdated dependencies when installing NetBSD packages (#3696)
The NetBSD job failed when installing git on a fresh runner, because the
image ships pcre2-10.48 and the git package needs pcre2>=10.48nb1, and
pkg_add does not update installed dependencies by default.

Pass -uu to pkg_add so it also updates installed dependencies that are
too old. Also drop the PKG_PATH override. netbsd-vm now writes the live
package mirrors for the running release to /etc/pkg_install.conf, so the
override is no longer needed to avoid the image's 9.0 fallback.
2026-11-01 00:52:18 +09:00
Jay Hemnani ac35c7dcbb Default the day of the month to 1 in strptime/1 (#3679)
A format without %d left the day of the month at 0, which mktime and
todate read as the last day of the previous month, and the weekday was
wrong for dates in January and February of 1900 and 2100.

Start parsing from the 1st, so a format without a day now gives the
first of the month, and a time-only format no longer outputs the 8 and
367 placeholders for the weekday and day of the year. This also fixes
the weekday of dates in January and February of 1900 and 2100.
2026-10-25 14:40:52 +09:00
Michiel van Slobbe 864d769d88 Implement ascii_downcase and ascii_upcase in C (#3689)
Both were defined as explode | map(...) | implode, which took 4 seconds
on a 10 MB string, about 90 times as long as parsing it.

Change the case of A-Z or a-z a byte at a time in C, copying multibyte
UTF-8 sequences unchanged, so the output stays the same and the 10 MB
case now takes about 60 ms including parsing. On a non-string input the
error now names the function, "ascii_downcase input must be a string",
instead of "explode input must be a string".
2026-10-25 14:18:21 +09:00
Huang-404-Q bd56a74562 Fix halt_error adding a newline to non-string output (#3694)
The manual says halt_error prints its input with no decoration, not
even a newline, but non-string values such as {"a":"xyz"} were printed
with a trailing newline.

Dump non-string values to JSON and print them the same way as strings,
so {"a":"xyz"} | halt_error(1) now writes exactly {"a":"xyz"} to stderr.
2026-10-24 15:19:14 +09:00
itchyny da4da65c0c docs: rewrite the tutorial (#3631)
The tutorial is where most people meet jq, but it was missing key
filters like select and abbreviated commands in ways that are hard for
beginners to follow.

Grow the page from 7 examples to 24, newly covering -r and -c, chained
paths and slicing, map, sort_by, group_by, select, test, to_entries,
from_entries, with_entries, string interpolation and @tsv. The sample
data is pinned with the API's until parameter and the outputs avoid
GitHub account data, so running the commands gives exactly the output
shown.
2026-10-24 09:41:07 +09:00
Douglas Adolph 53bbd4a3f9 docs: add ldconfig and make clean to the README source build (#3692) 2026-10-24 09:33:07 +09:00
qodelicious 49fbca1242 docs: explain that semicolons separate function arguments (#3685)
The manual's "Defining Functions" section shows only one-argument
functions, so it never says how to pass more than one. This adds a short
paragraph: arguments are separated by `;` in both `def f(a; b):` and
`f(.x; .y)`, and `f(.x, .y)` instead calls a one-argument `f` with the
filter `.x, .y`. It also adds an example for each. `tests/man.test` and
`jq.1.prebuilt` are regenerated.

Fixes #2163
2026-10-22 20:24:55 +02:00
qodelicious e440cccc0a docs: fix arithmetic update-assignment equivalence (#3682)
The manual said `a op= b` is equivalent to `a |= . op b`. It is actually
equivalent to `(b as $b | a |= . op $b)`: the right-hand side gets `.`
as input, not the value being updated, and each value it outputs gives a
separate result.

This updates the description and adds two examples, `.a += .b` and `.a
+= (1,2)`. `tests/man.test` and `jq.1.prebuilt` are regenerated.

Fixes #2119, fixes #2407
2026-10-22 20:23:52 +02:00
mika 94b00aa807 test: check that --run-tests reports failing tests (#3650)
Nothing tested that jq --run-tests exits with status 1 when the
tests fail, so a failure could have been reported as a pass.

Add shell tests with incorrect, missing and extra output that check
both the exit status and the reported message, such as "Insufficient
results", along with a passing control. Under Valgrind, memory errors
exit with status 99 so they are not mistaken for a test failure.
2026-10-21 21:40:49 +09:00
qodelicious 4b45d6c1ba docs: print one example output per line in the man page (#3683) 2026-10-21 21:34:38 +09:00
Léane GRASSER 175b8e3c51 docs: update quoting rules for PowerShell 7.3+ (#3649)
The manual recommended backslash-escaped double quotes inside the jq
program for all PowerShell versions, but since PowerShell 7.3 native
command arguments are passed with standard quoting by default, so the
backslashes reach jq literally.

Describe the quoting rules separately for Unix shells and PowerShell
7.3+, for older PowerShell and Windows PowerShell, and for cmd.exe, and
update the examples to match.
2026-10-20 22:28:24 +09:00
qodelicious ec0e2f3f94 docs: mention conda-forge on the download page (#3684) 2026-10-20 22:25:13 +09:00
fhgffy afa23a53cd Keep the sign of zero when negating a number literal (#3662)
Since jq 1.8.0, negating a number literal computed 0 - x, so -0 and
0 | -. printed 0 while (0+0) | -. printed -0.

Flip the sign bit with decNumberCopyNegate() instead, so -0 prints -0
again as it did in jq 1.7, and -(-0) is still 0.
2026-10-20 22:16:56 +09:00
Michiel van Slobbe 852c4d6096 Improve performance of UTF-8 validation (#3675)
jvp_utf8_next() had a fast path for ASCII, but it is not inlined into
its callers, so every byte of a string cost a function call.

Move the end check and the ASCII case into a static inline function in
jv_unicode.h and keep the rest out of line. This speeds up parsing of
string-heavy input by up to 1.17x and string functions such as length,
explode and @html, with the same output for every input.
2026-10-20 22:03:29 +09:00
Dmitri Vereshchagin 633ae6058a Disable colored output on a dumb terminal (#3552)
Enable colored output by default only when the TERM environment variable
is set to a value other than dumb, as git and grep do, so that users no
longer need to pass -M or set NO_COLOR on terminals that cannot display
escape sequences. Colored output is now disabled not only for TERM=dumb
but also when TERM is unset or empty. The -C option still enables colors
in all these cases. On Windows, colored output is still decided by
ANSICON and the console mode, and TERM is not checked.
2026-10-16 21:50:47 +09:00
Doha Nam 6b53f80311 Fix strftime/1 and strflocaltime/1 to allow an empty result (#3670)
These functions failed with "unknown system failure" whenever strftime()
returned 0 for a non-empty format, but 0 also means the format expands to
an empty string, as %p does in a locale without AM/PM.

Prepend a character to the format and trim it from the result, so that 0
can only mean the result is too long. Now 0 | strflocaltime("%p") gives
"" in fr_FR.UTF-8, and a result that is still too long fails with
"result too long" error instead. The size limit is unchanged.
2026-10-13 16:47:58 +09:00
Michiel van Slobbe 80fc7a169d Skip to the next RS after a parse error in --seq mode (#3654)
In --seq mode, a parse error was reported as "need RS to resync", but
parsing continued in the middle of the broken text, so fragments of it
were reported as more errors or output as values.

Set the parser state to wait for the next RS after resetting the parser,
instead of before, so that the rest of the broken text is skipped as
RFC 7464 recommends.
2026-10-12 13:40:40 +09:00
Hugohong258 611c575a97 docs: add simple and nested update-assignment examples (#3664) 2026-10-12 00:24:32 +09:00
Michiel van Slobbe b904884b94 Improve performance of string output (#3643)
Printing a string wrote each character with a separate call, one
fwrite() per character, or one jv_string_append_buf() for tojson and
tostring, which made output of string-heavy data slow.

Scan ahead for the next byte that needs escaping and write the run of
bytes before it with a single call, without changing the output.
Printing strings is now significantly faster, most of all for long
strings with few characters to escape, and the same applies to tojson
and tostring. With --ascii-output, text that is almost all non-ASCII is
about the same speed, since nearly every byte is escaped anyway.
2026-10-10 21:50:10 +09:00
itchyny a5323a369c Fix assertion failure on too many parameters in a nested function (#3663)
A call passing more than 4095 arguments at the start of a nested
function body aborted jq after reporting the compile errors, with
"Assertion failed: (nemb > 0 && sz > 0), function jv_mem_calloc" and
exit status 134.

Stop compiling a function before its bytecode is allocated when it has
compile errors, since the bytecode is only generated and used when
compilation succeeds. jq now prints the same compile errors followed by
"jq: 2 compile errors" and exits with status 3, as it does for other
compile errors, instead of crashing.
2026-10-10 21:29:56 +09:00
qodelicious 04042494cf Exit with the given status for negative halt_error codes (#3660)
halt_error with a negative exit code did not exit with that code. The
code collided with the internal status values for null or false output
and for no output, so halt_error(-1) exited with 0, or with 1 under
--exit-status.

Keep the low 8 bits of a negative code, as exit(3) does on POSIX
systems, so halt_error(-1) now exits with 255 and halt_error(-2) with
254, the same with or without --exit-status. Under --exit-status this
replaces the previous absolute value, so halt_error(-2) used to exit
with 2 and halt_error(-255) with 255, and they now exit with 254 and 1.
2026-10-10 21:26:02 +09:00
omkar bhor a8e6d5f871 Fix undefined behavior on out-of-range array index in has() and del() (#3560)
Converting a double outside the int range to int is undefined behavior,
and has() and del() did it on array indices like infinite or 1e10, which
UBSan reports as "inf is outside the range of representable values of
type 'int'". Only NaN was guarded against.

Clamp the index to the int range in has(), as getting and setting array
elements already do, and drop out-of-range indices in del() before they
are converted. Such indices can never refer to an element, so has()
returns false and del() leaves the array unchanged, the same as for
indices past the end of the array. Valid indices deleted together with
out-of-range ones, as in del(.[0, 1e10]), are still deleted.
2026-10-09 09:22:59 +09:00
neil dbbae0dee3 Add FreeBSD and NetBSD CI (#3600)
Add a BSD workflow with FreeBSD and NetBSD jobs that run the same build
and tests as the linux job, each inside a VM booted under QEMU on an
ubuntu-latest runner. The tests/shtest $NO_COLOR pty checks are now
skipped on NetBSD, as they already are on SunOS.
2026-10-08 23:38:20 +09:00
itchyny e001deb4cf Strip UTF-8 BOM at the start of each input file (#3657)
The UTF-8 BOM was stripped only at the start of the parser stream, but jq
feeds all input files into a single parser, so a BOM at the start of the
second and later files reached the parser as content and failed with a
confusing "Invalid numeric literal" error. Strip it in the file readers
instead, at the start of each input file including stdin, and in
jv_load_file.

This also strips the BOM for raw input, so -R and --rawfile no longer
yield a leading U+FEFF, and a BOM at the start of a -f program file or an
imported module is now accepted rather than reported as a syntax error.
In exchange, "\uFEFF1" | fromjson is now a parse error, since a U+FEFF
inside a string is content rather than an encoding marker, and the
dedicated "Malformed BOM" error is gone.
2026-10-08 23:01:36 +09:00
itchyny 17b87d25c7 Drop the date from the committed man page (#3659)
The date in the .TH line of jq.1.prebuilt changed whenever the manual was
regenerated in a new month, causing merge conflicts between pull requests
that touch the manual, and it did not reflect the release date anyway.
Generate the committed man page without a date.

Stamp the date into jq.1 at build time instead, taking it from the current
commit, or from SOURCE_DATE_EPOCH where that is set, so that release
tarballs and distribution builds still carry one and the behaviour added
in #3514 is kept. Write it in UTC and in ISO 8601 rather than the previous
"%B %Y", for which mandoc reports "cannot parse date, using it verbatim".
2026-10-08 22:16:42 +09:00
itchyny fd25c3e720 Parse the full ISO 8601 grammar in fromdateiso8601 (#3617)
`fromdateiso8601` was `strptime("%Y-%m-%dT%H:%M:%SZ") | mktime`, which
accepts only one of the many representations ISO 8601 permits. strptime
cannot be extended to cover the rest portably, since it has no specifier
for fractional seconds and glibc discards `%G` and `%V`.

Replace it with a parser in src/iso8601.c that handles basic and extended
representations, ordinal and week dates, fractional seconds, offsets and
date-only input. It uses integer arithmetic instead of `time_t`, so the
results no longer depend on the platform.

This is stricter than before. Impossible dates like `2015-02-30`, which
`mktime` used to normalize into March, and unpadded components like
`2015-3-5T6:00:00Z` are now errors. So is any trailing input, including
whitespace. Leading whitespace is rejected too; before, glibc skipped it
and macOS did not. A leap second now maps to the second before it rather
than the next minute. The error message has changed, and the result can
now be non-integer.
2026-10-08 08:24:10 +09:00
A4-Tacks a19efdd45d Parse ?// as ? and // outside destructuring patterns (#3593)
The lexer returned a single ALTERNATION token for `?//`, so any `?`
followed by `//` was consumed by it, and `.name?//"unknown"` failed
to parse even though they read as the optional operator followed by
the alternative operator.

Drop the lexer rule and spell the destructuring alternative operator
as `'?' "//"` instead. So `x ?// y` now parses as `x? // y`, while
`. as [$a] ?// [$b] | ...` keeps its meaning. Note that `?` and `//`
may now be separated by whitespaces inside a pattern.
2026-10-06 16:48:28 +09:00
itchyny f13c1effbf Run man page workflow on push only for master (#3648)
The push trigger had no branch filter, so pull requests from branches
in this repository (e.g. Dependabot) ran the workflow twice, once for
push and once for pull_request.
2026-10-01 15:39:23 +09:00
dependabot[bot] 57a03d610c build(deps): bump lxml from 6.1.2 to 6.1.3 in /docs (#3647) 2026-10-01 15:25:06 +09:00
dependabot[bot] 2bea9d6df9 build(deps): bump markdown from 3.10.3 to 3.11 in /docs (#3646) 2026-10-01 15:24:38 +09:00
Artem Lytkin 9a75bb0d43 Improve performance of join/1 on large arrays (#3639)
join/1 folded each element as `(acc + $x) + elem`, with the element
branch ending in `.//""`. Both leave a second live reference to the
accumulator: the nested + feeds the same `.` to both operands, and the
`//` leaves a forkpoint below it on the stack. `jvp_string_append`
therefore cannot grow the accumulator in place, and copies the whole
string once per element.

Pipe `acc + $x` into `. + elem` and drop the `//`, since adding null to
a string is already a no-op. join/1 is now linear: joining 8000
strings of 1000 chars goes from 6.5s to 0.06s, with output and error
messages unchanged.
2026-09-27 13:52:41 +09:00
Brandon 32580f5d83 Prefer getentropy() over arc4random() to seed the string hash (#3629)
glibc's arc4random() aborts with "Fatal glibc error: cannot get entropy
for arc4random" when the kernel lacks getrandom(2), so jq died on
startup on older kernels once 0c7d133 began seeding the hash on every
run.  getentropy() merely returns -1/ENOSYS there, so prefer it, and
route its failure through the existing `/dev/urandom` path - which works
on precisely those kernels -- instead of a guessable `getpid() ^ time()`.
2026-09-25 16:39:06 +09:00
itchyny df24981307 Fix reduce to preserve its input across init backtracking (#3633)
`reduce f as $x (init; update)` evaluated `f` against a stack slot
that forkpoints created while evaluating `init` restore. Both the
`DUPN` opening the reduction loop and the `LOADVN` retrieving the
result pop that slot destructively, nulling it out, so an `init`
that backtracks (e.g. `0, 0`) made `f` see `null` and fail with
"Cannot iterate over null".

Duplicate the input before the `FORK` instead of inside the loop,
and drop the leftover copy with `POP` once the loop is exhausted.
The slot left live at the `FORK` is then a block pushed after
`init` completed, which no earlier forkpoint can reach, so nulling
it is harmless. This is the same approach `gen_foreach` has used
since c70ae1a.

`DUPN` had no other user, so remove the opcode.
2026-09-19 15:21:29 +09:00
A4-Tacks 4beed4e01a perf: avoid the intermediate array in from_entries (#3626)
Define `from_entries` as `add(.[] | f) // {}` instead of
`map(f) | add // {}`. Since `add(f)` is `reduce f as $x (null; . + $x)`,
both fold the same values in the same order from the same seed, so the
only difference is that the array of single-key objects built by `map`
is never materialized.

Measured with both the generator and the result suppressed, so that only
the `from_entries` work differs: 6-15% less user time across input shapes,
which is 10-24% of what `from_entries` itself costs. For inputs above
roughly a thousand entries, peak RSS drops by 37%, around 80% of the
memory `from_entries` adds on top of its input; a 1,000,000 entry array
goes from 1064 MiB to 672 MiB.
2026-09-18 22:38:42 +09:00
itchyny 12cdd950e9 Register imported libraries in dependency order (#3620)
block_mark_referenced walks the joined block backwards and skips the
body of any definition not yet marked referenced, so a library must
precede its importers.  f58787c41 registered a library before walking
its dependencies, to have somewhere to keep the `loading` flag, which
reversed that order and made block_drop_unreferenced free definitions
that are still referenced through bound_by.

Keep the libraries being loaded on a stack threaded through the
load_library frames instead, so registration can move back after the
dependency walk.
2026-09-18 22:27:54 +09:00
itchyny e371bfaa92 Implement range/3 in C for consistent error handling (#3267) 2026-09-18 22:20:58 +09:00
Bumsu Hyeon dd409de28d Use WriteConsoleW() in priv_fwrite() too (#3607)
jq dumps JSON to the Windows console as UTF-16 with WriteConsoleW(),
but priv_fwrite() still writes the raw UTF-8 bytes with WriteFile(),
which the console decodes with its output code page.  So `jq .k` prints
non-ASCII correctly while `jq -r .k` prints mojibake, and the same goes
for -j, --raw-output0, --seq, halt_error and the `stderr` builtin.

The tty flag is computed once, from stdout, and passed to writes aimed
at stderr too, so ask the handle instead: with stdout on a console and
stderr redirected, WriteConsoleW() failed on the file handle and the
output was dropped.

One byte-level change: with stdout on a console and stderr redirected,
halt_error and the `stderr` builtin now go through the CRT, so bare LF
becomes CRLF and an existing CRLF becomes CR CRLF.  Use -b for
byte-exact output on that stream.
2026-09-18 20:12:34 +09:00
JUSHUANGHUI LI 7422e8c914 docs: clarify ownership of jv arguments and results (#3627)
The ownership comment in `jv.h` currently says every `jv_*` function
except `jv_copy` consumes its input. Several accessors and
object-iteration functions borrow their arguments instead, which makes
that guidance misleading for callers and language bindings.

Document the borrowing exceptions beside their declarations, including
numeric helpers and `jv_show`. Clarify that returned `jv` values are
owned, while the pointers returned by `jv_string_value` and
`jv_number_get_literal` belong to their input values. This changes
comments only.
2026-09-18 18:52:18 +09:00
itchyny 6aeafff056 Fix gmtime and localtime on negative timestamps with fractional seconds (#3634)
The whole seconds were truncated toward zero while the fractional part
was measured from the floor, so any negative non-integral timestamp was
rendered one second late; gmtime was not monotonic across the epoch.
2026-09-18 18:45:36 +09:00
itchyny 57f5976edf website: fold older versions on the download page (#3635)
Only the latest release stays visible in the binary, checksum and
signature, and source tarball lists; older versions move into
collapsible `<details>` sections. Condense the repetitive per-version
checksum and signature sentences into a single list.
2026-09-18 17:07:54 +09:00
Hugohong258andHugohong258 1b4109b0d0 docs: clarify that prebuilt downloads are standalone executables (#3632)
State explicitly in the README and download page that the
platform-specific prebuilt files are standalone executables, not
archives. Include the rename and executable-permission step for macOS
and Linux in the README.

Addresses #2956. Source archives are not described as executables.

Validation: the official `docs/build_website.py` completed and the
generated download page contains the new guidance. Used a Python venv
with the site's required rendering packages; restored the Windows
checkout's manual symlink in a temporary build copy only. jq itself was
not built or tested for this documentation-only change.

Co-authored-by: Hugohong258 <282228220+Hugohong258@users.noreply.github.com>
2026-09-15 11:13:25 +02:00
dependabot[bot] 9d241e2772 build(deps): bump markdown from 3.10.2 to 3.10.3 in /docs (#3622) 2026-09-01 15:30:46 +09:00
dependabot[bot] 8bce8b6543 build(deps): bump lxml from 6.1.1 to 6.1.2 in /docs (#3621) 2026-09-01 15:24:58 +09:00
Anna Rift 41b8edfe54 Fix a handful of typos (#3605) 2026-08-24 00:06:16 +09:00
Thomas Klausner 17b411837d Fix strftime-related functions on NetBSD. (#3579) 2026-08-24 00:03:21 +09:00
august fbee8f48ba Reject raw NUL bytes in the parser instead of silently truncating tokens (#3606) 2026-08-24 00:01:54 +09:00
A4-Tacks 8cf81cb80c docs: in example use [3,4] instead of [0,1] (#3599) 2026-08-23 23:28:10 +09:00
Anna Rift 4bb50d772b Fix typo 'you may wish [to] use' (#3604)
Fix all instances of the phrase "you may wish use `fabs`" -> "you may
wish _to_ use `fabs`" (emphasis mine) in the manual.
2026-08-12 21:02:39 +02:00
dependabot[bot] 603db3f577 build(deps): bump actions/setup-python from 6 to 7 in the official-actions group (#3595) 2026-07-26 10:10:34 +09:00
ded-furby 2d410d6d86 docs: clarify join behavior on objects (#3555) 2026-07-19 21:27:45 +09:00
WinkleMad f1f39b42e3 Advance past the whole codepoint after a zero-width regex match (#3586) 2026-07-19 21:13:51 +09:00
pavel kuliaka dbcaa9d491 shtest: skip locale test if date lacks locale support (#3583) 2026-07-18 17:03:18 +09:00
Thomas Klausner 579e6f76cf Cast char to unsigned char before passing to isspace (#3574) 2026-07-02 14:45:10 +09:00
itchyny 42d4035d4f Add a download link for Windows arm64 2026-06-22 19:31:20 +09:00
itchyny 3c81b62958 Update jq documentation for jq 1.8.2 release 2026-06-20 23:17:39 +09:00
github-actions[bot]andgithub-actions[bot] f0dabad36a Update signatures of 1.8.2 (#3566)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-20 23:12:40 +09:00
89 changed files with 4480 additions and 2128 deletions

No files matched your search

+84
View File
@@ -0,0 +1,84 @@
name: BSD
on:
push:
branches:
- master
tags:
- "jq-*"
pull_request:
jobs:
freebsd:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Clone repository
uses: actions/checkout@v7
with:
submodules: true
- name: Build and test
uses: vmactions/freebsd-vm@v1
with:
usesh: true
cache-after-prepare: true
prepare: |
pkg install -y autoconf automake libtool gmake git
run: |
set -e
# The VM runs as root over a checkout owned by another uid, so git
# rejects the repository and scripts/version -- which AC_INIT calls
# through m4_esyscmd_s -- exits 128, leaving JQ_VERSION undefined.
git config --global --add safe.directory "$PWD"
git config --global --add safe.directory "$PWD/vendor/oniguruma"
autoreconf -i
./configure --disable-docs --with-oniguruma=builtin --enable-static
gmake -j"$(sysctl -n hw.ncpu)"
gmake check VERBOSE=yes
- name: Upload Test Logs
if: ${{ failure() }}
uses: actions/upload-artifact@v7
with:
name: test-logs-freebsd
retention-days: 7
path: |
test-suite.log
tests/*.log
netbsd:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Clone repository
uses: actions/checkout@v7
with:
submodules: true
- name: Build and test
uses: vmactions/netbsd-vm@v1
with:
usesh: true
cache-after-prepare: true
prepare: |
# -uu also updates installed dependencies that are too old, such
# as the image's pcre2 when git needs a newer build.
pkg_add -uu autoconf automake libtool gmake git
run: |
set -e
# The VM runs as root over a checkout owned by another uid, so git
# rejects the repository and scripts/version -- which AC_INIT calls
# through m4_esyscmd_s -- exits 128, leaving JQ_VERSION undefined.
git config --global --add safe.directory "$PWD"
git config --global --add safe.directory "$PWD/vendor/oniguruma"
autoreconf -i
./configure --disable-docs --with-oniguruma=builtin --enable-static
gmake -j"$(sysctl -n hw.ncpu)"
gmake check VERBOSE=yes
- name: Upload Test Logs
if: ${{ failure() }}
uses: actions/upload-artifact@v7
with:
name: test-logs-netbsd
retention-days: 7
path: |
test-suite.log
tests/*.log
+11 -7
View File
@@ -37,6 +37,8 @@ jobs:
CC: aarch64-linux-gnu
- arch: armel
CC: arm-linux-gnueabi
# Ubuntu 26.04 has no crossbuild-essential-armel
packages: gcc-arm-linux-gnueabi libc6-dev-armel-cross
- arch: armhf
CC: arm-linux-gnueabihf
- arch: i386
@@ -65,7 +67,8 @@ jobs:
CC: riscv64-linux-gnu
- arch: s390x
CC: s390x-linux-gnu
runs-on: ${{ matrix.arch == 'i386' && 'ubuntu-22.04' || 'ubuntu-24.04' }}
# Ubuntu 26.04 no longer ships the MIPS cross toolchains.
runs-on: ${{ startsWith(matrix.arch, 'mips') && 'ubuntu-24.04' || 'ubuntu-26.04' }}
env:
AR: ${{ matrix.CC }}-ar
CHOST: ${{ matrix.CC }}
@@ -81,7 +84,8 @@ jobs:
- name: Install packages
run: |
sudo apt-get update
sudo apt-get install -y automake autoconf libtool crossbuild-essential-${{ matrix.arch }}
sudo apt-get install -y automake autoconf libtool \
${{ matrix.packages || format('crossbuild-essential-{0}', matrix.arch) }}
- name: Build
run: |
autoreconf -i
@@ -127,10 +131,10 @@ jobs:
- arm64
include:
- arch: amd64
target: x86_64-apple-darwin
target: x86_64-apple-macos14
- arch: arm64
target: arm64-apple-darwin
runs-on: macos-14
target: arm64-apple-macos14
runs-on: macos-15
env:
LDFLAGS: -dead_strip
SUFFIX: macos-${{ matrix.arch }}
@@ -146,12 +150,12 @@ jobs:
brew install autoconf automake libtool
- name: Set CC
run: |
echo "CC=clang -target ${{ matrix.target }}$(uname -r)" >> "$GITHUB_ENV"
echo "CC=clang -target ${{ matrix.target }}" >> "$GITHUB_ENV"
- name: Build
run: |
autoreconf -i
./configure \
--host="${{ matrix.target }}$(uname -r)" \
--host="${{ matrix.target }}" \
--disable-docs \
--with-oniguruma=builtin \
--disable-shared \
+1 -1
View File
@@ -7,7 +7,7 @@ on:
jobs:
disabled:
runs-on: ubuntu-24.04
runs-on: ubuntu-26.04
steps:
- name: Clone repository
uses: actions/checkout@v7
+5 -7
View File
@@ -1,6 +1,8 @@
name: Building man page, man.test, manonig.test
on:
push:
branches:
- master
paths:
- '.github/workflows/manpage.yml'
- 'docs/**'
@@ -22,7 +24,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup Python
uses: actions/setup-python@v6
uses: actions/setup-python@v7
with:
python-version: '3.11'
cache: pipenv
@@ -40,12 +42,8 @@ jobs:
./configure --enable-docs
- name: Build man page, man.test, manonig.test
run: |
mv jq.1.prebuilt jq.1.old
rm -f tests/man.test manonig.test
rm -f jq.1.prebuilt tests/man.test tests/manonig.test
make jq.1.prebuilt tests/man.test tests/manonig.test
- name: Make sure that jq.1.prebuilt, man.test, manonig.test are up to date
run: |
git diff --exit-code tests/man.test tests/manonig.test
# skip build date in jq.1.prebuilt
test -s jq.1.prebuilt
diff -- <(tail -n +3 jq.1.old) <(tail -n +3 jq.1.prebuilt)
git diff --exit-code jq.1.prebuilt tests/man.test tests/manonig.test
+2 -2
View File
@@ -9,7 +9,7 @@ on:
# we test other options for --with-oniguruma here.
jobs:
installed:
runs-on: ubuntu-24.04
runs-on: ubuntu-26.04
steps:
- name: Clone repository
uses: actions/checkout@v7
@@ -42,7 +42,7 @@ jobs:
tests/*.log
disabled:
runs-on: ubuntu-24.04
runs-on: ubuntu-26.04
steps:
- name: Clone repository
uses: actions/checkout@v7
+1 -1
View File
@@ -7,7 +7,7 @@ on:
jobs:
linux:
runs-on: ubuntu-24.04
runs-on: ubuntu-26.04
steps:
- name: Clone repository
uses: actions/checkout@v7
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup Python
uses: actions/setup-python@v6
uses: actions/setup-python@v7
with:
python-version: '3.11'
cache: pipenv
+16 -3
View File
@@ -5,7 +5,8 @@ LIBJQ_INCS = src/builtin.h src/bytecode.h src/compile.h \
src/exec_stack.h src/jq_parser.h src/jv_alloc.h src/jv_dtoa.h \
src/jv_unicode.h src/jv_utf8_tables.h src/lexer.l src/libm.h \
src/linker.h src/locfile.h src/opcode_list.h src/parser.y \
src/util.h src/jv_dtoa_tsd.h src/jv_thread.h src/jv_private.h \
src/util.h src/iso8601.h \
src/jv_dtoa_tsd.h src/jv_thread.h src/jv_private.h \
vendor/decNumber/decContext.h vendor/decNumber/decNumber.h \
vendor/decNumber/decNumberLocal.h
@@ -13,7 +14,7 @@ LIBJQ_SRC = src/builtin.c src/bytecode.c src/compile.c src/execute.c \
src/jq_test.c src/jv.c src/jv_alloc.c src/jv_aux.c \
src/jv_dtoa.c src/jv_file.c src/jv_parse.c src/jv_print.c \
src/jv_unicode.c src/linker.c src/locfile.c src/util.c \
src/jv_dtoa_tsd.c \
src/iso8601.c src/jv_dtoa_tsd.c \
vendor/decNumber/decContext.c vendor/decNumber/decNumber.c \
${LIBJQ_INCS}
@@ -189,8 +190,18 @@ else
@echo As a result, the manpage is out of date.
endif
# The committed manpage has no date to avoid merge conflicts. Stamp the date
# of the last commit when building in a git repository, including on make
# dist, so that release tarballs ship a dated jq.1. Respect SOURCE_DATE_EPOCH
# so that distribution builds can pin the date.
jq.1: jq.1.prebuilt
$(AM_V_GEN) cp $(srcdir)/jq.1.prebuilt $@
$(AM_V_GEN) date=`if test -n "$$SOURCE_DATE_EPOCH"; then \
date -u -d "@$$SOURCE_DATE_EPOCH" +%F 2>/dev/null || \
date -u -r "$$SOURCE_DATE_EPOCH" +%F 2>/dev/null; \
elif test -e $(srcdir)/.git; then \
cd $(srcdir) && git log -1 --format=%cd --date=short 2>/dev/null; \
fi`; \
sed 's/^\.TH "JQ" "1" ""/.TH "JQ" "1" "'"$$date"'"/' $(srcdir)/jq.1.prebuilt > $@
CLEANFILES += jq.1
@@ -224,6 +235,8 @@ EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \
libjq.pc \
tests/modules/a.jq tests/modules/b/b.jq tests/modules/c/c.jq \
tests/modules/c/d.jq tests/modules/data.json \
tests/modules/deep1.jq tests/modules/deep2a.jq \
tests/modules/deep2b.jq tests/modules/deep3.jq \
tests/modules/home1/.jq tests/modules/home2/.jq/g.jq \
tests/modules/lib/jq/e/e.jq tests/modules/lib/jq/f.jq \
tests/modules/shadow1.jq tests/modules/shadow2.jq \
+4
View File
@@ -12,6 +12,8 @@
### Prebuilt Binaries
Download the latest releases from the [GitHub release page](https://github.com/jqlang/jq/releases).
The platform-specific assets are standalone executables, not archives. On macOS and Linux,
rename the downloaded file to `jq` and make it executable with `chmod +x jq`.
### Docker Image
@@ -50,11 +52,13 @@ make clean # if upgrading from a version previously built fr
make -j8
make check
sudo make install
sudo ldconfig # on Linux, if jq cannot find libjq.so
```
Build a statically linked version:
```console
make clean
make LDFLAGS=-all-static
```
+181 -139
View File
@@ -66,153 +66,195 @@
},
"lxml": {
"hashes": [
"sha256:05a82eb6e1530a64f26225b55cbd178113bd0b5af1c2b625f25e5296742c26d2",
"sha256:07a4a68e286ee7a1ed7dfb8af83e615757c0ccfe9f18c6b4ea6771388d9ba8c9",
"sha256:09dd5b7075dc2f7709654a46543ba1ea3c2e217b2ed8fbd413a8a945a0f40f60",
"sha256:0b7e8a14c8634bf6f7a568634cb395305a6d964aeb5b7ee32248094bed3a7e2c",
"sha256:104c09bda8d2a562824c0e319d0768ce26a779b7601e0931d33b09b53c392ef7",
"sha256:126c93f7f56f0eda92f6d8c619edc463a4f23d9252f1c9d0405a76f25fa9f11a",
"sha256:162af1091cd785f2f27e62d3547ae9bc58ec5c86dd314d67021fd02463708d83",
"sha256:17e0e18d4ad8adbd0399291bc44845b69d9dd68439a3cdebdf35ff902ec05072",
"sha256:18b73c339ae29b90fd2d06e58ebd555a751bde9cd6bbd36cc0281b9a2c94e9d8",
"sha256:19607c6bbff2a44cf3fe8250abccd20942d3462473e0a721d01d379ed017e462",
"sha256:19b7ab10b210b0b3ad7985d9ac4eb66ab09a90b20fe6e2f7ba55d01a234345d0",
"sha256:1d4962d4c66bf830a7e59ed6cfc17d148149898a3aefa8ec6e59763e6e3ed085",
"sha256:1db753c9115ec7100d073b744d17e25e88a8f90f5c39b2f5dd878149af59671f",
"sha256:1dde6131244bba38a17c745836ba190bc753fd73c9291666287fd0a3fa3dcf30",
"sha256:25c6997a9a534e016695a0ba06b2f07945de682731ff01065b6d5a4474179da1",
"sha256:26e6eda8d38c1fcab1090dd196ee87cbd13788e531937610e2589085de074e77",
"sha256:27acc820660aaffa4f7c087f29120e12980f7779d56d8492d263170111284740",
"sha256:2a0217714657e023ef4293500f65aa20fce6164c8fd6b08fa5bd4a859fb14b9b",
"sha256:2c8daa471358dc2d6fcf02165e80ec68f77871a286df95bc5cc3816153b0fd2c",
"sha256:30a89d3ac8faec007453fb541f3f46807eeec88edd5826f6e3fe001752a2c621",
"sha256:31033dc34636ea6b7d5cc11b1ddbda78a14de858ba9d3e1ed4b69a3085bc521e",
"sha256:32ab449a5486f6c758e849bb86710d0e45edc24a04e250c01555f8f5653958f8",
"sha256:3483644525531e1d5762b0c44a8e18b6efba321b6dcf8a8952de10b037618bca",
"sha256:34c2d737beabfe35baada43941ed519251e9a12e779031496bcd5d539fcfd730",
"sha256:3779def59032b81e44a5f70096ef6bf2082f8d901937dca354474ba09782e245",
"sha256:37a58976370f36d9329d118ad0b953c5aeb9119ac9c6a4e258942a225d0573a1",
"sha256:3893c14c4b6ac5b2d54ba8cf03e99fe5104e592de491f19bd6b82756c09f8004",
"sha256:3a12689be69a28ddaa0ab99a5a1137da2afd5f8f16df7b5680b66f616d3eda1d",
"sha256:3ab541146f1f6968c462d6c2ac495148e8cdba2f8347700b2141b6ec5a75bf52",
"sha256:3abf332af33a74288675d936fe861fd4344da0dd6622193fbc4f2bfbb35536b5",
"sha256:3fd9728a2735fda14f4e8235830c86b539e9661e849665bf926d3f867943b4bf",
"sha256:424aa57aca0897eb922aef34395bd1289b3b6f04e6bae20ea123c0c7e333cffc",
"sha256:441dd227fa0690eb9fc81edabc63cdcefc212bba99b906dcf6e32cc1a9d3e533",
"sha256:469e3618338bd7ab5beb412d2439825479fcf0dab99e394ca563dbc4eaf6c834",
"sha256:47402e62c52ff5988c1e8c6c63177f5708bccf48e366dea4e3dcf1e645e04947",
"sha256:4f0dd2f01f9f8a89f565d000e03abcf0a13d692a346c8d22f628d49af098777a",
"sha256:53b7d2b7a10b1c35c0a5e21e9224accf60c1bbfba523990732e521b2b73adef2",
"sha256:53c909b62a0532183542fed00c5a7218258c56292d409bc789886fe1cb04c438",
"sha256:54a7f95e4de5fb94e2f9f4b9055c6ba33bf3d628fd77a1d647c5923caa2cdcdc",
"sha256:556e94a63c9b04716f8e4de2abb65775061f846e89331b6c5be79183a24f98ea",
"sha256:55b03549819867ea141c0202242c4816c82e52ec36e7e648db9d8da5a3dc3ed6",
"sha256:581d4c8ae690a6609e64862dd6b7c2489635c2d13907fc2b20f2bc200ff1d21e",
"sha256:58bb955caba94e467d2a96da17660d2d704e0675894cba21ab8a775b8621fd1c",
"sha256:5b7328b46d49fc9477d91ae8f6d55340347d827b7734ba3ea33faae0efef1383",
"sha256:5ba186ad207446c65d3bb3d3e0412b032b1d9f595e59861e2354798c5703d955",
"sha256:5bec7d03d78d853597d6107854c2310ce3f761fd218fe9fe91d5101fcf6c2efe",
"sha256:5c6bf403fbb3b3e348a561a5f4f0b9961835657981c802a1df03653eef8a9074",
"sha256:5f6994074ebae6ffb04447268e37dc16edc304f9859cf91acb86e0af6c1b395c",
"sha256:62aeb7e85b5d60320b9d77eef2e773994e2c0ce10121b277e0a19804e1654a5a",
"sha256:63876be28efefa04a1df615b46770e82042cce445cfdce55160522f57b231ccb",
"sha256:639f6c857d91d9be29bd7502348d6736dab168b54b5158cd899abf11684dc186",
"sha256:640f97d43d867bcb9c75b3af013b64850756b746cb6bce8ace83b70da3abba9d",
"sha256:649dda677cf3bd6ac9ae14007ba0c824ded8ce5808b53fc7431d9140399118c1",
"sha256:6540377fbd53fe1b629172288c464fb18db11ce1fa7dc15891da10aa9dcc3e7f",
"sha256:6689e828a94eee4f139408c337bb198e014724bb8a8c26d3cfac49d119ed69a6",
"sha256:68a9198d0fc122d14bb76837de9aa80cf84caed990b5b237f532ed87d3706736",
"sha256:6b1761fbf9ec984e2e9d9c589ef5f5fd684b7c19f92aadd567a26c5224958db6",
"sha256:70cdfd80589d59e43e18005dd7244e8895e93db8ab6a620b7e23df5445a4e3d2",
"sha256:70ef8a7e102a1508f8121aae5b0867abd663f72c14f0a9c937e6554cb4587b7b",
"sha256:73bc2086f141224ebddb7fc5c6a36ca58b31b94b561e1dfe8e073e3270fad1e7",
"sha256:74a9717fd0d82effef5c2854f0d917231d5324b5a3eb7275c43ac9fa32f97a14",
"sha256:752d3bbfe874715ccd0aec7f88d7fc623c0f1fd7aa7b3238a084e017bad2a009",
"sha256:762ff394d5bd56da0cf034a23dcce4e13923f15321a2adfa2ac00201dc6d3fca",
"sha256:76447f65250ed2501ead1a1552f5ce8edff159a86f308348e6a9c4acb5e1f1b4",
"sha256:766b010012d59470072c1816b5b6c69f1d243e5db36ea5968e94accf430a4635",
"sha256:787b2496d0dbe8cd180984e8d29e3a6f76e7ea34db781cb3bd55e4ba1ef8b4ee",
"sha256:793033d6c5cdf33a573f910d9bea14ef8f5771820411d118da8e1182edb53d5e",
"sha256:7d47866cb32fb503450b6edc9df355d10dc49836af2e89901bd6ac6b0896d9d9",
"sha256:7f7a92e8583f06b1fd49d01158143b8461cfcd135dcb10ec807270a3051bd603",
"sha256:80c2dfadb855da477cf73373ad29a333535dedb9b12bad02c9814c8e2b43bf08",
"sha256:83b6b30eb131da7a75b601f28c5d6971e6ed3e887919bf6b6a1ad3c2df289080",
"sha256:86281fbdd6a8162756f8d603f37e3435bfa38043adb79c6dc6a2dfee065e7525",
"sha256:86c89b9d55ebf820ad7c90bc533410f0d098054f293351f10603c0c46ff598f5",
"sha256:876e1ff5930ed8bf295ec5ef9a8155e9b6b1876bbf1deed8b3a8069311875a8f",
"sha256:88136950da4d13c318bde414ce10219931937851327f44328f2df4d2c4614067",
"sha256:88d8cb75b9d82858497a5393e3c63cfbf03035225e4b35a49ed7ccb151e4dc0e",
"sha256:8be8ad51249698103d24b0571df35a10990fbe93dd043b6c024172189485f5e3",
"sha256:8d43ca737b20e106e4aebc42b2f3ae19f00ba63d7eb731698ee083d72d15646f",
"sha256:8dadbe5b217ff35b6a8d16610dd710219b59b76d13f0e3f0d9f36786206e4485",
"sha256:9395002973c827b3ed67db77e6ec09f092919a587022174554096a269378fb13",
"sha256:96f2ec43df44b1f76249ee0a615334f9b5b060e1c8bd90e706dad2d14d02f383",
"sha256:98fc784c2c1440667aeedf8465bdfe10208acf0ead656a2c68627299f546b315",
"sha256:9e36f163528fc50cbef305f02a5fd66d404edf7049cdaff211dbc2cba5a7013e",
"sha256:9eb9b5a968f6e0f6d640092a567e14529ff8cea2e29d00da6f78a79fa49f013c",
"sha256:9f76acfb5f68ba982635a53fd985a8044be98a35b43232c2a1ee235ffab3e1dd",
"sha256:a088f287f7d8275a33c07f2cac6c50b9319309a0200a39e7e75d80c707723099",
"sha256:a10bd2fd62e8ce916ececb342f348f190724a098c1faa056fdfb2a22ad5e8660",
"sha256:a4bbea04c97f6d78a48e3fbc1cb9116d2780b1b39e03a23f6eb9b603fd61f510",
"sha256:aa366a1e55b8ebfe8ca8ddc3cfe75c8ebade181aeb0f661d0cb05986b647f72a",
"sha256:aa49e06d94aba782c6a02eecb7e507969e7e7a41b267f1b359bb35585f295d5b",
"sha256:aad9aa39483ed8ec44d6d2e59e5b98a0d80676ef0d92f44bfc374836111f62f5",
"sha256:aae97dfdb60715c164419ac2532a76d013c3918a665eb6cb7288098b5f349aaf",
"sha256:abbefa31eee84842140f67acef1c828e28bba8bbf0c3bc6e5492a9af88152c28",
"sha256:ac931cdc9442c1763b8a8f6cd62c0c938737eafc5be75eff88df55fc73bc0d00",
"sha256:acd7d70b64c0aae0c7922cca83d288a16f5f6da523637697872253415269baef",
"sha256:add8cf6ddf9a65116119a28ece0f7886e30af27ba724a7594305f1d1b58a92a1",
"sha256:aee395f5d0927f947758b4ec119fd5fc8ec71f07a1c5c52077b30b04c0fa6955",
"sha256:b1b963fd8f5caa68e99dfae060d54de1fe9cba899b8718b44a00cdca53c3e590",
"sha256:b2d444f2e66624d68e9c6b211e28a76e22fff5fcabcfff4deac18b529b7d4137",
"sha256:b8d812c6011c08b8111a15e54dd990b8923692d80adf35488bee34026c35accf",
"sha256:ba96ae44888e0185281e937633a743ea90d5a196c6000f82565ebb0580012d40",
"sha256:bdebcc8a75d38c7598dfb2c9ed852d7a9eb4a10d6e2d0764b919b802bf32ac88",
"sha256:c07da4cebf6889f03ebac8d238f62318e29f495de0aa18a51ea14e61ae907e2e",
"sha256:c08e5c694306507275f2290073350c4f32e383db15213b2c69e7ff39c1193840",
"sha256:c4f469aebd783bb741c2ecb2a681008fd26bfe5c16a9a72ed5467f834e810df2",
"sha256:c5d7152ec39ca7c402d8fb9bad86140a15b9503bd0c54484e3f1bbe3dd37ceca",
"sha256:c674693f055fa2495de12292cb45e9944199d8eaef5a2dec45175c7c61cb73e3",
"sha256:c6ed5141a5c7507cf3ee76bd363b0d6f801e3321adc35b5d825a23115faa5465",
"sha256:c921ba5c51e4e9f63b8b00267d06566e1f63407408a0496da2d1d0bfc819c7fc",
"sha256:c9a4b821dc7055bf9e05ff5719e18ec501f75c0f0bbfabd573b277559780833d",
"sha256:c9f79d5325907f13e1be0b3e4dacc1049d1dffc4aeee3c995284bea5fe0fab7d",
"sha256:cd312b9692e831d2ffcad61eab31d91d4b4655a962e61de8fb410472cbcd37aa",
"sha256:cea3f4c1af79af13cdb2da0c028111d8f8522d4f22a000c82385535f24e5cf3a",
"sha256:cecdd5dfdc87b1fd87dbf81d4b037a544f47f4c744200a67013771682d67686a",
"sha256:cf9d57306d848218f3601fee7601fab1a327c942d56e2e97610583cb4dd74206",
"sha256:d34bbf07dbc7ca5970671b1512e928991fb5e9d95365636c9b2d8b4f53af405e",
"sha256:d49514be2f28d895c38cf9d2b72d7b9a07d00314519f456c0b50b53cfcf4c785",
"sha256:d680fbcb768404c601ecb43519ecd8461f6954cb11c06a78962f666832ccfca8",
"sha256:db1d75f6617a49c1c01bc7023713e0ff59ab32c9579ae62a7674c0e34f3b0b0a",
"sha256:dcb292aa7fe485ceff7af4f92e46c5af397daec5dff64871a528f0fc47a3cc5b",
"sha256:e07c65f443c887bbcf31cc1771d932ecc192a5273943589b3c7572b749f1ffb2",
"sha256:e902da4b04e6b52e5893900d4b8ab46068f75f3561f01bf1080957f9fd932ed6",
"sha256:e9308ff8241c532df3f3e570f9a5aeed6c853f888512ba4b75638d7c11c95ef6",
"sha256:eb7c9811bfaa8b1ed5ed319f5d370dfbcaa59d52ea64be2a5a85e18195930354",
"sha256:ebe6af670449830d6d9b752c256a983291c766a1365ba5d5460048f9e33a7818",
"sha256:ed21202aec73cda4d55d1ce57b389aadb90ffb044e6cd1080b8347efe1b1ec84",
"sha256:efe0374196335f93b53269acd811b944f2e6bdc88e8894f214bd636455484909",
"sha256:f64ec5397ea6a41fc1b4af0380d79b44a755b5531dcaccd9940fb260dca93038",
"sha256:f6ac4ef4d82dff54670227a69c67782ae0b811b5cf6b17954f1e8f7502fc0d1d",
"sha256:f6f0ce10945fab9c4c06ce14e22af9059d1a87493a9af4501a5b0b9187e21cf2",
"sha256:f8844cd288697c6425c9beba919302241e3278871dc6519515e72b04e987abcf",
"sha256:fe0306bd29505a9177aac19f1877174b0e7422c222a59f70b2cd41633448c3dc",
"sha256:ff3f333630ab480244a1bff72043e511a91eb22e7595dead8653ee5612dd8f3d",
"sha256:ffecec8eb889b58ba9be5b95fb1cc78e22ea8eedea38e8736a1568fe1979250e"
"sha256:032a0a97eed428bd143c75a11118238546424ceb2fa311cca5f073aa44658dc4",
"sha256:05f5bce9af14fd1506997594bd81cee6d9c6b58ea80a39c058327aa6371ed9e9",
"sha256:0794e04ba343852c6d78e996c58ef4b8e579b4ecc72f8df0d4058bf843b4c96e",
"sha256:0ab2467e405e748d93495fb5568e74044802b8d3ff2b2a1607c3f78c6e982de5",
"sha256:0bf5a3e397df2ec4258eb5eea4c1ac6cf013ca1abd04a176903bff20a70021fe",
"sha256:0c0710ac085a157b593c38fbcacd950f15c4afa8e2057527185875ab302752bc",
"sha256:0dee106e9aa97fb00541b1ed7827070564d0549c3d3fba8920e6b20fd980f748",
"sha256:0f17d83c48ee9dfd96abae3ac3e2108c76d2fc86ce96355e37b8da9f7f4ecc08",
"sha256:0feebef8d0521188d0157f758356072e840173aa61ca45b8b3f87959ac283dd5",
"sha256:13a620a3fcc20023f9e6ed5c383e00e826f1c2d5db554df2f67240760f9118e8",
"sha256:13d22c0d57355366b393936acf6b98a5e0edeadddd3fccbc6a846c50a76b8741",
"sha256:160fcf381f76c3aeac28a756bec44f48942a8f7245a87aa28e3a523b4d90cd87",
"sha256:16148acd77ed1d8836a56db883af2f5eed720f9723088110b16a0d08582130a6",
"sha256:170773d8a3cdc76259065523ddd978c44f9806e28605f08812e8f86783e44ac6",
"sha256:18293f8a8d8b6a8e71ef37706b659e3846a4261232158167b1ddf35f6994f633",
"sha256:18a4db52b5a7b53a3540b0b0f4123319334621ee8083d496de314d0bf06ff59a",
"sha256:1a635e837b50a1819bebfedaac5916498ea024120969da8790500148fb0a894d",
"sha256:1aeca87830c4fe649dcf93fe2b059525b71c72587f21be4ae4af7103082a79fa",
"sha256:1b7c37339d7e75cab9a123a04248e243cefefb302ad6db566ea0c77cbcde421e",
"sha256:1beb0f9909b26cee938df9ba56b15252a84429b1fc30ce6fca161390b9789a70",
"sha256:20384c2bbcbf87180c8c61eb60869699c1ec0cd09b62cfd13804022d860b0867",
"sha256:20428910dae17a1a93152a3ff2c0441d2f4932992c0797d65651dd0561f1792f",
"sha256:207dfc3d47cf0e575e643bbc140dacc8863b39abaa1e5307cd64c7f2365b8a12",
"sha256:209c3ccbfe35a04ac6d24f0611f9d1cbf8025d49991b14acd935236234d6c156",
"sha256:2123e5aa075ac20d23c7af489255efd129cbfe190dbe88fd42598cc9df3199b6",
"sha256:21402998e4b78e7cce237d2788841aaa21ac9a4d1574d04dc2d12ee41ae807b5",
"sha256:2221e88679d1351e9a40aaee54bc65679b9795bbd0160bc3d5e36b163344eb75",
"sha256:22eec57e26c418cde02c051ce9914a365e52a7f135a565c6f0480242aeebab48",
"sha256:23c366231259cd75ad06495174701afb3fcb36a92917fa47de2d1f1bd9d95739",
"sha256:25f4118c438f96bb466e83108506d03d5c31b1bd2387e83e5b070bda6ded9c37",
"sha256:28a23fefdb345b2d4d0ff2860571b5ff9a89a28b6a120f720e8fb0324d346626",
"sha256:290f66b97ede0e552e1cb44a0fd8a74f9753ee635b50830a0b122fb72788d015",
"sha256:2b9b1325ca1c2a9a2dbb6eb913ae563313f2082ae60b03210f7e83ee80712274",
"sha256:2bec13085dc8ef48a3fe62f7dfcacfeda2c785cdf19cc8eeda2bb9ed081da165",
"sha256:2cae5d5c90a62d9139c512a0cb1aad1d182b022b5740daea2617eb5bf7fc658e",
"sha256:2e01125896585139453cab8cb235893644d8815d7509520da95ae3ee8d1c1f79",
"sha256:2e62c569ec7531b679b184cbfe335c501c1d13c4b363560013019962eb630e6d",
"sha256:2f5b2a2b9811b853b39bfa41367c6d78747b8e3e80e07fc5a24aae295c1a4d7d",
"sha256:302f72413251c03f671e063c9414bed5dc8c927069e5abb69245521e51a4e81b",
"sha256:32a409be3190b088f960ac92bfedfbef2f86c49ff940765e1548177592d20026",
"sha256:33cadd956b667997e4de1635fce9541f2e8ede2038fcde8cf55aa14d571d1bad",
"sha256:379f8a75cf6eb7eef0af074b55f49ab73b868388a98de14646abcdfa4564bb11",
"sha256:3847e71a78cbbc1aff955dbbbaf2fff12153f611d3162c5beaa3395636cbc2f9",
"sha256:38fc4e4e4e084e0bd491949482527d406788045c546d4f8789e93fc527b91385",
"sha256:3a27ac6c780c8b8a1cd231b58407634cafc1c4cc28cd6c7141362df0f36351e7",
"sha256:3a48093cdb058a93af842ede9703520e810b05dcd0fc6d7190a06376c3bfb6bd",
"sha256:3e42265103fb385d8642a78672edf376c6f7e1d3598a7a4f9cb1278f2f6b5f6f",
"sha256:3e9a00d1c2c30936f7add097c41afc5da6556c580909104aafd382cac92a855c",
"sha256:40983eabefd13da003e68170928c7acc011f0d095eefce5871a3c71c9385fb9a",
"sha256:40bcbd9f94166ffe925811e730607385cec959f42fb1bb7dad83748680465221",
"sha256:41096ec0740a58dad03d3ae0c7486d306d20becefb13ceb1649835ab3eb64167",
"sha256:415e3a115c0d510e329020012834d1c0aa1c581ee53a218603e38abbc1dea70a",
"sha256:41e2d428110b408e963b6fb18f9bbf1f5c027b56bd4b498d54556476c0aeb1c3",
"sha256:424aa5657141d306ba9ad1baab4b2c0a0719040075ee6c66aee9bb2dea2b5054",
"sha256:42632b4024ab24a6b488f559ac851312509888b6b80ae2aa11cf29a646a0d245",
"sha256:45222d94ddd511536f3b2f7d9deae3b2339b4ce0f075f1ca25703b07cad9dd21",
"sha256:4736e6c87e603146d8949d8501da621ad20c31015060d3fcf95ace2859f3e3e6",
"sha256:48542c9acba9ff9450bd18d871d2c2c8787fdb283572b623d206f1b927cd7d9e",
"sha256:49fbc2682a9306135b7ec49e93f97f9c26689b9b7f96ed2742d8d6497e994d13",
"sha256:4a579dfb9c835f8ab47f4b8ed33440cbc75b806b73297208e6ec2a33e903740b",
"sha256:4b061064b4a2fe8598a466d723d43dbcd5a610a5d5cfe02fb6226f5c17349f75",
"sha256:4e11e885e0704be185867fcf71b904d8f65d7d6877bc121f69870b0d0479ba7b",
"sha256:4f4db7c7e954d289d71878938348b3d91b904a3e8210a11939359fb758a58e7d",
"sha256:527195c188d7d0af748cd48d220ab8cdc5cb99be3d49ac4d9be7324d8abf9bc0",
"sha256:53258656846f5c48996b882fb4b135885e088a3ad3d96b4bc0530f95124d1f69",
"sha256:545ccc14fb05485f48b4439ec35beb16d5b5280eb6c81c658bd4707a2a119414",
"sha256:5609efdb0d3c95499c00046bc53648b3482ec2175b5503d6e611b3f0555dc71d",
"sha256:5929d9df5e7e3379183be0e21f7d559618a5b61cb63280df6164019242e337ed",
"sha256:5a143e6207579de8baeded4eaac9134413200359f1969d636f0bfb98ee8c3c8f",
"sha256:5a721a98c649855963811b59b55755b30566e7f7fc40bdc9803d66dee9f811cf",
"sha256:5cffe18571ccc51d742cd08cbb3f8b756de9311d18c7ea98f5d92f37b8fb60c2",
"sha256:5d12669a2c419b0e8dc423d23dea24bb82f6f9cb829f32e04674b0ba40322a7c",
"sha256:5d582042c69857c364e8153de6e18e0da9b7b515a6a8113caf69a6ec8e0520f2",
"sha256:61116cec57ed69aebc70f37a545eec095339bb829efbdabcfb97c51e9536e158",
"sha256:611a51e61c92f62345a50b0035df6fc0d678f9299f33728826d831598862f59d",
"sha256:623c8799c17128753c65699f1c3aa32402657393a9ad6db09ed8b98ddf76611d",
"sha256:6374e9e382e5a98c9c5e66d41b357b470da1c54bce30f17f9dc4bcc58436cc1c",
"sha256:66299564c046bc7e0cc5de5106601eae907e9fa5904cd68a323380a8502f7861",
"sha256:69cafd61aea04ebb3502c93c2aaa568b12931ca0802231e0b5de76bf8b6e74bd",
"sha256:6a406d0b3cb207b0fa460ed4dc93e866f44f105da0169361cb18ff998a44c7f0",
"sha256:6ba4fe5bfbef6811a8e49b3719cde373ad399006c0c1ac184b7297116ecbba5d",
"sha256:6cd11e7550d89e551a87dcec30f04b1fca32e86b68708aa01a4daa455d8605e5",
"sha256:6e1eb8a4cbffd5553680ad96be6680e364710656eced73d1dc90ec489df599a3",
"sha256:6ea2f13dce778ca072ccee598bca46a092ce192e8fd907b6c1f0e52c800529a0",
"sha256:71532ebf30be0048a45559b4fab15333fbaaf9042f658e878d918ecd0cf09805",
"sha256:73fc05988ed20809450474ba760a87c8ad4e455fc09783c02195e56ec634b41a",
"sha256:75cc6569e86be5785b6188ef1642670c6adbc984e81ec35e224842ecd9eefcc8",
"sha256:773062aec2f2e56b2b22d37054123f0de8a22a4688a0c3376c3fe42685f975cf",
"sha256:7ae4949f212a53b007dbc355884fda122545c5764a54256c9217e419a62a6559",
"sha256:7b2bb7d703bed7ac893bf7f40d97b5d9279d35d2ce460624ca28929eab0d5a3d",
"sha256:7d0f5976aa2701996f759b30172925829867547bb073af0ae67d1307a0f0262c",
"sha256:7d5a748d12dd9b535e0a130f60dae9ddf0adafbabe61e7864f55c7436c84547a",
"sha256:7dd624c1eaa629ad44b59a1a0145fdf2d67895592dce94c9358b938b3d075e65",
"sha256:7f75b9b9fec2a9c6b18095c81865580e795b1441c429e42d22fcc82a77f40039",
"sha256:83e3a51e7933db700a0da0db31849db3a24022d9970da9bb73001e1d0326fd92",
"sha256:8499d464de86fab0f102313cce32a9bed9ab1f06ec813cf025cb790964fbb765",
"sha256:869dfcd4d381cb0ea87085cc4f011b9171b494ef21e76ad8665f6d5e2d1dc8a1",
"sha256:8753b8d51dbc86fd335ee31fcf7f3658e9f5c016d4edfb23f76ad295f4b8c9d0",
"sha256:887c021d9a977cff89cb273047c1352997b772a8908a25c21836861f69b92be1",
"sha256:88e719b9437f148f7e1465df845c758dd1598618cbea3a2fd1e61a715542f2b2",
"sha256:8a330c0ee5fa318c7b5cbbaad882baeca3f570357e7eb25ab34bf31008150758",
"sha256:8db38ff3fb7aee7d6a82ae4da2eef1178656fe1216841fbd24870062a9d60473",
"sha256:8e49a646acfab83c68974f4aa1d0a2acca9e88d7d627ae0fc13201b14b76d310",
"sha256:909f4e927bb051f7740d6367285fc60cdcfdaf0258c2dba4ff5ba7eadadc250c",
"sha256:90f709b9accab6b2e4d14f5c8718203877a0486bcb3afd74d8b539ecd1e961d4",
"sha256:92d96586376fb79a33474797186bf993250152ee5c32650b67db78d54b92e6f3",
"sha256:93476b6514b373fc6ca67d26c442784f7807c86f00635bfe79f935c3eab2af17",
"sha256:97acecb11cbc411473f15b8d780df06d7a9f3a2aad9aca78364f56640c8fb70e",
"sha256:97ce49699d87ebf8aad631b55d65b33219a4f1bfefbbf5bff19dc9af160aeaf9",
"sha256:9bde9ae026a55b9a192078dfa6e27dd0ca4a050171ab6272e92f97b757dfdf48",
"sha256:9e67324961ac9bbe616cce5100514d2e34d88665aeb07071e8b16eac55d06d94",
"sha256:9efe56a68179f3adc4de41861c9358931db03837c48dd5e1c78077b84dd07f3a",
"sha256:a1932d7ce78a561367512c594fe66eac2b2ec9b9264cfd9b5f950622f4a116e2",
"sha256:a1cec0f99b9b914d39176347a93b7610dc09324491aee1cbc57cd291a41a1d55",
"sha256:a2e3f70673a1d5b82f38255f777d26cd855bf2092b1436c4867464a7892f9238",
"sha256:a43b3bdf11e477dc7770609d3477316f974354dfc8425d596f64f471cc8daf6e",
"sha256:a5c18810318303ce9afb3f95e2ddb54834f96fa699a8600433fd5a93dcf44c56",
"sha256:a7eb78ba28b187e1e9203a55c60fcf70df2d22cb205fe6d51b9383d6097419f0",
"sha256:aa633613ff907ea91b9b0489a1f0da1b8725d8c6ccec6b77e8a1c9c235044bb0",
"sha256:aa9fd1ee2a5dacfc41039ed49ffeeacfa75bafbd255b69f3b578e11897a0e623",
"sha256:ace1d2c83b2bd24db5940600541140e87a325e119cb32d5fa9ad720d7e76648e",
"sha256:b1cc980905221a5d8b3c476330730b3adb40ff80add71ffbdb6215ba055656f1",
"sha256:b37772102d44bb6628186accca3a121b1fa3a6b3d97518a8c29a5229ca4c0d0a",
"sha256:b3ff39654f0ce6ebd4db154211136dbe7e8157bcc3bed2344c87f32c7c6ecb6c",
"sha256:b477912f42c5c33405a10c759d22f80cf5af043ae02d95b9d8e5e5bc555739ed",
"sha256:b49638355ea3bebba70da783ccbc630fd72afa16bc46c54474bfa1f9a915bbc6",
"sha256:b4fc6b03b9d9d90557274f571ab30e7fbbfc527955536935d96f98b6817a86e4",
"sha256:b50343241eb69fd85f7791cf8bcc7b1c4729826b7d59ba2f6b27db29638fa745",
"sha256:bc8dd3d9c93e70c3df974a201ac2958b6d77b465d813c51d1f15fa8e645763ae",
"sha256:be5346653c0b0e34be96869ff9dbeba23860156f89a2896a64c64fb419260cb6",
"sha256:c00e26288784460885fe76e4d4b293573e0f791f52e6d60e27b42edf005922eb",
"sha256:c1b50797ac246bb2942a04b6c0f69af0667aba7cf7535f39bbb1b3208fd5d128",
"sha256:c34ca1dc41bd86d9ff830d5bdf4e4a752bba6c54f7d2707027ce0eabd36084c9",
"sha256:c55e71a9b1db1f107efb60da49c093689b74c5c31a708e5379e2fd9439d4fbb5",
"sha256:c581b1d68b3845fb86c6b2983e755b29bf001461c59fa411d2c26a911b6559a9",
"sha256:c59e4265608da6a041f54646ecc0c9ecdbb19aaf14c4c684bb6c2114998cc415",
"sha256:c5e7ce578aa8a80910a72a8ca0bbea3baae10100827249001999726a788456d8",
"sha256:c66f858b82497173f73366795fc6ee8171620e75a338506d6b2e7bc16f5fca11",
"sha256:c6c0c13128a32eb04a51357e56a094e13aa8e6d3d1884de2e9ae923f6915e1a8",
"sha256:c9389b3784b56c58d933b5e0aecdf28f901b073ff385358d8a7d40907f6e14b2",
"sha256:ca0ec532ad2f5ba1e5ec120ac157769c57f01855b3d8bf37213f5d88abd9ba0a",
"sha256:cad7617727a96d189bd6f979d0fadf765198c7934e85f4edaba9bf3ad919a300",
"sha256:cae82b5ca24b0c2beedb269f6e2a96f466acd926879ab00ae19f1a65cbf9ffb0",
"sha256:cc669256d28736f7f3a149df5c380c50ace2692ba3e62203d10656fade4a2145",
"sha256:ce1f220114959941170e22b8ad44279f6dee2dcef7591814d01ae805dc058889",
"sha256:cfb398886a7eb4c719161c3efcff2a1248febc53a4d8e5072d2d8a87fed84ac9",
"sha256:d077f21f4b16f0471353883748f126f62038760397c107bb9fad2ca94dc0dfb7",
"sha256:d0c5c362bc94f1929dc7e96e715bbe7bd17037f802e6d8f0d1545df9133c0559",
"sha256:d2765c18ce303149ee804b1f3dad11232726dd0a702d73a15cf19179ac8cc962",
"sha256:d44442effeb8781f392340c5dc8c6716fba41dbeacb82fd4c0f09026fb5ff682",
"sha256:d85dfab42dd672f87a7f76e9de7172962aee69fa12044f0d6e1a23cbd53fb80e",
"sha256:d97c5227621af74b111882a290b10f371780a38eef9d9e730408fba2259b52fb",
"sha256:d9a0d12846d6ce434fb3857918eef4315ec9b4769deb020c75828798614bfcfd",
"sha256:d9b3e7d71bf6acff341233417abbdface29c647e3113892d9aaedc02eb4aa2bc",
"sha256:da707f14ea3c35ee463d50acd596d6488e4b2b4ae7cf77a5bf93f55c023d63e8",
"sha256:da85db328e507da922d586c3c7416ec360ec22e9cd9e0700691afacde0c81f53",
"sha256:dc205732d593118cf701d986f40e9de7801bb2e371cb189ddbda9b7348f4d97e",
"sha256:dc3a44689eea43eab836e5c98a8ab015dc2419987d1ea6eafc7c590cdff86bed",
"sha256:dd5e90f34cffcfed97f36cf066325773d2b6021c60c29942e53a18b028501b1d",
"sha256:ddcf547bea2aee967d6a77779376a45e77e610e8465147a1f3d7e20d539d6e32",
"sha256:e477aca0bc0d19f3b4ae9e4f2a1cfd687c31bf772d78734910658186b40b2477",
"sha256:e8b17e23df3e827a69d25af70990ca2420e92668aaffaeeb3cd2351d7916a023",
"sha256:e99e09ab7741f1281e2677f4c0058c7f5267d182530b09c87e4f6aa26adf3887",
"sha256:ea2c01cdb16dc12156e455007c406dfaaece0c89aa4ba0e3b47586779f951d41",
"sha256:ea6b1e9105b4b24a34c722432d9fb578f9ed83af21fa1abda639011e0f22bbb6",
"sha256:ebd054ad1737a68fb7c5c073d405cef2b88bb824e294de3b4a4e995b47f0e376",
"sha256:ec295280f4b37769256da025acf5890370355ac589c27e89caae0b5e9eedc702",
"sha256:f6449672f9c93316deb5e2839e18931f468670e44d5bd9b1301a5a9655d45c07",
"sha256:f683dc6300317700025e41d89a43e0276692ded16113a3c43eab704d605c58e5",
"sha256:f6b9d2aad499c769ee8287609ab0e6de99d8bcea99c6e6c2e64945259fd52fb2",
"sha256:f8b9c8ceebae6387d0dc77f7f4dbbfbfc962dba2efbfe6877486075a480726b4",
"sha256:fad67b12ffe0f71e02b4932b04883cbc76a9072bbd30731409d3523cf058b011",
"sha256:fbfb70ba01355251faf6b293171df49f73a88a1b6494db109ffea85442574458",
"sha256:fe91993149523aa59941b9e3c90e2eb45f57ad014697aef6c8b13339a59c019e",
"sha256:febd35ef45f603c2d74b74655efdbf45e14f55fc0aef4ac82b663ca829b283e0",
"sha256:ff88a92cafde90888511242d1c54afcc1a8adbb6dc0a88fa7f87e29e92400d4a"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==6.1.1"
"version": "==6.1.3"
},
"markdown": {
"hashes": [
"sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950",
"sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36"
"sha256:87bf5d90f2d2882e2c02fcda182c2800456b985bff38913867c49706481514b0",
"sha256:f80390747a2a0ff2ba54da074ce4f862f72a6685f608cd2637b646a6d83993f5"
],
"index": "pypi",
"markers": "python_version >= '3.10'",
"version": "==3.10.2"
"markers": "python_version >= '3.11'",
"version": "==3.11.2"
},
"markupsafe": {
"hashes": [
+2 -7
View File
@@ -1,13 +1,10 @@
#!/usr/bin/env python3
from datetime import date
from io import StringIO
from lxml import etree
import markdown
from markdown.extensions import Extension
import re
import os
import sys
from time import time
import yaml
@@ -68,9 +65,7 @@ class RoffWalker(object):
last_tag = None
while root is not None:
if root.tag == 'h1':
epoch = int(os.environ.get('SOURCE_DATE_EPOCH', time()))
self.__write_cmd('.TH "JQ" "1" "{}" "" ""'.format(
date.fromtimestamp(epoch).strftime('%B %Y')))
self.__write_cmd('.TH "JQ" "1" "" "" ""')
self.__write_cmd('.SH "NAME"')
# TODO: properly parse this
self.__write_raw(r'\fBjq\fR \- Command\-line JSON processor' +
@@ -232,7 +227,7 @@ def convert_manual_to_markdown():
f.write("jq '{}'\n".format(example.get('program', '')))
f.write(" {}\n".format(example.get('input', '')))
output = [str(x) for x in example.get('output', [])]
f.write("=> {}\n".format(', '.join(output)))
f.write("=> {}\n".format('\n '.join(output)))
first = False
f.write("~~~~\n")
f.write('\n')
+2 -1
View File
@@ -33,7 +33,8 @@ env.filters['entry_id'] = lambda input: re.sub(
r'\1', # e.g. range-range-range -> range
re.sub(r' ?/ ?|,? ', '-',
re.sub(r'[`;]|: .*|\(.*?\)| \[.+\]', '', input)))).lower()
env.filters['markdownify'] = lambda input: Markup(markdown(input))
env.filters['markdownify'] = lambda input: Markup(
markdown(input, extensions=['md_in_html']))
env.filters['no_paragraph'] = lambda input: Markup(re.sub(r'</?p>', '', input))
env.globals['unique_id'] = pass_context(
+95 -29
View File
@@ -3,8 +3,9 @@ body:
- text: |
jq is written in C and has no runtime dependencies, so it should be
possible to build it for nearly any platform. Prebuilt binaries are
available for Linux, macOS and Windows.
possible to build it for nearly any platform. The prebuilt files linked
below are standalone executables, not archives, and are available for
Linux, macOS and Windows.
The binaries should just run, but on macOS and Linux you may need
to make them executable first using `chmod +x jq`.
@@ -32,6 +33,19 @@ body:
* jq is in the official [Arch](https://archlinux.org/packages/?q=jq) repository.
Install using `sudo pacman -S jq`.
* jq is in [conda-forge](https://anaconda.org/conda-forge/jq).
Install using `conda install -c conda-forge jq`.
* jq 1.8.2 binaries for
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-amd64)
or
[ARM64](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-arm64)
or
[i386](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-i386).
<details markdown="1">
<summary>Older versions</summary>
* jq 1.8.1 binaries for
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-linux-amd64)
or
@@ -80,6 +94,8 @@ body:
or
[i386](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-linux-x86).
</details>
### macOS
* Use [Homebrew](https://brew.sh/) to install jq with `brew install jq`.
@@ -88,6 +104,17 @@ body:
* Use [Fink](https://finkproject.org) to install jq with `fink install jq`.
* Use [conda-forge](https://anaconda.org/conda-forge/jq) to install jq with
`conda install -c conda-forge jq`.
* jq 1.8.2 binaries for
[Apple Silicon](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-macos-arm64)
or
[Intel Mac](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-macos-amd64).
<details markdown="1">
<summary>Older versions</summary>
* jq 1.8.1 binaries for
[Apple Silicon](https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-macos-arm64)
or
@@ -124,6 +151,8 @@ body:
or
[i386](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-osx-x86).
</details>
### FreeBSD
* `pkg install jq` as root installs a pre-built
@@ -154,6 +183,16 @@ body:
* Use [Chocolatey NuGet](https://chocolatey.org/) to install jq with
`choco install jq`.
* jq 1.8.2 executables for
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-windows-amd64.exe)
or
[ARM64](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-windows-arm64.exe)
or
[i386](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-windows-i386.exe).
<details markdown="1">
<summary>Older versions</summary>
* jq 1.8.1 executables for
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-windows-amd64.exe)
or
@@ -194,40 +233,65 @@ body:
or
[i386](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-win32.exe).
</details>
### Checksums and signatures
SHA-256 checksums are provided for all release and pre-release binaries.
The checksums for jq 1.8.1 are in
[sig/v1.8.1/sha256sum.txt](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.8.1/sha256sum.txt).
The checksums for jq 1.8.0 are in
[sig/v1.8.0/sha256sum.txt](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.8.0/sha256sum.txt).
The checksums for jq 1.7.1 are in
[sig/v1.7.1/sha256sum.txt](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.7.1/sha256sum.txt).
The checksums for jq 1.7 are in
[sig/v1.7/sha256sum.txt](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.7/sha256sum.txt).
The checksums for jq 1.6 are in
[sig/v1.6/sha256sum.txt](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.6/sha256sum.txt).
The checksums for jq 1.5 are in
[sig/v1.5/sha256sum.txt](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.5/sha256sum.txt).
Additionally, all release artifacts are signed by a jq release key. We have two release keys, [one for 1.6 and older releases](https://raw.githubusercontent.com/jqlang/jq/master/sig/jq-release-old.key), and [one for 1.7 and newer releases](https://raw.githubusercontent.com/jqlang/jq/master/sig/jq-release-new.key).
The signatures for jq 1.8.1 are in
[sig/v1.8.1/\*.asc](https://github.com/jqlang/jq/tree/master/sig/v1.8.1).
The signatures for jq 1.8.0 are in
[sig/v1.8.0/\*.asc](https://github.com/jqlang/jq/tree/master/sig/v1.8.0).
The signatures for jq 1.7.1 are in
[sig/v1.7.1/\*.asc](https://github.com/jqlang/jq/tree/master/sig/v1.7.1).
The signatures for jq 1.7 are in
[sig/v1.7/\*.asc](https://github.com/jqlang/jq/tree/master/sig/v1.7).
The signatures for jq 1.6 are in
[sig/v1.6/\*.asc](https://github.com/jqlang/jq/tree/master/sig/v1.6).
The signatures for jq 1.5 are in
[sig/v1.5/\*.asc](https://github.com/jqlang/jq/tree/master/sig/v1.5).
SHA-256 checksums are provided for all release and pre-release binaries,
and all release artifacts are signed by a jq release key. We have two release keys,
[one for 1.6 and older releases](https://raw.githubusercontent.com/jqlang/jq/master/sig/jq-release-old.key),
and
[one for 1.7 and newer releases](https://raw.githubusercontent.com/jqlang/jq/master/sig/jq-release-new.key).
You can use [GnuPG](https://gnupg.org/) to verify a signature by downloading
the signature and running `gpg --verify signature.asc`.
* jq 1.8.2
[checksums](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.8.2/sha256sum.txt)
and
[signatures](https://github.com/jqlang/jq/tree/master/sig/v1.8.2).
<details markdown="1">
<summary>Older versions</summary>
* jq 1.8.1
[checksums](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.8.1/sha256sum.txt)
and
[signatures](https://github.com/jqlang/jq/tree/master/sig/v1.8.1).
* jq 1.8.0
[checksums](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.8.0/sha256sum.txt)
and
[signatures](https://github.com/jqlang/jq/tree/master/sig/v1.8.0).
* jq 1.7.1
[checksums](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.7.1/sha256sum.txt)
and
[signatures](https://github.com/jqlang/jq/tree/master/sig/v1.7.1).
* jq 1.7
[checksums](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.7/sha256sum.txt)
and
[signatures](https://github.com/jqlang/jq/tree/master/sig/v1.7).
* jq 1.6
[checksums](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.6/sha256sum.txt)
and
[signatures](https://github.com/jqlang/jq/tree/master/sig/v1.6).
* jq 1.5
[checksums](https://raw.githubusercontent.com/jqlang/jq/master/sig/v1.5/sha256sum.txt)
and
[signatures](https://github.com/jqlang/jq/tree/master/sig/v1.5).
</details>
### From source on Linux, macOS, Cygwin, and other POSIX-like operating systems
* [Source tarball for jq 1.8.2](https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-1.8.2.tar.gz)
<details markdown="1">
<summary>Older versions</summary>
* [Source tarball for jq 1.8.1](https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-1.8.1.tar.gz)
* [Source tarball for jq 1.8.0](https://github.com/jqlang/jq/releases/download/jq-1.8.0/jq-1.8.0.tar.gz)
* [Source tarball for jq 1.7.1](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-1.7.1.tar.gz)
@@ -235,6 +299,8 @@ body:
* [Source tarball for jq 1.6](https://github.com/jqlang/jq/releases/download/jq-1.6/jq-1.6.tar.gz)
* [Source tarball for jq 1.5](https://github.com/jqlang/jq/releases/download/jq-1.5/jq-1.5.tar.gz)
</details>
You can build it using the usual `./configure && make && sudo
make install` rigmarole.
+4
View File
@@ -32,6 +32,10 @@ tail: |
on [Libera.Chat](https://libera.chat/). For more interactive discussions, feel free to join our [Discord server](https://discord.gg/yg6yjNmgAC).
news:
- date: 20 June 2026
body: |
jq 1.8.2 released. See [release notes](https://github.com/jqlang/jq/releases/tag/jq-1.8.2) for details.
- date: 1 July 2025
body: |
jq 1.8.1 released. See [release notes](https://github.com/jqlang/jq/releases/tag/jq-1.8.1) for details.
+128 -35
View File
@@ -85,24 +85,24 @@ sections:
language is quite rich and allows for much more than just
validation and pretty-printing.
Note: it is important to mind the shell's quoting rules. As a
general rule it's best to always quote (with single-quote
characters on Unix shells) the jq program, as too many characters with special
meaning to jq are also shell meta-characters. For example, `jq
"foo"` will fail on most Unix shells because that will be the same
as `jq foo`, which will generally fail because `foo is not
defined`. When using the Windows command shell (cmd.exe) it's
best to use double quotes around your jq program when given on the
command-line (instead of the `-f program-file` option), but then
double-quotes in the jq program need backslash escaping. When using
the Powershell (`powershell.exe`) or the Powershell Core
(`pwsh`/`pwsh.exe`), use single-quote characters around the jq
program and backslash-escaped double-quotes (`\"`) inside the jq
Note: It is important to mind the shell's quoting rules. As a general
rule, it's best to always quote the jq program, as many characters with
special meaning to jq are also shell meta-characters. For example, `jq
"foo"` will fail on most shells, as it's equivalent to `jq foo` which will
generally fail because `foo is not defined`.
Inside a Unix shell or PowerShell 7.3+, use single quotes around the jq
program and double quotes inside the jq program.
When using PowerShell before 7.3 or Windows PowerShell (`powershell.exe`),
use single quotes around the jq program and backslash-escaped double
quotes (`\"`) inside the jq program.
When using the Windows command interpreter (cmd.exe), use double quotes
around your jq program, and backslash-escaped double quotes inside the jq
program.
* Unix shells: `jq '.["foo"]'`
* Powershell: `jq '.[\"foo\"]'`
* Windows command shell: `jq ".[\"foo\"]"`
* Unix shells, PowerShell 7.3+: `jq '.["foo"]'`
* PowerShell 7.2 and older, Windows PowerShell: `jq '.[\"foo\"]'`
* Windows command interpreter: `jq ".[\"foo\"]"`
Note: jq allows user-defined functions, but every jq program
must have a top-level expression.
@@ -169,8 +169,10 @@ sections:
By default, jq outputs colored JSON if writing to a
terminal. You can force it to produce color even if writing to
a pipe or a file using `-C`, and disable color with `-M`.
When the `NO_COLOR` environment variable is not empty, jq disables
colored output by default, but you can enable it by `-C`.
When the `NO_COLOR` environment variable is not empty,
or the `TERM` environment variable is unset, empty, or set to
`dumb`, jq disables colored output by default, but you can
enable it by `-C`.
Colors can be configured with the `JQ_COLORS` environment
variable (see below).
@@ -888,7 +890,7 @@ sections:
section on the identity filter for the implications of this
definition for numeric input.
To compute the absolute value of a number as a floating point number, you may wish use `fabs`.
To compute the absolute value of a number as a floating point number, you may wish to use `fabs`.
examples:
- program: 'map(abs)'
@@ -1820,7 +1822,7 @@ sections:
Whitespace characters are the usual `" "`, `"\n"` `"\t"`, `"\r"`
and also all characters in the Unicode character database with the
whitespace property. Note that what considers whitespace might
whitespace property. Note that what is considered whitespace might
change in the future.
examples:
@@ -1865,14 +1867,16 @@ sections:
- title: "`join(str)`"
body: |
Joins the array of elements given as input, using the
Joins the values from the input array or object, using the
argument as separator. It is the inverse of `split`: that is,
running `split("foo") | join("foo")` over any input string
returns said input string.
Numbers and booleans in the input are converted to strings.
Null values are treated as empty strings. Arrays and objects
in the input are not supported.
Null values are treated as empty strings. When the input is
an object, `join` operates on the values that `.[]`
produces. Arrays and objects among the joined values are not
supported.
examples:
- program: 'join(", ")'
@@ -1881,6 +1885,9 @@ sections:
- program: 'join(" ")'
input: '["a",1,2.3,true,null,false]'
output: ['"a 1 2.3 true false"']
- program: 'join(", ")'
input: '{"a":1,"b":2}'
output: ['"1, 2"']
- title: "`ascii_downcase`, `ascii_upcase`"
body: |
@@ -2245,13 +2252,45 @@ sections:
The `fromdateiso8601` builtin parses datetimes in the ISO 8601
format to a number of seconds since the Unix epoch
(1970-01-01T00:00:00Z). The `todateiso8601` builtin does the
inverse.
(1970-01-01T00:00:00Z). The `todateiso8601` builtin formats a
number of seconds as `"%Y-%m-%dT%H:%M:%SZ"`.
The `fromdate` builtin parses datetime strings. Currently
`fromdate` only supports ISO 8601 datetime strings, but in the
future it will attempt to parse datetime strings in more
formats.
`fromdateiso8601` accepts a complete date, optionally followed by
a time of day, written in either the extended representation, which
separates the components, or the basic representation, which does
not. The two cannot be mixed within one datetime. The date may be
a calendar date (`2015-03-05`, `20150305`), an ordinal date
(`2015-064`, `2015064`), or a week date (`2015-W10-4`, `2015W104`);
all three denote the same day. Years outside the range 0000 to 9999
are written with a sign and six digits, as in `+012015-03-05`.
The time of day may omit its seconds, or its minutes and seconds,
as in `2015-03-05T23:51Z` and `2015-03-05T23Z`, or be left out
altogether, in which case the value is midnight UTC. It may carry a
fractional part after a `.` or a `,`, which belongs to the lowest
component present, so `23,5` is half past 23. It may be followed
by an offset from UTC written as `Z`, `+hh`, `+hh:mm` or `+hhmm`;
a datetime with no offset is read as UTC. A time of `24:00:00`
denotes midnight of the following day, and a leap second is read as
the second before it, since jq counts every day as 86400 seconds.
The `W`, `T` and `Z` designators may also be written in lower
case, which ISO 8601 permits where upper case is not available.
RFC 3339 additionally allows the date and the time to be separated
by a space instead of a `T` "for the sake of readability", which jq
accepts too. The offset may use the other representation's
separator style, as in `2015-03-05T23:51:47+0900`, although
ISO 8601 does not allow the basic and extended representations
to be mixed.
A complete date is required, so `2015` and `2015-03` are errors
even though ISO 8601 defines them as dates, and `T23:51:47` is an
error because a time of day on its own is not a point in time.
Dates that do not exist, such as `2015-02-30` or `2016-W53-1`, are
errors too, as is `2015-03-05Z`, since a zone designator belongs to
the time of day.
The `fromdate` builtin is an alias for `fromdateiso8601`.
The `todate` builtin is an alias for `todateiso8601`.
@@ -2291,8 +2330,11 @@ sections:
the local timezone setting.
The format strings for `strptime` and `strftime` are described
in typical C library documentation. The format string for ISO
8601 datetime is `"%Y-%m-%dT%H:%M:%SZ"`.
in typical C library documentation. `"%Y-%m-%dT%H:%M:%SZ"` is
the format that `todateiso8601` produces; it is only one of the
ISO 8601 representations that `fromdateiso8601` accepts, and
`strptime` cannot parse the others -- there is no portable format
specifier for week dates or for fractional seconds.
jq may not support some or all of this date functionality on
some systems. In particular, the `%u` and `%j` specifiers for
@@ -2303,6 +2345,14 @@ sections:
input: '"2015-03-05T23:51:47Z"'
output: ['1425599507']
- program: 'fromdateiso8601'
input: '"2015-03-06T08:51:47.25+09:00"'
output: ['1425599507.25']
- program: 'map(fromdateiso8601)'
input: '["20150305T235147Z","2015-064T23:51:47Z","2015-W10-4T23:51:47Z"]'
output: ['[1425599507,1425599507,1425599507]']
- program: 'strptime("%Y-%m-%dT%H:%M:%SZ")'
input: '"2015-03-05T23:51:47Z"'
output: ['[2015,2,5,23,51,47,4,63]']
@@ -2814,7 +2864,7 @@ sections:
which to place the data.
It is also possible to define functions in jq, although this is
is a feature whose biggest use is defining jq's standard library
a feature whose biggest use is defining jq's standard library
(many jq functions such as `map` and `select` are in fact written
in jq).
@@ -2896,7 +2946,7 @@ sections:
. as {realnames: $names, posts: [$first, $second]} | ...
The variable declarations in array patterns (e.g., `. as
[$first, $second]`) bind to the elements of the array in from
[$first, $second]`) bind to the elements of the array from
the element at index zero on up, in order. When there is no
value at the index for an array pattern element, `null` is
bound to that variable.
@@ -3022,6 +3072,16 @@ sections:
to be evaluated once per value in the value of `.` at the call
site.
Multiple arguments are separated by semicolons, both in the
definition and in the call:
def f(a; b): ...;
f(.x; .y)
A comma does not separate arguments. `f(.x, .y)` calls a
one-argument `f` with the single filter `.x, .y`, which
outputs `.x` and then `.y` (see the comma operator above).
Multiple definitions using the same function name are allowed.
Each re-definition replaces the previous one for the same
number of function arguments, but only for references from
@@ -3035,6 +3095,12 @@ sections:
- program: 'def addvalue(f): f as $x | map(. + $x); addvalue(.[0])'
input: '[[1,2],[10,20]]'
output: ['[[1,2,1,2], [10,20,1,2]]']
- program: 'def f(a; b): [a, b]; f(.x; .y)'
input: '{"x":1,"y":2}'
output: ['[1,2]']
- program: 'def f(a): [a]; f(.x, .y)'
input: '{"x":1,"y":2}'
output: ['[1,2]']
- title: 'Scoping'
body: |
@@ -3511,6 +3577,13 @@ sections:
The left-hand side can be any general path expression; see `path()`.
The right-hand side of `|=` is run with the value at the path
as its input, not with `.`. This is what sets it apart from
plain assignment (`=`) and the arithmetic update-assignment
operators such as `+=`, whose right-hand side is run with `.`.
For example, `.a |= .b` sets `.a` to the `b` field of `.a`,
while `.a = .b` and `.a += .b` use the `b` field of `.`.
Note that the left-hand side of `|=` refers to a value in `.`.
Thus `$var.foo |= . + 1` won't work as expected (`$var.foo` is
not a valid or useful path expression in `.`); use `$var |
@@ -3524,6 +3597,12 @@ sections:
releases, it used to be that only the last one was used).
examples:
- program: '.foo |= . + 1'
input: '{"foo": 41, "bar": "unchanged"}'
output: ['{"foo": 42, "bar": "unchanged"}']
- program: '.user.age |= . + 1'
input: '{"user": {"name": "alice", "age": 30}, "active": true}'
output: ['{"user": {"name": "alice", "age": 31}, "active": true}']
- program: '(..|select(type=="boolean")) |= if . then 1 else 0 end'
input: '[true,false,[5,true,[true,[false]],false]]'
output: ['[1,0,[5,1,[1,[0]],0]]']
@@ -3532,13 +3611,27 @@ sections:
body: |
jq has a few operators of the form `a op= b`, which are all
equivalent to `a |= . op b`. So, `+= 1` can be used to
increment values, being the same as `|= . + 1`.
equivalent to `(b as $b | a |= . op $b)`. So, `+= 1` can be
used to increment values, being the same as `|= . + 1`.
Note that the right-hand side `b` is evaluated with the same
input as the left-hand side, not with the value at the path
being updated. So `.a += .b` adds the value of `.b` to `.a`,
whereas `.a |= . + .b` would look up `.b` inside the value of
`.a`.
If `b` outputs multiple values, then `a op= b` outputs one
result for each of them.
examples:
- program: .foo += 1
input: '{"foo": 42}'
output: ['{"foo": 43}']
- program: '.a += .b'
input: '{"a": 1, "b": 2}'
output: ['{"a": 3, "b": 2}']
- program: '.a += (1,2)'
input: '{"a": 0}'
output: ['{"a": 1}', '{"a": 2}']
- title: "Plain assignment: `=`"
body: |
+1 -1
View File
@@ -1008,7 +1008,7 @@ sections:
which to place the data.
It is also possible to define functions in jq, although this is
is a feature whose biggest use is defining jq's standard library
a feature whose biggest use is defining jq's standard library
(many jq functions such as `map` and `select` are in fact written
in jq).
+1 -1
View File
@@ -1414,7 +1414,7 @@ sections:
which to place the data.
It is also possible to define functions in jq, although this is
is a feature whose biggest use is defining jq's standard library
a feature whose biggest use is defining jq's standard library
(many jq functions such as `map` and `select` are in fact written
in jq).
+2 -2
View File
@@ -2171,7 +2171,7 @@ sections:
which to place the data.
It is also possible to define functions in jq, although this is
is a feature whose biggest use is defining jq's standard library
a feature whose biggest use is defining jq's standard library
(many jq functions such as `map` and `select` are in fact written
in jq).
@@ -2253,7 +2253,7 @@ sections:
. as {realnames: $names, posts: [$first, $second]} | ...
The variable declarations in array patterns (e.g., `. as
[$first, $second]`) bind to the elements of the array in from
[$first, $second]`) bind to the elements of the array from
the element at index zero on up, in order. When there is no
value at the index for an array pattern element, `null` is
bound to that variable.
+2 -2
View File
@@ -2432,7 +2432,7 @@ sections:
which to place the data.
It is also possible to define functions in jq, although this is
is a feature whose biggest use is defining jq's standard library
a feature whose biggest use is defining jq's standard library
(many jq functions such as `map` and `select` are in fact written
in jq).
@@ -2514,7 +2514,7 @@ sections:
. as {realnames: $names, posts: [$first, $second]} | ...
The variable declarations in array patterns (e.g., `. as
[$first, $second]`) bind to the elements of the array in from
[$first, $second]`) bind to the elements of the array from
the element at index zero on up, in order. When there is no
value at the index for an array pattern element, `null` is
bound to that variable.
+3 -3
View File
@@ -876,7 +876,7 @@ sections:
section on the identity filter for the implications of this
definition for numeric input.
To compute the absolute value of a number as a floating point number, you may wish use `fabs`.
To compute the absolute value of a number as a floating point number, you may wish to use `fabs`.
examples:
- program: 'map(abs)'
@@ -2733,7 +2733,7 @@ sections:
which to place the data.
It is also possible to define functions in jq, although this is
is a feature whose biggest use is defining jq's standard library
a feature whose biggest use is defining jq's standard library
(many jq functions such as `map` and `select` are in fact written
in jq).
@@ -2815,7 +2815,7 @@ sections:
. as {realnames: $names, posts: [$first, $second]} | ...
The variable declarations in array patterns (e.g., `. as
[$first, $second]`) bind to the elements of the array in from
[$first, $second]`) bind to the elements of the array from
the element at index zero on up, in order. When there is no
value at the index for an array pattern element, `null` is
bound to that variable.
+13 -8
View File
@@ -888,7 +888,7 @@ sections:
section on the identity filter for the implications of this
definition for numeric input.
To compute the absolute value of a number as a floating point number, you may wish use `fabs`.
To compute the absolute value of a number as a floating point number, you may wish to use `fabs`.
examples:
- program: 'map(abs)'
@@ -990,7 +990,7 @@ sections:
- program: '.[] | in({"foo": 42})'
input: '["foo", "bar"]'
output: ['true', 'false']
- program: 'map(in([0,1]))'
- program: 'map(in([3,4]))'
input: '[2, 0]'
output: ['[false, true]']
@@ -1820,7 +1820,7 @@ sections:
Whitespace characters are the usual `" "`, `"\n"` `"\t"`, `"\r"`
and also all characters in the Unicode character database with the
whitespace property. Note that what considers whitespace might
whitespace property. Note that what is considered whitespace might
change in the future.
examples:
@@ -1865,14 +1865,16 @@ sections:
- title: "`join(str)`"
body: |
Joins the array of elements given as input, using the
Joins the values from the input array or object, using the
argument as separator. It is the inverse of `split`: that is,
running `split("foo") | join("foo")` over any input string
returns said input string.
Numbers and booleans in the input are converted to strings.
Null values are treated as empty strings. Arrays and objects
in the input are not supported.
Null values are treated as empty strings. When the input is
an object, `join` operates on the values that `.[]`
produces. Arrays and objects among the joined values are not
supported.
examples:
- program: 'join(", ")'
@@ -1881,6 +1883,9 @@ sections:
- program: 'join(" ")'
input: '["a",1,2.3,true,null,false]'
output: ['"a 1 2.3 true false"']
- program: 'join(", ")'
input: '{"a":1,"b":2}'
output: ['"1, 2"']
- title: "`ascii_downcase`, `ascii_upcase`"
body: |
@@ -2814,7 +2819,7 @@ sections:
which to place the data.
It is also possible to define functions in jq, although this is
is a feature whose biggest use is defining jq's standard library
a feature whose biggest use is defining jq's standard library
(many jq functions such as `map` and `select` are in fact written
in jq).
@@ -2896,7 +2901,7 @@ sections:
. as {realnames: $names, posts: [$first, $second]} | ...
The variable declarations in array patterns (e.g., `. as
[$first, $second]`) bind to the elements of the array in from
[$first, $second]`) bind to the elements of the array from
the element at index zero on up, in order. When there is no
value at the index for an array pattern element, `null` is
bound to that variable.
File diff suppressed because it is too large. Load diff
+13
View File
@@ -45,6 +45,19 @@ ul {
padding-left: 1rem;
}
details {
margin-bottom: 1rem;
padding-left: 1rem;
& summary {
cursor: pointer;
}
& ul {
padding-left: 0;
}
}
pre {
margin: 0 .5rem 1rem;
padding: .5rem 1rem;
+6 -6
View File
@@ -14,15 +14,15 @@
<h2 class="px-1" style="width:16em">{{ blurb }}</h2>
<div class="btn-group d-print-none" role="group">
<button type="button" class="btn btn-primary dropdown-toggle text-nowrap" data-bs-toggle="dropdown" aria-expanded="false">
Download jq 1.8.1
Download jq 1.8.2
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-linux-amd64" aria-label="Link to download executable: Linux (AMD64)"><span class="bi bi-download me-2" aria-hidden="true"></span>Linux (AMD64)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-linux-arm64" aria-label="Link to download executable: Linux (ARM64)"><span class="bi bi-download me-2" aria-hidden="true"></span>Linux (ARM64)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-macos-arm64" aria-label="Link to download executable: macOS (Apple Silicon)"><span class="bi bi-download me-2" aria-hidden="true"></span>macOS (Apple Silicon)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-macos-amd64" aria-label="Link to download executable: macOS (Intel Mac)"><span class="bi bi-download me-2" aria-hidden="true"></span>macOS (Intel Mac)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-windows-amd64.exe" aria-label="Link to download executable: Windows (AMD64)"><span class="bi bi-download me-2" aria-hidden="true"></span>Windows (AMD64)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-amd64" aria-label="Link to download executable: Linux (AMD64)"><span class="bi bi-download me-2" aria-hidden="true"></span>Linux (AMD64)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-arm64" aria-label="Link to download executable: Linux (ARM64)"><span class="bi bi-download me-2" aria-hidden="true"></span>Linux (ARM64)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-macos-arm64" aria-label="Link to download executable: macOS (Apple Silicon)"><span class="bi bi-download me-2" aria-hidden="true"></span>macOS (Apple Silicon)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-macos-amd64" aria-label="Link to download executable: macOS (Intel Mac)"><span class="bi bi-download me-2" aria-hidden="true"></span>macOS (Intel Mac)</a></li>
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-windows-amd64.exe" aria-label="Link to download executable: Windows (AMD64)"><span class="bi bi-download me-2" aria-hidden="true"></span>Windows (AMD64)</a></li>
<li><a class="dropdown-item" href="/download/">Other platforms, older versions, and source</a></li>
</ul>
<a class="btn btn-primary text-nowrap" href="https://play.jqlang.org" rel="noopener">
Generated
+220 -61
View File
@@ -1,5 +1,5 @@
.
.TH "JQ" "1" "May 2025" "" ""
.TH "JQ" "1" "" "" ""
.
.SH "NAME"
\fBjq\fR \- Command\-line JSON processor
@@ -38,16 +38,19 @@ jq filters run on a stream of JSON data\. The input to jq is parsed as a sequenc
The simplest and most common filter (or jq program) is \fB\.\fR, which is the identity operator, copying the inputs of the jq processor to the output stream\. Because the default behavior of the jq processor is to read JSON texts from the input stream, and to pretty\-print outputs, the \fB\.\fR program\'s main use is to validate and pretty\-print the inputs\. The jq programming language is quite rich and allows for much more than just validation and pretty\-printing\.
.
.P
Note: it is important to mind the shell\'s quoting rules\. As a general rule it\'s best to always quote (with single\-quote characters on Unix shells) the jq program, as too many characters with special meaning to jq are also shell meta\-characters\. For example, \fBjq "foo"\fR will fail on most Unix shells because that will be the same as \fBjq foo\fR, which will generally fail because \fBfoo is not defined\fR\. When using the Windows command shell (cmd\.exe) it\'s best to use double quotes around your jq program when given on the command\-line (instead of the \fB\-f program\-file\fR option), but then double\-quotes in the jq program need backslash escaping\. When using the Powershell (\fBpowershell\.exe\fR) or the Powershell Core (\fBpwsh\fR/\fBpwsh\.exe\fR), use single\-quote characters around the jq program and backslash\-escaped double\-quotes (\fB\e"\fR) inside the jq program\.
Note: It is important to mind the shell\'s quoting rules\. As a general rule, it\'s best to always quote the jq program, as many characters with special meaning to jq are also shell meta\-characters\. For example, \fBjq "foo"\fR will fail on most shells, as it\'s equivalent to \fBjq foo\fR which will generally fail because \fBfoo is not defined\fR\.
.
.P
Inside a Unix shell or PowerShell 7\.3+, use single quotes around the jq program and double quotes inside the jq program\. When using PowerShell before 7\.3 or Windows PowerShell (\fBpowershell\.exe\fR), use single quotes around the jq program and backslash\-escaped double quotes (\fB\e"\fR) inside the jq program\. When using the Windows command interpreter (cmd\.exe), use double quotes around your jq program, and backslash\-escaped double quotes inside the jq program\.
.
.IP "\(bu" 4
Unix shells: \fBjq \'\.["foo"]\'\fR
Unix shells, PowerShell 7\.3+: \fBjq \'\.["foo"]\'\fR
.
.IP "\(bu" 4
Powershell: \fBjq \'\.[\e"foo\e"]\'\fR
PowerShell 7\.2 and older, Windows PowerShell: \fBjq \'\.[\e"foo\e"]\'\fR
.
.IP "\(bu" 4
Windows command shell: \fBjq "\.[\e"foo\e"]"\fR
Windows command interpreter: \fBjq "\.[\e"foo\e"]"\fR
.
.IP "" 0
.
@@ -115,7 +118,7 @@ Output the fields of each object with the keys in sorted order\.
\fB\-\-color\-output\fR / \fB\-C\fR and \fB\-\-monochrome\-output\fR / \fB\-M\fR:
.
.IP
By default, jq outputs colored JSON if writing to a terminal\. You can force it to produce color even if writing to a pipe or a file using \fB\-C\fR, and disable color with \fB\-M\fR\. When the \fBNO_COLOR\fR environment variable is not empty, jq disables colored output by default, but you can enable it by \fB\-C\fR\.
By default, jq outputs colored JSON if writing to a terminal\. You can force it to produce color even if writing to a pipe or a file using \fB\-C\fR, and disable color with \fB\-M\fR\. When the \fBNO_COLOR\fR environment variable is not empty, or the \fBTERM\fR environment variable is unset, empty, or set to \fBdumb\fR, jq disables colored output by default, but you can enable it by \fB\-C\fR\.
.
.IP
Colors can be configured with the \fBJQ_COLORS\fR environment variable (see below)\.
@@ -472,7 +475,8 @@ Note that the iterator operator is a generator of values\.
jq \'\.[]\'
[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
=> {"name":"JSON", "good":true}, {"name":"XML", "good":false}
=> {"name":"JSON", "good":true}
{"name":"XML", "good":false}
jq \'\.[]\'
[]
@@ -480,11 +484,14 @@ jq \'\.[]\'
jq \'\.foo[]\'
{"foo":[1,2,3]}
=> 1, 2, 3
=> 1
2
3
jq \'\.[]\'
{"a": 1, "b": 1}
=> 1, 1
=> 1
1
.
.fi
.
@@ -505,15 +512,19 @@ The \fB,\fR operator is one way to construct generators\.
jq \'\.foo, \.bar\'
{"foo": 42, "bar": "something else", "baz": true}
=> 42, "something else"
=> 42
"something else"
jq \'\.user, \.projects[]\'
{"user":"stedolan", "projects": ["jq", "wikiflow"]}
=> "stedolan", "jq", "wikiflow"
=> "stedolan"
"jq"
"wikiflow"
jq \'\.[4,2]\'
["a","b","c","d","e"]
=> "e", "c"
=> "e"
"c"
.
.fi
.
@@ -537,7 +548,8 @@ Note too that \fB\.\fR is the input value at the particular stage in a "pipeline
jq \'\.[] | \.name\'
[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
=> "JSON", "XML"
=> "JSON"
"XML"
.
.fi
.
@@ -720,7 +732,8 @@ produces
jq \'{user, title: \.titles[]}\'
{"user":"stedolan","titles":["JQ Primer", "More JQ"]}
=> {"user":"stedolan", "title": "JQ Primer"}, {"user":"stedolan", "title": "More JQ"}
=> {"user":"stedolan", "title": "JQ Primer"}
{"user":"stedolan", "title": "More JQ"}
jq \'{(\.user): \.titles}\'
{"user":"stedolan","titles":["JQ Primer", "More JQ"]}
@@ -854,7 +867,8 @@ jq \'{"k": {"a": 1, "b": 2}} * {"k": {"a": 0,"c": 3}}\'
jq \'\.[] | (1 / \.)?\'
[1,0,\-1]
=> 1, \-1
=> 1
\-1
.
.fi
.
@@ -867,7 +881,7 @@ The builtin function \fBabs\fR is defined naively as: \fBif \. < 0 then \- \. el
For numeric input, this is the absolute value\. See the section on the identity filter for the implications of this definition for numeric input\.
.
.P
To compute the absolute value of a number as a floating point number, you may wish use \fBfabs\fR\.
To compute the absolute value of a number as a floating point number, you may wish to use \fBfabs\fR\.
.
.IP "" 4
.
@@ -908,7 +922,11 @@ It is an error to use \fBlength\fR on a \fBboolean\fR\.
jq \'\.[] | length\'
[[1,2], "string", {"a":2}, null, \-5]
=> 2, 6, 1, 0, 5
=> 2
6
1
0
5
.
.fi
.
@@ -988,7 +1006,8 @@ The builtin function \fBin\fR returns whether or not the input key is in the giv
jq \'\.[] | in({"foo": 42})\'
["foo", "bar"]
=> true, false
=> true
false
jq \'map(in([0,1]))\'
[2, 0]
@@ -1263,7 +1282,8 @@ It\'s useful on occasion\. You\'ll know if you need it :)
jq \'1, empty, 2\'
null
=> 1, 2
=> 1
2
jq \'[1,2,empty,3]\'
null
@@ -1486,7 +1506,8 @@ The three argument form generates numbers \fBfrom\fR to \fBupto\fR with an incre
jq \'range(2; 4)\'
null
=> 2, 3
=> 2
3
jq \'[range(2; 4)]\'
null
@@ -1551,7 +1572,8 @@ The \fBtonumber\fR function parses its input as a number\. It will convert corre
jq \'\.[] | tonumber\'
[1, "1"]
=> 1, 1
=> 1
1
.
.fi
.
@@ -1566,7 +1588,10 @@ The \fBtoboolean\fR function parses its input as a boolean\. It will convert cor
jq \'\.[] | toboolean\'
["true", "false", true, false]
=> true, false, true, false
=> true
false
true
false
.
.fi
.
@@ -1581,7 +1606,9 @@ The \fBtostring\fR function prints its input as a string\. Strings are left unch
jq \'\.[] | tostring\'
[1, "1", [1]]
=> "1", "1", "[1]"
=> "1"
"1"
"[1]"
.
.fi
.
@@ -1617,11 +1644,13 @@ Currently most arithmetic operations operating on infinities, NaNs, and sub\-nor
jq \'\.[] | (infinite * \.) < 0\'
[\-1, 1]
=> true, false
=> true
false
jq \'infinite, nan | type\'
null
=> "number", "number"
=> "number"
"number"
.
.fi
.
@@ -1919,11 +1948,17 @@ Outputs all combinations of the elements of the arrays in the input array\. If g
jq \'combinations\'
[[1,2], [3, 4]]
=> [1, 3], [1, 4], [2, 3], [2, 4]
=> [1, 3]
[1, 4]
[2, 3]
[2, 4]
jq \'combinations(2)\'
[0, 1]
=> [0, 0], [0, 1], [1, 0], [1, 1]
=> [0, 0]
[0, 1]
[1, 0]
[1, 1]
.
.fi
.
@@ -1984,7 +2019,7 @@ jq \'[\.[]|trimstr("foo")]\'
\fBrtrim\fR trims only trailing (right side) whitespace\.
.
.P
Whitespace characters are the usual \fB" "\fR, \fB"\en"\fR \fB"\et"\fR, \fB"\er"\fR and also all characters in the Unicode character database with the whitespace property\. Note that what considers whitespace might change in the future\.
Whitespace characters are the usual \fB" "\fR, \fB"\en"\fR \fB"\et"\fR, \fB"\er"\fR and also all characters in the Unicode character database with the whitespace property\. Note that what is considered whitespace might change in the future\.
.
.IP "" 4
.
@@ -1992,7 +2027,9 @@ Whitespace characters are the usual \fB" "\fR, \fB"\en"\fR \fB"\et"\fR, \fB"\er"
jq \'trim, ltrim, rtrim\'
" abc "
=> "abc", "abc ", " abc"
=> "abc"
"abc "
" abc"
.
.fi
.
@@ -2047,10 +2084,10 @@ jq \'split(", ")\'
.IP "" 0
.
.SS "join(str)"
Joins the array of elements given as input, using the argument as separator\. It is the inverse of \fBsplit\fR: that is, running \fBsplit("foo") | join("foo")\fR over any input string returns said input string\.
Joins the values from the input array or object, using the argument as separator\. It is the inverse of \fBsplit\fR: that is, running \fBsplit("foo") | join("foo")\fR over any input string returns said input string\.
.
.P
Numbers and booleans in the input are converted to strings\. Null values are treated as empty strings\. Arrays and objects in the input are not supported\.
Numbers and booleans in the input are converted to strings\. Null values are treated as empty strings\. When the input is an object, \fBjoin\fR operates on the values that \fB\.[]\fR produces\. Arrays and objects among the joined values are not supported\.
.
.IP "" 4
.
@@ -2063,6 +2100,10 @@ jq \'join(", ")\'
jq \'join(" ")\'
["a",1,2\.3,true,null,false]
=> "a 1 2\.3 true false"
jq \'join(", ")\'
{"a":1,"b":2}
=> "1, 2"
.
.fi
.
@@ -2187,15 +2228,23 @@ The recursive calls in \fBrecurse\fR will not consume additional memory whenever
jq \'recurse(\.foo[])\'
{"foo":[{"foo": []}, {"foo":[{"foo":[]}]}]}
=> {"foo":[{"foo":[]},{"foo":[{"foo":[]}]}]}, {"foo":[]}, {"foo":[{"foo":[]}]}, {"foo":[]}
=> {"foo":[{"foo":[]},{"foo":[{"foo":[]}]}]}
{"foo":[]}
{"foo":[{"foo":[]}]}
{"foo":[]}
jq \'recurse\'
{"a":0,"b":[1]}
=> {"a":0,"b":[1]}, 0, [1], 1
=> {"a":0,"b":[1]}
0
[1]
1
jq \'recurse(\. * \.; \. < 20)\'
2
=> 2, 4, 16
=> 2
4
16
.
.fi
.
@@ -2453,10 +2502,22 @@ jq \'@base64d\'
jq provides some basic date handling functionality, with some high\-level and low\-level builtins\. In all cases these builtins deal exclusively with time in UTC\.
.
.P
The \fBfromdateiso8601\fR builtin parses datetimes in the ISO 8601 format to a number of seconds since the Unix epoch (1970\-01\-01T00:00:00Z)\. The \fBtodateiso8601\fR builtin does the inverse\.
The \fBfromdateiso8601\fR builtin parses datetimes in the ISO 8601 format to a number of seconds since the Unix epoch (1970\-01\-01T00:00:00Z)\. The \fBtodateiso8601\fR builtin formats a number of seconds as \fB"%Y\-%m\-%dT%H:%M:%SZ"\fR\.
.
.P
The \fBfromdate\fR builtin parses datetime strings\. Currently \fBfromdate\fR only supports ISO 8601 datetime strings, but in the future it will attempt to parse datetime strings in more formats\.
\fBfromdateiso8601\fR accepts a complete date, optionally followed by a time of day, written in either the extended representation, which separates the components, or the basic representation, which does not\. The two cannot be mixed within one datetime\. The date may be a calendar date (\fB2015\-03\-05\fR, \fB20150305\fR), an ordinal date (\fB2015\-064\fR, \fB2015064\fR), or a week date (\fB2015\-W10\-4\fR, \fB2015W104\fR); all three denote the same day\. Years outside the range 0000 to 9999 are written with a sign and six digits, as in \fB+012015\-03\-05\fR\.
.
.P
The time of day may omit its seconds, or its minutes and seconds, as in \fB2015\-03\-05T23:51Z\fR and \fB2015\-03\-05T23Z\fR, or be left out altogether, in which case the value is midnight UTC\. It may carry a fractional part after a \fB\.\fR or a \fB,\fR, which belongs to the lowest component present, so \fB23,5\fR is half past 23\. It may be followed by an offset from UTC written as \fBZ\fR, \fB+hh\fR, \fB+hh:mm\fR or \fB+hhmm\fR; a datetime with no offset is read as UTC\. A time of \fB24:00:00\fR denotes midnight of the following day, and a leap second is read as the second before it, since jq counts every day as 86400 seconds\.
.
.P
The \fBW\fR, \fBT\fR and \fBZ\fR designators may also be written in lower case, which ISO 8601 permits where upper case is not available\. RFC 3339 additionally allows the date and the time to be separated by a space instead of a \fBT\fR "for the sake of readability", which jq accepts too\. The offset may use the other representation\'s separator style, as in \fB2015\-03\-05T23:51:47+0900\fR, although ISO 8601 does not allow the basic and extended representations to be mixed\.
.
.P
A complete date is required, so \fB2015\fR and \fB2015\-03\fR are errors even though ISO 8601 defines them as dates, and \fBT23:51:47\fR is an error because a time of day on its own is not a point in time\. Dates that do not exist, such as \fB2015\-02\-30\fR or \fB2016\-W53\-1\fR, are errors too, as is \fB2015\-03\-05Z\fR, since a zone designator belongs to the time of day\.
.
.P
The \fBfromdate\fR builtin is an alias for \fBfromdateiso8601\fR\.
.
.P
The \fBtodate\fR builtin is an alias for \fBtodateiso8601\fR\.
@@ -2483,7 +2544,7 @@ The \fBstrptime(fmt)\fR builtin parses input strings matching the \fBfmt\fR argu
The \fBstrftime(fmt)\fR builtin formats a time (GMT) with the given format\. The \fBstrflocaltime\fR does the same, but using the local timezone setting\.
.
.P
The format strings for \fBstrptime\fR and \fBstrftime\fR are described in typical C library documentation\. The format string for ISO 8601 datetime is \fB"%Y\-%m\-%dT%H:%M:%SZ"\fR\.
The format strings for \fBstrptime\fR and \fBstrftime\fR are described in typical C library documentation\. \fB"%Y\-%m\-%dT%H:%M:%SZ"\fR is the format that \fBtodateiso8601\fR produces; it is only one of the ISO 8601 representations that \fBfromdateiso8601\fR accepts, and \fBstrptime\fR cannot parse the others \-\- there is no portable format specifier for week dates or for fractional seconds\.
.
.P
jq may not support some or all of this date functionality on some systems\. In particular, the \fB%u\fR and \fB%j\fR specifiers for \fBstrptime(fmt)\fR are not supported on macOS\.
@@ -2496,6 +2557,14 @@ jq \'fromdate\'
"2015\-03\-05T23:51:47Z"
=> 1425599507
jq \'fromdateiso8601\'
"2015\-03\-06T08:51:47\.25+09:00"
=> 1425599507\.25
jq \'map(fromdateiso8601)\'
["20150305T235147Z","2015\-064T23:51:47Z","2015\-W10\-4T23:51:47Z"]
=> [1425599507,1425599507,1425599507]
jq \'strptime("%Y\-%m\-%dT%H:%M:%SZ")\'
"2015\-03\-05T23:51:47Z"
=> [2015,2,5,23,51,47,4,63]
@@ -2572,7 +2641,10 @@ jq \'\. == {"b": {"d": (4 + 1e\-20), "c": 3}, "a":1}\'
jq \'\.[] == 1\'
[1, 1\.0, "1", "banana"]
=> true, true, false, false
=> true
true
false
false
.
.fi
.
@@ -2651,11 +2723,15 @@ jq \'42 and "a string"\'
jq \'(true, false) or false\'
null
=> true, false
=> true
false
jq \'(true, true) and (true, false)\'
null
=> true, false, true, false
=> true
false
true
false
jq \'[true, false | not]\'
null
@@ -2699,7 +2775,9 @@ jq \'(false, null, 1) // 42\'
jq \'(false, null, 1) | \. // 42\'
null
=> 42, 42, 1
=> 42
42
1
.
.fi
.
@@ -2929,7 +3007,8 @@ jq \'test("foo")\'
jq \'\.[] | test("a b c # spaces are ignored"; "ix")\'
["xabcd", "ABC"]
=> true, true
=> true
true
.
.fi
.
@@ -2978,7 +3057,8 @@ Capturing groups that did not match anything return an offset of \-1
jq \'match("(abc)+"; "g")\'
"abc abc"
=> {"offset": 0, "length": 3, "string": "abc", "captures": [{"offset": 0, "length": 3, "string": "abc", "name": null}]}, {"offset": 4, "length": 3, "string": "abc", "captures": [{"offset": 4, "length": 3, "string": "abc", "name": null}]}
=> {"offset": 0, "length": 3, "string": "abc", "captures": [{"offset": 0, "length": 3, "string": "abc", "name": null}]}
{"offset": 4, "length": 3, "string": "abc", "captures": [{"offset": 4, "length": 3, "string": "abc", "name": null}]}
jq \'match("foo")\'
"foo bar foo"
@@ -2986,11 +3066,13 @@ jq \'match("foo")\'
jq \'match(["foo", "ig"])\'
"foo bar FOO"
=> {"offset": 0, "length": 3, "string": "foo", "captures": []}, {"offset": 8, "length": 3, "string": "FOO", "captures": []}
=> {"offset": 0, "length": 3, "string": "foo", "captures": []}
{"offset": 8, "length": 3, "string": "FOO", "captures": []}
jq \'match("foo (?<bar123>bar)? foo"; "ig")\'
"foo bar foo foo foo"
=> {"offset": 0, "length": 11, "string": "foo bar foo", "captures": [{"offset": 4, "length": 3, "string": "bar", "name": "bar123"}]}, {"offset": 12, "length": 8, "string": "foo foo", "captures": [{"offset": \-1, "length": 0, "string": null, "name": "bar123"}]}
=> {"offset": 0, "length": 11, "string": "foo bar foo", "captures": [{"offset": 4, "length": 3, "string": "bar", "name": "bar123"}]}
{"offset": 12, "length": 8, "string": "foo foo", "captures": [{"offset": \-1, "length": 0, "string": null, "name": "bar123"}]}
jq \'[ match("\."; "g")] | length\'
"abc"
@@ -3024,11 +3106,14 @@ Emit a stream of the non\-overlapping substrings of the input that match the reg
jq \'scan("c")\'
"abcdefabc"
=> "c", "c"
=> "c"
"c"
jq \'scan("(a+)(b+)")\'
"abaabbaaabbb"
=> ["a","b"], ["aa","bb"], ["aaa","bbb"]
=> ["a","b"]
["aa","bb"]
["aaa","bbb"]
.
.fi
.
@@ -3061,11 +3146,17 @@ These provide the same results as their \fBsplit\fR counterparts, but as a strea
jq \'splits(", *")\'
"ab,cd, ef, gh"
=> "ab", "cd", "ef", "gh"
=> "ab"
"cd"
"ef"
"gh"
jq \'splits(",? *"; "n")\'
"ab,cd ef, gh"
=> "ab", "cd", "ef", "gh"
=> "ab"
"cd"
"ef"
"gh"
.
.fi
.
@@ -3116,7 +3207,7 @@ Variables are an absolute necessity in most programming languages, but they\'re
In most languages, variables are the only means of passing around data\. If you calculate a value, and you want to use it more than once, you\'ll need to store it in a variable\. To pass a value to another part of the program, you\'ll need that part of the program to define a variable (as a function parameter, object member, or whatever) in which to place the data\.
.
.P
It is also possible to define functions in jq, although this is is a feature whose biggest use is defining jq\'s standard library (many jq functions such as \fBmap\fR and \fBselect\fR are in fact written in jq)\.
It is also possible to define functions in jq, although this is a feature whose biggest use is defining jq\'s standard library (many jq functions such as \fBmap\fR and \fBselect\fR are in fact written in jq)\.
.
.P
jq has reduction operators, which are very powerful but a bit tricky\. Again, these are mostly used internally, to define some useful bits of jq\'s standard library\.
@@ -3215,7 +3306,7 @@ Multiple variables may be declared using a single \fBas\fR expression by providi
.IP "" 0
.
.P
The variable declarations in array patterns (e\.g\., \fB\. as [$first, $second]\fR) bind to the elements of the array in from the element at index zero on up, in order\. When there is no value at the index for an array pattern element, \fBnull\fR is bound to that variable\.
The variable declarations in array patterns (e\.g\., \fB\. as [$first, $second]\fR) bind to the elements of the array from the element at index zero on up, in order\. When there is no value at the index for an array pattern element, \fBnull\fR is bound to that variable\.
.
.P
Variables are scoped over the rest of the expression that defines them, so
@@ -3267,7 +3358,9 @@ jq \'\. as [$a, $b, {c: $c}] | $a + $b + $c\'
jq \'\.[] as [$a, $b] | {a: $a, b: $b}\'
[[0], [0, 1], [2, 1, 0]]
=> {"a":0,"b":null}, {"a":0,"b":1}, {"a":2,"b":1}
=> {"a":0,"b":null}
{"a":0,"b":1}
{"a":2,"b":1}
.
.fi
.
@@ -3340,11 +3433,13 @@ Additionally, if the subsequent expression returns an error, the alternative ope
jq \'\.[] as {$a, $b, c: {$d, $e}} ?// {$a, $b, c: [{$d, $e}]} | {$a, $b, $d, $e}\'
[{"a": 1, "b": 2, "c": {"d": 3, "e": 4}}, {"a": 1, "b": 2, "c": [{"d": 3, "e": 4}]}]
=> {"a":1,"b":2,"d":3,"e":4}, {"a":1,"b":2,"d":3,"e":4}
=> {"a":1,"b":2,"d":3,"e":4}
{"a":1,"b":2,"d":3,"e":4}
jq \'\.[] as {$a, $b, c: {$d}} ?// {$a, $b, c: [{$e}]} | {$a, $b, $d, $e}\'
[{"a": 1, "b": 2, "c": {"d": 3, "e": 4}}, {"a": 1, "b": 2, "c": [{"d": 3, "e": 4}]}]
=> {"a":1,"b":2,"d":3,"e":null}, {"a":1,"b":2,"d":null,"e":4}
=> {"a":1,"b":2,"d":3,"e":null}
{"a":1,"b":2,"d":null,"e":4}
jq \'\.[] as [$a] ?// [$b] | if $a != null then error("err: \e($a)") else {$a,$b} end\'
[[3]]
@@ -3427,6 +3522,23 @@ def addvalue($f): \.\.\.;
With either definition, \fBaddvalue(\.foo)\fR will add the current input\'s \fB\.foo\fR field to each element of the array\. Do note that calling \fBaddvalue(\.[])\fR will cause the \fBmap(\. + $f)\fR part to be evaluated once per value in the value of \fB\.\fR at the call site\.
.
.P
Multiple arguments are separated by semicolons, both in the definition and in the call:
.
.IP "" 4
.
.nf
def f(a; b): \.\.\.;
f(\.x; \.y)
.
.fi
.
.IP "" 0
.
.P
A comma does not separate arguments\. \fBf(\.x, \.y)\fR calls a one\-argument \fBf\fR with the single filter \fB\.x, \.y\fR, which outputs \fB\.x\fR and then \fB\.y\fR (see the comma operator above)\.
.
.P
Multiple definitions using the same function name are allowed\. Each re\-definition replaces the previous one for the same number of function arguments, but only for references from functions (or main program) subsequent to the re\-definition\. See also the section below on scoping\.
.
.IP "" 4
@@ -3440,6 +3552,14 @@ jq \'def addvalue(f): \. + [f]; map(addvalue(\.[0]))\'
jq \'def addvalue(f): f as $x | map(\. + $x); addvalue(\.[0])\'
[[1,2],[10,20]]
=> [[1,2,1,2], [10,20,1,2]]
jq \'def f(a; b): [a, b]; f(\.x; \.y)\'
{"x":1,"y":2}
=> [1,2]
jq \'def f(a): [a]; f(\.x, \.y)\'
{"x":1,"y":2}
=> [1,2]
.
.fi
.
@@ -3624,15 +3744,25 @@ When \fBEXTRACT\fR is omitted, the identity filter is used\. That is, it outputs
jq \'foreach \.[] as $item (0; \. + $item)\'
[1,2,3,4,5]
=> 1, 3, 6, 10, 15
=> 1
3
6
10
15
jq \'foreach \.[] as $item (0; \. + $item; [$item, \. * 2])\'
[1,2,3,4,5]
=> [1,2], [2,6], [3,12], [4,20], [5,30]
=> [1,2]
[2,6]
[3,12]
[4,20]
[5,30]
jq \'foreach \.[] as $item (0; \. + 1; {index: \., $item})\'
["foo", "bar", "baz"]
=> {"index":1,"item":"foo"}, {"index":2,"item":"bar"}, {"index":3,"item":"baz"}
=> {"index":1,"item":"foo"}
{"index":2,"item":"bar"}
{"index":3,"item":"baz"}
.
.fi
.
@@ -3685,7 +3815,10 @@ All jq functions can be generators just by using builtin generators\. It is also
jq \'def range(init; upto; by): def _range: if (by > 0 and \. < upto) or (by < 0 and \. > upto) then \., ((\.+by)|_range) else empty end; if init == upto then empty elif by == 0 then init else init|_range end; range(0; 10; 3)\'
null
=> 0, 3, 6, 9
=> 0
3
6
9
jq \'def while(cond; update): def _while: if cond then \., (update | _while) else empty end; _while; [while(\.<100; \.*2)]\'
1
@@ -3839,7 +3972,8 @@ Consumes a number as input and truncates the corresponding number of path elemen
jq \'truncate_stream([[0],"a"],[[1,0],"b"],[[1,0]],[[1]])\'
1
=> [[0],"b"], [[0]]
=> [[0],"b"]
[[0]]
.
.fi
.
@@ -3906,6 +4040,9 @@ This is the "update" operator \fB|=\fR\. It takes a filter on the right\-hand si
The left\-hand side can be any general path expression; see \fBpath()\fR\.
.
.P
The right\-hand side of \fB|=\fR is run with the value at the path as its input, not with \fB\.\fR\. This is what sets it apart from plain assignment (\fB=\fR) and the arithmetic update\-assignment operators such as \fB+=\fR, whose right\-hand side is run with \fB\.\fR\. For example, \fB\.a |= \.b\fR sets \fB\.a\fR to the \fBb\fR field of \fB\.a\fR, while \fB\.a = \.b\fR and \fB\.a += \.b\fR use the \fBb\fR field of \fB\.\fR\.
.
.P
Note that the left\-hand side of \fB|=\fR refers to a value in \fB\.\fR\. Thus \fB$var\.foo |= \. + 1\fR won\'t work as expected (\fB$var\.foo\fR is not a valid or useful path expression in \fB\.\fR); use \fB$var | \.foo |= \. + 1\fR instead\.
.
.P
@@ -3918,6 +4055,14 @@ If the right\-hand side outputs multiple values, only the first one will be used
.
.nf
jq \'\.foo |= \. + 1\'
{"foo": 41, "bar": "unchanged"}
=> {"foo": 42, "bar": "unchanged"}
jq \'\.user\.age |= \. + 1\'
{"user": {"name": "alice", "age": 30}, "active": true}
=> {"user": {"name": "alice", "age": 31}, "active": true}
jq \'(\.\.|select(type=="boolean")) |= if \. then 1 else 0 end\'
[true,false,[5,true,[true,[false]],false]]
=> [1,0,[5,1,[1,[0]],0]]
@@ -3927,7 +4072,10 @@ jq \'(\.\.|select(type=="boolean")) |= if \. then 1 else 0 end\'
.IP "" 0
.
.SS "Arithmetic update\-assignment: +=, \-=, *=, /=, %=, //="
jq has a few operators of the form \fBa op= b\fR, which are all equivalent to \fBa |= \. op b\fR\. So, \fB+= 1\fR can be used to increment values, being the same as \fB|= \. + 1\fR\.
jq has a few operators of the form \fBa op= b\fR, which are all equivalent to \fB(b as $b | a |= \. op $b)\fR\. So, \fB+= 1\fR can be used to increment values, being the same as \fB|= \. + 1\fR\.
.
.P
Note that the right\-hand side \fBb\fR is evaluated with the same input as the left\-hand side, not with the value at the path being updated\. So \fB\.a += \.b\fR adds the value of \fB\.b\fR to \fB\.a\fR, whereas \fB\.a |= \. + \.b\fR would look up \fB\.b\fR inside the value of \fB\.a\fR\. If \fBb\fR outputs multiple values, then \fBa op= b\fR outputs one result for each of them\.
.
.IP "" 4
.
@@ -3936,6 +4084,15 @@ jq has a few operators of the form \fBa op= b\fR, which are all equivalent to \f
jq \'\.foo += 1\'
{"foo": 42}
=> {"foo": 43}
jq \'\.a += \.b\'
{"a": 1, "b": 2}
=> {"a": 3, "b": 2}
jq \'\.a += (1,2)\'
{"a": 0}
=> {"a": 1}
{"a": 2}
.
.fi
.
@@ -3993,7 +4150,9 @@ jq \'\.a |= \.b\'
jq \'(\.a, \.b) = range(3)\'
null
=> {"a":0,"b":0}, {"a":1,"b":1}, {"a":2,"b":2}
=> {"a":0,"b":0}
{"a":1,"b":1}
{"a":2,"b":2}
jq \'(\.a, \.b) |= range(3)\'
null
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1YACgkQsNpg+0VL
rxgIQA//S9rRZNMEU9lHvS2XNqpCA5LGWS9z0mXAGHEW9fLtSxZywoaEcaKv9BvS
LTttVKRsX2ucsP3i6w7BJIa4MfnTdye7QrbDsgmpNQISiTU/ZbXsAS/TyN/eSo5Z
Jk3iQH4AoAUWU+E82JlR6D6VAzx8FFTEnzauE+HnetOctKBXwb/jMM6USNYTXaD7
ZBzqkGyoCW7iOjrA+FIMpKbZN8uvf1aAiv+Oudj2Wb7724dhHcg9IgJIyBT7r3na
6A6Y1fuUE3AX5Ig88Aq25CcYpMPAUpQBrqjxnVr8yyw5PcOMI+BO8HBXtdcv/ksI
dflkhze8X+vdlZ92QkkGiWSKUlKUICePe8MNT0GVFpN91Mr5VA6meS6GFuCYjNMK
W6/8K2pafHqR5/gpSapxxy/qdUfIYw3ZRE0ByxA3A1XWzyFq9wcm8/mKwizqTsb3
LQLwbsxx/setaOcB68d0wUgqEIFe5PRzz9GicUtoyB2xMjuqJfyd9B/9rF89Wgoi
Fevqxdip7w8dTzHmlQWwmbluyW7E11nUom/hfta7QDDnTOkURKKvvxmv3OYqds6x
tu5G+EC41motxZfhIatHjGDhIqPo/1T8jFXael663VTULYMXvC0hCm/qJV/Q2OB8
q3fVFT6BWIa1IOXwgah5FMRH5Q7qJP2/hVXHkE87jMbhJvzt1nQ=
=x2Gw
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1cACgkQsNpg+0VL
rxgB4Q/+NLkJEnS6mEeZAopBPH18NpYQbhDTCcIKhelPJ44q5yZtDVM0xLHZsk/W
CTnkTH8ZtJ20GuVLgXggc1IvE1XC8MShK5ndZP8so8/BBsA/Zvheq4l8XUUY5pup
o3RVFeFMkwmFlvnRgvLkZMnFFEcFO24Maeme5DJVfIn35WnLWvot4mSlnqaDb6DR
hQwnI6+GA0GGDxj0FNSugrywDnCvtHeQvZdQNtaI2KVgKDLfsij33781sPhyl5jr
AgNK8bDETYyAj/SixYrXU017Sl582RMcz55A4l2WTKkj+BXEFftfagHyaw6vuHud
PBFRiUjDnGiQd1OydF6J00/ydNxTmcx7ADLqkP+mHYoBejAL2jIf/dcdeIELaa0+
hT15Crgq8+JY3fDrri/oR79CBh9SRZ5Lo79fnLTaly9OM2yrJNfd3+tar99j2ysa
s8QFZgke5lQyPe7ljNAV2w0n4rnXVWRpQ+a/XybfPUeffWqS121Xm//huQWtcgEY
Zabau9YcSF0IHt2VPMQXz15RCtBSgTywb0YPgfqgRDCSlaC9wMuDTqc8STU/MUnc
INssJTUMcwk0694/zt8kRl90/ds2lNelqvpr+d9wtBa9oacelobTpCEyyblYYJgd
EyC6OnEQZeDnr+41aXhBa9bVsO+tb2VQTH46wytfNUvM1mBKXps=
=8Jj2
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1cACgkQsNpg+0VL
rxjxjg//UMgxAgmZ0WL4taeo12YMs8PGaWN/rLvEBGntm+c2mYp9c6WHwiuUzn9e
KG/yUk3GSuKu/pTtVh1Y8NpOw5VUuGuod19o6Dwjy7yD9Y5Bh48eR1JJYUl0UcEz
nxP5draj59BRElxlx7asPGw3vTfWHaBIYtIpzunEm+c2mB1JQBRlwosxOnQggOmJ
t7G5xdfKb0jkt8dVDRVZ1p9XCgW/qKbKVC1uCUyCF9p4MjuhL03wZ7sMsmN5mRk4
x6P1tidD9mitqG81CIl8GyMVZRURBh8njYGknu9vVZyaNhgG6pxdr8vEytHmRSbw
kfCHb5RkIyMEMJ09SZGcnDk6lrof/PFOmi9c5rzqkgxIKZEbeM7RpQdAfjz+j+pT
VMhBzCBjAWBsSEQEBpp9wpRh9/lStEcqhVuQ2ZZJo6mcpgItdvC3QSAv2mERoFo5
6c/vvx5MRW9sHs6Zwip7KxkANIyxkIkXxzy0UgP5NSPyzx2Sf7dw9a56S5UM/GqA
PCJxcaDt8h/ZPVuo0/2VIgjKF2+Ds7scTls2sN0MPoQ4OZhCfGQzUFOIrpopyDsd
7r6AWjjbvc4bbQ3EC5bQdGiCt8RH7i5BqfZJs5J3pUpNdCbHwQPpkJrj9gU3+MS8
0hQLgV1KiNke1WV1LBj9WjZEKLf13iXy6nPE/ugTQWnj0V/20JI=
=oVlS
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1cACgkQsNpg+0VL
rxi9TQ//Yx5iMz3lAd5BYoScwvnrlvR07DmkNi8qHQaGyVjjxBiSKr1mbMSolisz
K+m+6fOZDU81vO7MumQ0kn63mqTXkTsHP8MGVHMjEn+1tWfbANXmLXC0B/Qpvf8y
ZQQqJgxK88BZ4gXHQvOWoJ0hqvxYsEaLc2SZ5x+g8WUAf6RCUKjrWHGyXcCQVpQY
vxJTztD74wIcofs+14zPd2PtSxw1wBscHbxLtyH5KLrfgUsM7BrGdBeL2h022Kvs
p8oS2pqpSUUvTTbZTNuu64dsqfWVjMWhpiQhVHRVnEJ6HD+E/Paq0dUXr/g/Hdwk
DpzZ/PH75e5z2+1eWuFtyo5RlQhIgKkiv+Dt8rv7Xws48Do0jIicdlBkiNOyPrq/
UwC05sswWUM5+IDU6YviX/spLGTz4aucIx3DW2xWQE74z5kNjMbLv+ABEOUv1pMs
93y0ndLH0UdnA6TsVfwwyBkjkCqGqdsY4LOmOior6KFWnXd8b9vFOzw7LUKPBfri
o0l68lnwij9QLwRuwpAIoi+eBRA2whG8iLaUb57BoL05S+B0dKJAloMR8v+YI7Hq
yAApbLe7MVcxxgZejOsYgXlLLQBvlUMDQ3KZNOp4NcVChN2DuX0On5Vk7eAJG82R
I867FgTntoSwagrcr0Tq2nyP/5W9KUvx4fA6Q2TnACZ6/1XZLBo=
=ZR9a
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1cACgkQsNpg+0VL
rxgJBA//dsxmaX4oL+fVI1tf2XAM8ZmNboLyHdP+P7lnylExczc2VirWC633Hz7a
M5pylUBptX3mHucGIsqhzpRA1434/JoF63GZXOcS/ZP9TmtpRyuLm/VwmK3kLZbY
nFKMcUWpLHSqwbI4xOltHizOsqZyJYfpd1B+1EEQ9RcZ0QZol1uz8Cvnm6z43lh4
PtlhEOys39Yy61QibIzfgty1fRnsm0jcgfKVOVpoNjs1YJMxufVbuu4i+oTZT1Yl
Tlzh2Pee9nN7nKuX0K1DbyaRoSTkAGcJ4q+w4ne3RPnGp2BL2U9TtDbNiiq8+WrK
qvisNm6x37Po/jOKsV09f0vEKxZwj2SpJCesNpiVj28tKyj8oKKtUXA8YVToTBZp
GXDvG2L3cu4u83f40+n7ZvryVMLL4ZHo5FtFlR2czawhVtkHVJRJtyhuYG3JwciX
7p9wxVbRqpXnnXjRzEe96J9VdqCeu4yIFGClvTOrD3IROEFvsgV37yj+ZxZRAPiG
kl8snWruvBEPHHIdhvnV5zxKeKVXXYCZ3mCvbHwL9nun0DI7DPP5FUFZpEzlspms
JvM0ln7XKtjdYPaPOLcfht54QJOgzWDMi38HYyRwLp2tsdB1vOPqt12l0CDzy4Ua
L/WBGBaZZ299xFvuc61jPAFVJTMsy2S3Nf5+TXrQCKQ3WanNOAw=
=r6R0
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1gACgkQsNpg+0VL
rxikAxAAqjv54fn/DyoLr0JdTZimbxrXxZgTve86UuODx40WoK26aQm620aHcc/1
X5i6fS8VSaAs+rkLaE0LjT+juU6mBxBCD2K7qgugiIaUiCUckm+gnJISxDD+cixm
nvep04IPO2F7E/PFROL3K7hhP8oG2tR6K7pIf0N/KrQFA8MS3A4DA3o/tYpUx6ML
PNE2lnGTi/27In2YMoBPQBX6oO/Z6q54cG12QG4dGbQl2Ncje9fQY2dstIEZMUkg
VprB1JUz3lBLVKMbeR3qqg74Xh+z/5BxOraS3KV47PMMo9uT6Q2ZrWgg40pj7F/Y
m7WmtCk8hUTSiTJPLwpYzqujWunx+GjL2KMmRKgCMFXap95YGZ7NPP8GLSNswTL8
Md63WeZjPBbY10kNfH2OkQEkyobTOWnzVDRAR8Lqgh2Kwxzi20l1Hub8FNdWKUut
fNvm9LkOXoVZrfGeCH05Sd0a7yn+usqM7j1Z22VWq0MONtpt/w5HLzzuVP7A8TfO
5uxHnLFF2gG5oqgoW2wTcrFAPT/1g2UpPmZEBfXNIFOuHL+31PuR1hO78dD9WoEv
C28R5oda2awGh8xEvH4jt8k0VrTOw2w49WFUvoi/VaBeh1HXdmZ16P3S3ReLNmV3
5SvXkjHaTU8J6JU078X1vvS+XqVu/fALcQsOYFVJc0fBe87WP98=
=LV9M
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1gACgkQsNpg+0VL
rxgxQA//cDM3EXMozRtSAxz7VvNlVIQ70TweSQHYOEEqBnlIfxrG4Aa7YRkvg07Z
Zyt4cJwB0kqpCC9hzW+huKEeEEFvQyx1nopc5rxipBATypD8LUCGvQb78jZgzgEx
VglAcyOVU5c/AfJ1W52DKxz3ZWEwH0LG9Xcq7JfpY+pKDtQZFEsTQalmzKaKbREo
Gp0zeDaVkzE/azym+2W2BPkZXGUZONl1N/AiYRtPoxyZ8TFIV3Ti5OW8x1TTrNHI
zAOWL90t13c4hjRxGY52Mr2R5zBKGJT8UI5+cc8OXP6yp2t15J8KNNil37mRCTl5
ZYDeAOp/OMKx9p4ZO/8UP+JKCZQj4/1I7NEjgiVeN4lLLAqcYsuZL6+QAj79VjD5
1hqrKTWoeDMuT3gJ49SIrS9ncgxkdWOI9LCVQ/k+U31KVfWODKGeizzM4cVuq4In
gnFelLPNxTlV0RuHEgxw5s5RicrVsDoozQJImAkgEPAQeBIYByvdicbjH3aDAylr
WB7Upl7j9p2ELcy7uVXkLXL6tCBjEdmnIHSdEqPW0v+puhwUS5TpD59eXDcI3y8T
Geos92K8vg9NQ2mJqXh5TNDJBjB24aMgIKGl+BD5x++yJ3PiAM2Z/8OXWTZpj/t1
3MHwHSb22HrRrMxpz9i3WJmhcpNq2rg/yejPVWNEYHqlv39ri6Q=
=8FaE
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1gACgkQsNpg+0VL
rxizrQ/+LPss58IqvpP95b/cnzSxaphCUTTEflNYs7dnqCfr6fZ9V59EYer/a8+j
wIfCV1oz+Apt4xmDTFjqjDH+TAImuaXhU+pZ97/OUqM2esPwwLcuJxXyxLbsQ/rz
IzpCnaeDdjQL8SGe+TPGvJ1w76hkzFZU0zQUMJOol6qpV8pLA/3nVTwc0HdSY4IM
FFZp3roP7rVrBuOJ7HUON1ZHdFRNBUvlTIm/dh+3i6ZjSZa2T3q2TaPH0ZgegsWJ
wAocQ0FxYGGFPyMApzGno/ZFVOrDihLAgv6wIU+1F74iteAj541GmCi7/MecXZzf
cIsXvhdePEfbFXpXuz2YITDYUh1KnpoLigI4F2MDn9vYnlTChVjfVLD+aKdQr8OV
X6rvpDLe8BFsM5gosq0gRoUoK5sEwgh3sfyy89a1+5aPsTgznHHAl1SmUF5vgMxt
3/QhFVTbigG2mC+5FbIDy4GBfbys7EphvKgTQACeUybFNNu+ikYshexmiOr89o6j
f3n7WZ35uyQknBIRtR0VvoSyPX4p9N7GiTQLJXFO+QYG9WkNQGQJhuIC9HVJ0Xwl
Baw6zc8hsht3gKx76zjFzXf835f/aYh6yIA4bRwhk8O80Bb4pf6/W3vuWIw59dqZ
XKgc4KxINaJkrXuOwN4fGJqPhxSoNRnm+eXE7WnV9Wo+kSPd8hk=
=Gk/l
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1gACgkQsNpg+0VL
rxg5HQ//ZWHj0/D1CXMKVFh7GAjUQcq5ndnNwVuPLwnsCGf90NZYRlvYbAzfg6Jn
Dp6FStjpOC/uhrXTHUv2q0UVzDOz/AxrGd9Nglowa4IPMEi6mQpVO+IFcogt5Fsy
fbtqJUyZROZV4F6rXy+ZQzznEZoG0lbm27iWNpws8oOPkE5UJxi/IeHAywvB2PnP
KdV9o7PDTzS7GA+jJ8LVIEWWJpYhZdib3P9ZvxdqZc901eEVSvHo7vtlUBdnwGSA
m/GPrJYH1/fBamBYnpVcVioMbujGc3exH0E3YgkOBtPaqhbBu9qWiM2EV9lxY8fo
2Xr7RijgvmnLh34/R045A1mVF9IEKW8ehIgGMRLPqNWgPiN9bYL2z9jAEoIR0Cp6
yZSY2VhfkXTy42HeQSCJLMfT90m1hX7YIPo/qaDRaOU9zNeEYuHnHCQ+HKo5hEjL
ORlt+pcU3BxIuBtsOrLlryx9MKdh5M8p8p5FGbS/TX01eVbNkS1rrvRHsa6iNkpJ
8ZUrmCFS0asKwwnG/h5Y4cbZb0247Tskg78U9AVqT10CSGhI/XvajPFA2RgvQf/7
MW1ZLz8E9wKfIfjBjqJ/MzcbuwF5i880Z2EyJ+kd4jyqr55NzvjOLdN2cnIVP0cL
mIMiBuRIIdoVXhgJVnZLZxQl5G9TMAQvNyaNdB8P4OcuDPGqp1o=
=uCE3
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1gACgkQsNpg+0VL
rxhc1w/9ERXx7ucZbEUP/Xc5a7KX0tmltnMUS3q2/5TuLDzyXXD/0acTX4eYuIlM
xHx30G1TBnMM1B/tcDctXszlJmi4WlcU+mzTbarmILllgIPb1WDp3udWE6ormCSy
WHibUk9s8d3/a2wA8fA7Dkrw4zXTqF6z90D2MyBrbY7tyGMBT2oS1KHuVdEuUtdk
IOJWRlw9z9TtDLV7VzKda4JiUnGHesNT/xwZnUo/E+sM1RMuDEDQK5aal+YliIIc
1ZtX63sYTwV7jJ56bcsXQirujMPg0Nydrx8VxPybHVYiukEPWBLQXnfQoVofbP3z
fpPsnE6CLw477XV8XWRQ0ktRlqdm8B41GfnggxJ5HJDhfUu8oL4iDJkr6PJBUxjV
BqX2eFWzJYN2n1Bgtw6GmHIY+tXzQQjswF7T69njR+ztlnqy52il+cHmuAUh2P/n
xHODwm/QqVoSZ3xskU0DE3DTgHWvMFUkcijxSnTKg1yZ94g2v+raaj/W+n6NM/2V
0ar0NJoV71QqWcDdphiMW/dV7gmCy5sEL36MKwYh9y3pJmslX+dJBokYJiSHKIsb
bwm9RCKNt0Hf+gaiMXqVFul+Bcnr2VX8W4p4oIsgAx6r0+jR5dvD3vLM+hEcOeMZ
MD5qZEcxHtMoD4kOkyi2bKhDIh4vFmEkOCnl1LhdybF4vZ8FZBs=
=I3qc
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1kACgkQsNpg+0VL
rxjVQA//WLJP7BaGqzHnlzaE9GClD3D5zT8VlLc+6TwNsv55BK8ZBb8R1xaSDDi6
Idb6L0BwDyagy/7LaoAywEkC7sh1B1rNL3fq5oX6yinoIBcecvEbE0Kr7gfQ0+8h
sie+Vg/h3d4JW8o7k0Etk+RbENrcKIdy7uWqfLzRIkfkzJicA4xhFlwpk78SyLhG
WxmgciKRKeCoSzI5t6DELd3tevHJlPga2T8PtIzbwhWE7tKho3hXo/1jHGKYAxV1
2smFubtgEl4NisbjTwXAq13pleP2KwB+9APPSyISmi2B7Uqc1elgrBQhOIwn98W0
x5Z5X2RLvMGBoLM7JY6EP6nfJvq8w70l4fUWGHlh/UFp1rxLrZMfAkbDK8kxvoGg
xXDYdixASYC9zUrXbRbtSIcLx68HFAp0Tu6lCOifHrf/ziyFXWZpXLHadZmtAd3z
cVPd4MEfj03C4+Z4uqamzgoRRSLYKszJzm+3xXQTfPqbZb+4iokskm+Eu6DWxe7D
LwsBU++5lr4jw+l1YUaRbTbHmHpeoxemtiscX0rzn1YZWFFg+Fso/bYTgP3qhIkP
7oEvH0vrv4u/HqaOwWJD2mxKDpnWdHRpgFchsd+EtXIIU1Y8irrjasLNwrnd16Jw
ophvLcgALo22fOJakx1VW+ql472vfWYIvQLgD/mkK3wm2W9dNhA=
=c7uX
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1kACgkQsNpg+0VL
rxj58hAAvmZnLgldU66dm1HliVetOhnzqSlL+UI/R6vtcWRplWh8DfLyxdTkZIPi
q8LqM4fy1caIMRo6Tl9GoA9UE347lwxVYsYmOK+wUiJaVzlwwLMuT1RD7mLfwtcx
eWfqa/wCLZHGh1/0QS0YppL4zT5v2s+z12zrLoEbq3ZdisVS/YUeGas2ED1dDrps
/KgmI71WSKIyH6kiBI6S/pIuLYoQ0DHtBffTAmXyI8v8dp7OtUiwuoIsXb4/XI5i
3XidxGp+3a3HgjwIvj9Gqf/Em0jev2IW0pDPxXdw3Sa/xufl03hHezfunulr6Rdw
V9GEurq2C4SdHfZgiJ4PJ8qRfiQmdN+vF06cVcHzzRj07Kc/T3y+A9SgVKftISzj
d1sUr/3N/kpyoBRhuIc4OBmDtwx+ZxNPZ7GrS2lTVucWs/rhmehP1g0AnSCM5wBX
4XPntEwh1rV0f2OmZu8MO4SpDQLKwKN6iI1hUf+7NW45cmPDdduvKEcB34iKg2py
M+r6I8QdCq+LEE3ct2QLqjNHajqgs43VGQLArhAoRd90+itzc/dJoQajhuhe8DAb
dEu4LMYdL0J3Qo2Dx+7mlSvQe2CJiJLS5kw4rTxDcBf4u87vAZemgO9A13jM2f0n
i/Oz+Wsx4eZsWxkJ4JTq1N8iJkZtca5mh8EHK2IX45YJIhIak+4=
=hZh+
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1kACgkQsNpg+0VL
rxiAEhAArbDUQhNJ2ADr41oQrpEpenqF7Becc/VxK5lPCM7SEiEZms44cAEE1oBn
h4hbZEjUR25wtm3PxNtBmP+hMYwaoGIQeCSl+3ls7EKiZXQ9Gaj29WAiLpFAj2fQ
jHCE0GOYnE9hDWQli/feJ9UeoBXUJi+iMXemXnkOmnscjoSlgw9TMJgHV0C3plho
/wXFoILBVdn41XV0tjWKasOYVlQgXIgl8WYG/OTHlQp0itHV+SvkNqgG1oLwbY1k
GYMmvhjRP1IXb4NpcLPsb3xPOIWQgHqlLrJlAuV+JYDToCPvyiNr6+7Uxq7al/a8
iaTavxPz1Z4oeXpJChAlxbmh5bbhb0+PhjEP3xAOzwholXdPRY7TRMsNACDNflV/
K9obdtX6ohX3goqOeV090YW+T1u2rMPrWhEaikGdCkv+4jCY0V+bpVKEW3mTKTvW
Ui0VZIjhwF6wBovCmSl2zrGxuvb3SZQ3FJyoxYAtB5CS3LHnIxBs3zeo7rwqaBv0
kujmVQPvfwXBdI36CaB/vzY4cGxjDykWhn9OldGDQKKnSdZ9WBonoUuiU1kNXjXe
5RntEXmYk/VCHkmXOyGs+NKtdP9ezAND47KqnV6Zy+9pJpgCPNLUxwT/2fcPnadv
SNR58BxjRtToj14xYU5hL9BUihldY7lzvAu+8ufI0dckdEkScLw=
=BuDK
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1kACgkQsNpg+0VL
rxiwnhAAuo+K5yQpDzl0Mep2ZC3Lg0hdiY7XDeIObQrwMefu1huJQuMnyLCYo8P1
7qE6sZKuxRovmTfDMBEQY7aJt4vGNEOMve+O/qhEeuqC3LUEeFQRyLaPZEYewXdQ
DGfA0622H+jfAJion3dIoVjQ3Put8Wx0GSfp1xFS77I284fBjrCZwc6HuOfY2rdA
/W47sny6I/YSt0sF+5UI+GFv9vVsxNKIQw8j3CVkxinR9dqScylOKFDNLMf7sg7L
ln9gUz/hE9gNPk38APaQrk18+TX75wMjveKsHLKhvIzADakEKCeG+1mVLEooZTAx
pIyythhriksl7+KK/6vuHVLPEvx9nZaQr7yj+ys02+pzQKQqrFVIr+AD7YvbUrmy
0lBmrskSI+TQsjqtKT9C8cZBjOHduZ1a9+1o5IU2bmHWfqOO9YqO42aKNQRMV8rB
8X+Vlx/1tddIv5Dk7XR7LTQ5e8r+sCFhnYPbFucSPYSRTxR3fTD0Zlyd84MrK3XM
8MN4lA9r0sx8rgeAAAcB9x+czFN0GgIbUurVlZzRuNe64r9zLfbQ6hLgdBFOyM0w
fdO5+rRQTyW1lLaDqdeYQi0qICKfY6HaBcH0e5C491zhzhnLZXud6253jqRX0yIQ
3B1OHXiYPl8bRFdQeoiAJ584kAtXjWx1090K+TqWxRaTke+MX2g=
=lHiH
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1oACgkQsNpg+0VL
rxjwERAAq4E105nW0kdsWgNKcXCtkNo2rGG0EMje6b5mFhBxsCnZgjyFor1azEfv
d0RCrotW7dLgWx9gKF8aTnhJ5T8LArd8cXVo5hNTSB7//pi+hsIb4YJzX+9rrVtQ
QD/W6lvRfesF+aUi0VmWwELxkWLDwcEU9n0YIXae1s4qPVv5QzCmKj+5NmoEFqK5
FHHEy7pTHd4DME2Zhl3HY6C/LV7jZUuV6jaKiG5ODZ73V3OmAJaIM+Bl2o2csTCD
4UeBOBYS/441z6wqDFWh948ffBF5SFSg13HeLb6tMKNdpkWT87zxStSTt/x69hAp
5UYP259rvrZIWAZ343/4HBdzF+lpHgL2atCpsl2Wqq0Z3fnr/byUma0BgFA44oOr
E+B/8B2F1x2OxlQLjMTCq08jmvzIK7m7XW2WGtCi1qkhbdjnAKbuBd5fHee9Qb9b
dbwk9IhEQilOSoVf+96R9tAB/Ujf//a6ryc5q47o0QFcP0LENc5lcTkhKiwqJXhl
wTG6Ywop6Y63dfaeZZSZOZrm5EGyvb1aUL91xfXM1ACpcjVJrv7yclio6VTiWbTj
T3w6azf+o7v8XEqeCeT+uzIB/hSh3QSWLU3TCovvPgkS1eX0YwnIRrL+tQjSLF4W
EedxWLNNnUMuOSJXBBWtBq2R+EyQLD++9T3pIeqSmd8hG8VqE5Y=
=u/9Q
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1oACgkQsNpg+0VL
rxghBA//fxXb0cWTR3FXALZYg5WkmAKeEejdCHdRFsJry3lkXC26YEkMK2zHtr1i
rOErYcTnNOtILijVUdmJJd6U7MqZEZlDkG90Hwi/ILjqEnN8jkMJUPYh9jdI4/Nj
XlBr49gTLHjfqzpiRzhi166ZjMYysyk6i2G5UCkUg8hP3FLvuhxopAp8c267Qn4l
DKT0LgJt7ffOpOV/rsydS0kOHlJua/5QE9RrBGAR5L+Fv+bWH+lvwHsbEV60HC59
pEhA13mp7ypZxSiGm/iOXUZ8UO28WDzA+BX3V7oDL1QKkvrPxGzpGgjZNYJLeN+r
5GN/U3iGDMiqLJNFP6UzMtnJ7OnhQR56MOKZWHxLrntKwhPg1OpkAPjeuZgXMkBs
QM+XR57h/nC+1hqQlCgK3nLHrBp/9fh2rbPyxHNgmYS1p/5cucEnYC06LUx1yhM6
lrYnxLFn5U/aUeRF73X6Mcoyi3JVqhvCShUvRkmyY93/97zSdMPuSNUFFeQVc70S
lK75DLr9HQ3ymP2x3hqKCA9AXfTksuvWsP6q6wg4j3stkpaLZwVEIs9yFrKfa2MK
pnatvijcBcTMZpG/Jlh2NgjoHB5dpLajsHgTMt44MIqDpToBSQ64mvc7vqC3evME
LRLJQLSmL9ImDlk6gYEfpDtYF/LsIjx+QCagQa3DAHf9X9EV6ZY=
=QeCH
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1oACgkQsNpg+0VL
rxhosQ/+OHb48FBmuw+YC3E178oVPN6KxjNzFveWA3Sm/8Gn8uKBY13TdRd+arNH
HFibSsPmCpde5exaQ47IkCC7r3Rap8VLVu1ZdmsFlN+O0J5/POh9CKWUrTiMKYj5
yptEYl2BK7a2HktIxkd0sWhvlVAfUa67CuyYEcwXFF4K2mZrloSddFrabv6DALl7
Cj2ZiKjZMUFwZjGS5vv7Yn39W6s5JowSI7Fkfa4VPffKfKa5DlCFKRs4pD0yVd/N
XrPaBsvc1Ysfi+tpxBwKlIfF9IkhUVDDYTWfDHzDeBuBSRAH0/H8Wi3lMDjxuUvg
CK9iGcEqC8ZvjpelGwAviA/R7Jwyxx1+/YAwb2w0b5EYGzf7UOSxNPtkaoIwuekX
X7G4ZJXNyh3RWyemD/Dj+uBFbGVUE/rkQY0KzvhAM3KkxfT+gC1NdDNL+JAMB4rM
mMZW1XM2sQwfZpgKKcJrYKvEku3gekvYJ7qJ4phzPKk8nlq79oxDnar5wJIOWEk0
6nZrHP+u2hCHq/UrI+LvbWF/D2xzLtoBgA+1z7nJTP6FC5JRhlV75XuzXG5q6MbO
FEtxSGmYTf+bRG5VlMfyrrHAAIMesAMLIGpRMu2bBGJK6I4MxduheR9AUbIWwiDC
Es1vxoK4t2P5FXSKA1dYI/fe2xlQjEm/hcE3xVhmkGn6ZkJIXo0=
=Ht3/
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1oACgkQsNpg+0VL
rxjc7hAAhaegaPdcpyouAAfT25/SBSYuOYfqOt6+Lurmgi/FMRJPqYOdBHrcEdFw
uxr+uZFyReQsa7B2cbTkCZAG8k7j+GmziJIfD+WTRL2OSvDcBROW/dbqersakoLX
Fdh0pV7P8uW2acio9fUNvh3U2MXvfSPMFasy0JJ49BO0g0w20tiAdMeL/LIq6GxM
HOwl7+vsZlwicFMP8+UdM+WQouDKGtafGtTPfsRJhWmXhnWbI+W7URjQ9+m+qAau
UkramfnPfdSrmPCeRONX7N/cyhYu8OPtNjYXbNT7mG7V5xS8E5cYYozls+lZ6G67
U7BQNnXPwwuLTBzRz1qATrlp5V60KVc3vKJQfXNwRWJ9o4m9nipcWcIKTUe/Xh9B
h4fcee+kMuWNq+5r2oi3dmO5opbecTy0TiEJrjBswfiKyJNBIK3jDLhcaJ8Tz4kd
p11dBPgQlmY/AOPM5OFHdh3FCqR11NNDfQgxBr00FFzlbEtD17ctDCBOJIz39NVI
OJgyFYUFVhvk4eUxT3fxDBghL3U6BFpv9laJPkJ3FSUyaQon560XAUAKw76f+rj2
x5JuYrvXD53OJO+hP1CgUqtxv9rXRYo9iFygxUvkjnDFaDg4quXWWpgVKdxX8DAv
fFWgqLxIJVTyDbslCK1IMTFWkCACtTRugHWCvvwW4wfhIO/Ev7w=
=aKOf
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1oACgkQsNpg+0VL
rxh3fRAAj77DVczOBwX4Ff37FpeswC2Ygna69XQ4deNHOjX87nGvSFgMX91JRWzR
71SzTfcKVKogYkjFc8VP9CXRrIAAPWa/IP0A27SL9mCwXCj3C1SE9L5Lv+7vLYIg
FtUKYAYqxfP0vHhvK9xjdaMo1ZGKxrZ9cx1PN//R18eg5ww8CYst7MOyuH14pj3/
G+3QZufuzGJFjrnGngeTykqYDlOOyn17h0hZ4xcCMoi5eZ3BtXVGMTyEscK5D42U
9zJqifTJQCjUDBDACSvDTAvGXu/7wblqqwOux4eT+LvedKQQFznF0PHDctPi/Rvm
KXZGzf7vTXnYNZBrXnJUzSd2bwnGbyDjftAtMu6OqzlM/lBRlgODaiIr7yILPzEz
vh2hcUBssipJpW6zvR7EU67ougiPhNoTg6XnKLxPXmdvUGCm2IbTzESMFh6SqlkF
hkBhOTOufaAClYJRAyWF+lNR5hs2GzM/3NcQCkW3p71BnBddC/l7n5IfORZ778BX
Dj4BBGLBs+cKIqCu3BWqYeH+KmgLLzXP/vlcsTyRFgvkOmwzZ1UzsV0IG36UxNVV
awMxUlPZZPfMwyLGlBkbrwKEnCyLzciJP1iHxZq9mpyTi6gztmMJ2dMk5lwjIMyK
NxFMSvsGSP0H9z7dgHkOlXrr4jPLAELtXNQeiJPH0XJbkHufkDU=
=kcOX
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1sACgkQsNpg+0VL
rxjTXA/9E31QzjCQ2AU2TiNWLGIM1dTAYZJIPylgkXtOha5R7kvmwBVIc+AAzDFK
RFnc11SdBd6/xgYQRGUlG7BVZvwA89SdqwS2FK64UKYGPkM9r1fZPIH0wesoc0lx
iWjUKH52vE3hViaLB+kjb46ldBSEjL2Zw7R0oc4YlwXTw5XP3t4ApECFR+f9KFSv
/umMKLsMnfdER+lcxFr4Xcsg1ZQjHVsuITsnG1q0rVEqzkj3rlmizdF/hiDm5C2A
TS79lqn1OIExW5jVjWz/ZnolCfyrlFFcZhI9dwtANpf1dCcd+p7TQfBIj+v3N28h
M5Xq9pmuyV5DkS7TwSZYsGzvM0KDQmlp66XEaC1d4MCw+udD6sJmKfLB62HU1dw6
RL+uzuN49MgBo/NKJOCRn8DYiiWDxkZNVuh/869bAE3D9SpGzHIh1AeqPSZ/gcuz
hjdzlQZ1jZQiubpnswkVHlafrzfJdRhvwqykeXQ0FeDRyCuFUtIWH6eoD5fjDFpd
b051foyrvAF2aqGQ49JgdMDX1D/CVfADQ2HpAQNeLsZPglOqkfp2P+0tmccuoKkh
jdus+A6uhb+DpdM4FgQb+BD4ijpH4WEMvz4grAn4StR8FFqMfwChKwcJhLKIu4fX
daEWWs/xq71xfRFt/3N89N1uXcHbFbvcFQrqPuqUQ7jDwSdNvdk=
=df2/
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1sACgkQsNpg+0VL
rxi3zg/+NRYVaonoQcH/883OgOV35/HveFM1vtarj64D+fbl/RFk0idXoXM6FeMM
vz8sUAWSYFSDAspPaIhUlXsc0KNxRW8D0BmUzy3zjPlT32mVQBbHg31suxqbmgox
Vj2k0xW8q55w7mae67YaNyQPKVlNNFTVTkCv3XIYJzmiVy8Oe9lqYmpxhgrBskNi
YZju5vSAwkeXrZyqFsT3j8uZ7vtz9uhT+TmBv8FXR9jalOlpJ/fCg4d4qgj4cU4k
F6BjHukh3d3uM7P6WSkOIwwJpEMhKndmzwPEfpudvLG2BltpQUpGxNaXs5ryirvy
xtX1aBPkaeig+RQTIsejf+IBCQKragaztEoaL0Y3tq6XnlxLOqYriQRh6BOpmdSx
BDmMt2O7vgGA55fTXTtA4jSyfqWB2ZqI+m6VOGUCKehIVi5/OWEW64aDqWUVplZD
pQw6Q+BNIewBw8PTEEL+P2d5S0ZN8By00oZiji4+MaKrrQEevjZgIEksOlgQ9xXR
uoKOvaDlYjEuQaHgY9c+ZiHblGdadox9r7pPwUMjBfSo81rhw0Erq09UOqERPj2Q
yn1wBedXlTyoVS9rJCv2XQS93YoFZsIajzRqtaRbzMT0FSpCuWMyuuPT9cm+Iwi3
1ad0i2aJRvcVXdHJA90NabcPues8WMZEHnMN1XVHKvgIrYjEtVk=
=jnVt
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1sACgkQsNpg+0VL
rxipZw/+IQo3L0nS7PtWDQdju0I+bQnqsKPj/xK3YkKnxw/LbXd7XYkXW/lNdcAC
6/8gTs1ncXQjZLzMyKpyHeml7mXbvAzOibddR29jHdlYHc97jzS+JzCgeUaJWC+k
O3R0Qy4KusHdzXsaA4nRQbQdYTxx4zbgPJcM1Jdj51JKn/J8IkaKKpNWCkMgXta7
nk5EoHK2u4L2I74F/YQECvrg8vUisfAQ6eVB3JPZQeRsXus+zdiJqyhJR76uWXxB
OIoHH0/HD6Wnx0nSIwdmCnXD17B6DCFBrJ7Ud0dwvy/iedZq1012GVloL9I5avg9
6qn85MyUAnxXQmRzTKV4jBInIkASu+ijC2P88gi/Qukh/NWKLFPQsSHhHd2ruHMU
AQbLB6OCTSp1UiVQNggaka/BbteKr0J9RLsSa2mxskjKnz4wfKNewGwXyRz1kiBb
/EMIc2Vh+wyqObGgAdadyn9ZQeCXaMSPBRWDZyKNHE8BXRPK6d2an3obXJ8gSmhG
hxy2lM+1Y2Jte5RMWJ/sGOqSE/DNBrLiRvkzDggshUPVlXflQNsPTQr1K4gpbJc/
QWoWHzaDUqV9l3JArvfBaDs8oSQnxpD9JmlQnZR0Eh/30rm71nAIx8fHsCBq48aL
rAVS1pZs8y6nCL+h8Mqhn8zvvpcBProWiupJEvvHgQMWtD9ZuYY=
=qLgT
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1sACgkQsNpg+0VL
rximkQ/+MzdRNjJT+U09yhVki1caImdJq3FyvAuxQwMKXidlOKf/bKogHpvHzxNo
KpVA1yt0IxydG5RUsIWVDHkv2RuuYCuD86Zb7ucWfp2/uKy171aBmRcaO82R5p8x
8N432AocqHculT5UiW65BJB8OLzPJr2lQfYUJ6/0ucXmu9Rp2nLeL896z0+RBS0c
/7Qp+VYCSc/AuVTtDTg5eTOAVDpuCYCNM6GlujNvFwk9Zo22DG40nuEzDUj/nqGj
zGvEclEm4bBnUb/dUV7alpYLiQgSwl0DyrEF62HRAKvdkvhQI4Jl9jyy5HFp+A4M
bCtzDY4mduAUxiZThGZtzjc88cob1IJt5UHwmeikPk4AVSIEi0umVyfdZf/PIoVN
CJfUsNpdo04XU8MhUIajcAQ1vf5V2weJ144n4ycCq586j6QYu72LfYzMXZ/7mf5r
FzuY8BK7WIhiYxHlWvbtbMZ+ivuHEtPsqLk7tmCg84SeZhd2iJJMcu998DSUlGPy
7VLqZOmE3sLynBKd9AJfXsESWg6giAHDAq8CbOO5DV9c7S3zTkEXB+gYVFgVuY+g
hdKVBDnP0FmXD4pty4BJuFObqgFAvCu36mYWele/CDQVgx0clTG3PCe1ZEtpla/d
o5ZhEnKLiAdoFX7+oU8/0fhdQNMr28QJ1W26onZCZ4jyRedumEY=
=GhYZ
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1sACgkQsNpg+0VL
rxipZw/+IQo3L0nS7PtWDQdju0I+bQnqsKPj/xK3YkKnxw/LbXd7XYkXW/lNdcAC
6/8gTs1ncXQjZLzMyKpyHeml7mXbvAzOibddR29jHdlYHc97jzS+JzCgeUaJWC+k
O3R0Qy4KusHdzXsaA4nRQbQdYTxx4zbgPJcM1Jdj51JKn/J8IkaKKpNWCkMgXta7
nk5EoHK2u4L2I74F/YQECvrg8vUisfAQ6eVB3JPZQeRsXus+zdiJqyhJR76uWXxB
OIoHH0/HD6Wnx0nSIwdmCnXD17B6DCFBrJ7Ud0dwvy/iedZq1012GVloL9I5avg9
6qn85MyUAnxXQmRzTKV4jBInIkASu+ijC2P88gi/Qukh/NWKLFPQsSHhHd2ruHMU
AQbLB6OCTSp1UiVQNggaka/BbteKr0J9RLsSa2mxskjKnz4wfKNewGwXyRz1kiBb
/EMIc2Vh+wyqObGgAdadyn9ZQeCXaMSPBRWDZyKNHE8BXRPK6d2an3obXJ8gSmhG
hxy2lM+1Y2Jte5RMWJ/sGOqSE/DNBrLiRvkzDggshUPVlXflQNsPTQr1K4gpbJc/
QWoWHzaDUqV9l3JArvfBaDs8oSQnxpD9JmlQnZR0Eh/30rm71nAIx8fHsCBq48aL
rAVS1pZs8y6nCL+h8Mqhn8zvvpcBProWiupJEvvHgQMWtD9ZuYY=
=qLgT
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1wACgkQsNpg+0VL
rxh+Bw//X06PzoyRpmRLdsLbkqV1WZtw/ax95Q2fjmt8OEpF0gFzwG23wgj1VyL0
8notDVo3/WmAdjTyTaZqibEBd8mMDmLBqPsc6FQdqxTXwqbPG538aVDR79r0cO9z
ZxLpioj0ZK5TwPzyiM459aV4bgHXhVByaWE01wYWB23UAlpljdo64zRWb46yKtyl
nt64r+N5wI67Q8oW6EftLNcHZg76Ge7ENZzJzALSeUilemFQwOrEYX/eprC1TX5Z
Iey9KDgL6pU2nsfED1O+k7fBQQv6YDzMQ0J+gxa2TrU0UUV6VmfTIrnH9nurn89O
iSaIVWVlK3dbUgaVRX/FI72l4R0Lg2JePLfet8EAoM8NIwr0mDWNQ+xF6Slpd3ug
rTXrglveqSCywCAaKj4YhY8oK4pS8jkPBUB0awW9+iqqTRlDiXYlXdtjxwgKzeVO
rQj1HVyJ3hZVn7KO9tMzg3h+P+XDF4KFZpXFZMgR8TllYmwEgYpCuDyoqne4JV/y
D5yPCjSMUX05VK7Hc8T9iITIOjk+FZdg9qnAw06mV7HjuNmBCdFyHzQrgC7VgoIv
I/0w+y2fwEl8qYuFHW0J8QLDY7JAQgtD3XftQzGQyAxWgTE6/Sh5Rv92boZTsUII
9LyAwSK5AWUo4gsBvgeLCSdNqbCeBYe/LbaLRwjcUtbtaT//XcI=
=PAeO
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1wACgkQsNpg+0VL
rxh+Bw//X06PzoyRpmRLdsLbkqV1WZtw/ax95Q2fjmt8OEpF0gFzwG23wgj1VyL0
8notDVo3/WmAdjTyTaZqibEBd8mMDmLBqPsc6FQdqxTXwqbPG538aVDR79r0cO9z
ZxLpioj0ZK5TwPzyiM459aV4bgHXhVByaWE01wYWB23UAlpljdo64zRWb46yKtyl
nt64r+N5wI67Q8oW6EftLNcHZg76Ge7ENZzJzALSeUilemFQwOrEYX/eprC1TX5Z
Iey9KDgL6pU2nsfED1O+k7fBQQv6YDzMQ0J+gxa2TrU0UUV6VmfTIrnH9nurn89O
iSaIVWVlK3dbUgaVRX/FI72l4R0Lg2JePLfet8EAoM8NIwr0mDWNQ+xF6Slpd3ug
rTXrglveqSCywCAaKj4YhY8oK4pS8jkPBUB0awW9+iqqTRlDiXYlXdtjxwgKzeVO
rQj1HVyJ3hZVn7KO9tMzg3h+P+XDF4KFZpXFZMgR8TllYmwEgYpCuDyoqne4JV/y
D5yPCjSMUX05VK7Hc8T9iITIOjk+FZdg9qnAw06mV7HjuNmBCdFyHzQrgC7VgoIv
I/0w+y2fwEl8qYuFHW0J8QLDY7JAQgtD3XftQzGQyAxWgTE6/Sh5Rv92boZTsUII
9LyAwSK5AWUo4gsBvgeLCSdNqbCeBYe/LbaLRwjcUtbtaT//XcI=
=PAeO
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1wACgkQsNpg+0VL
rxikdw//UiRZLCXH4jDxC7lMW1TcMTlfFFhwcMusnKpnqtJqcXBYXpkitsK1iSLo
nZvKjL2qckF/lF8l4AjDVKYl9hiyNaDpH1WaTK1icc+FJJSN9TAccdQktKgVP55+
ZXT5gBKgMXA8pLK+fU4qrNJYv0Y3ijCpIJq2WMuPBV8h7/251qh/HVenb4bBOMPX
JGO0PwlL7RNGZcK/h/5NEWDyYJiBARA/5zz9XQoa0osq55aO7IOOomJnCyeI5Owk
UV9FcuxmAghZv1dLkvbL65vfgplnD7wAsOhnYa2f6/GYHi3zZTc7gPAJhuVEY3kw
lIL+MuevDf6FTai6oXsw9ogzqdIcmeLRJtwL9S0MEBB28WlXt4W/b3s704YfdtjI
rzH1/HQRnmspq+3kMkdETtkfRfnZiiZbrwOHtOZUo6G9DF9VEaGbW/WWkcD5dzIZ
WY3UiwJWfBRLTkiKMuZ0SDStsj5FbJm+pZjXYz7TnaI4t2oMcBXQ1j99PWa6kmz3
FlpIKv1lgNX39IMNI1sOJPETHfDTxhjY7qPE/qZR1lO4XN8NAvFQAH0TGENevNSc
Vo6rMbdCzsnB9iyStjD36i4weKsrDXf3k9kOweIsVJHEZSjMZXRgNidvY8U7Q0B1
DtKbqwMV6CuRe7dE/7Vx8DQ4ACQ7jJwXTOfLH3Gz5x+NcD5ZyPo=
=5KNB
-----END PGP SIGNATURE-----
+16
View File
@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkwealRHvwLfWzb+1sNpg+0VLrxgFAmo2n1wACgkQsNpg+0VL
rxgVKg/+Pecu0yNdAY7PjYLaNbzJGW+FknKWnQ8gNf75fqWg0qpli1V1c7oRlDnt
Q+gIE5kOhBzmGS0duINh4+5K6ySEA4Wv48VubGDb3w78S5e/drN5qRWC4STf9fSU
WEOU8sn28+fcvHRQGduOA9jxT6z6cdEjR7AKsgk32f47Mwo5gg1qPVHhxZ6HI7sY
C1M+kdrjMY5SgHuIC+C2F3E0Nhen8hdkAAyN4DeS0ir3X5mb638HiVmHnKbOow/P
A3lVQpzyM43bMWTCCzQinAS/WdUi6LsHg/WfKWta3jpqb+x9e9lHRYOJG8LUcFiy
e8ykC4GSNwNcMvcJHgpCyGoqro2CBo6EkK/nCeSAE+DOsybUIGKpxj0CDhmkHCNf
EBXn3lvet6ciLhjGqgpIWboZ7iCd4ytjXQptG+WFIoS66IwpEvCPQxGg2erRfYma
dLbC9YP31pEuY+93X3zzr1x9DYrvdaFgfs0OC18s1Hk3eoqBlaSZpFTWRy5IvYdG
ONsfxREKR/FXSMduUmNGRdUIEGWobf5RXQN07b14I5cl5AKQIyq7wXWkCNJwy4PT
QE0ldopaxXCR1ZRy25CCHBTXdop5ckP03ry/o54+HWtyDT+K0UrtD/gw1kZdsi0Y
FdBx5EQnRL6WunAzjxNTeBXnkHrtnMkoQ6/rhp+AEzITucAQ3js=
=SVZs
-----END PGP SIGNATURE-----
+28
View File
@@ -0,0 +1,28 @@
71b8d6e8f5fe81f6c6d0d110e3892251f6ce76ed095abd315e26e6e1193af3af jq-1.8.2.tar.gz
332dd9ae07c19fb47f6e8c4dd973a141064c0d35363c254235ee84d2d9e0167c jq-1.8.2.zip
01e9619236573939473c0f2eb2c5c38dc0f066fbdc89a5357a6f3f2954e00eed jq-attestation.json
b1c22172dd303f3be49e935aa56aa48a8b7a46e0bc838b4997d3bb451495870f jq-linux-amd64
8b85c817833814ddca00a144c33705546355afccf0cf39b188f3cdb48b852309 jq-linux-arm64
d88f6bd640ef8909b3deb587f12c03a0ed38fe8bd5e2e882e2b1bf88f5dab8d2 jq-linux-armel
78458244fb546469b4042e9e07cf78714ef6848895eb9515df76b4eb0b1dc992 jq-linux-armhf
ba996e8ce436973e2f39e2639405a37e8c81ba8c722b71c83996278ad0af16dd jq-linux-i386
1e9930ef7c4e69a49c2e5e9a1a5b1240a36d10123fa8524952ddeaedc039ad72 jq-linux-mips
34e53f8df8298fd609f8e3dcc7eae1d8a741976f289909286601443caf64229a jq-linux-mips64
eb382d2419aa99c82b8fb1cbb0d1cfa3da71b0852108f9140ca1ddcfd3d33d81 jq-linux-mips64el
365c0bcda2e695ab1e6f3372094d812e914784c03aa45ca4b67b93cc54fc78d9 jq-linux-mips64r6
01bfe1a1579cfac74a680870031e1d4bdd500040fae18fd9e2a27ada8e555a80 jq-linux-mips64r6el
9570c9dcbd7d0de85b16a00046a3e5a9ba72aabe4b85c8f5f8b5927aed8d664e jq-linux-mipsel
d2105ab249e66dc14465982d4b8b3e8cf0e6301eb606fa6116dfe0bfacbfb918 jq-linux-mipsr6
5e66dcad39eaa2d1e5b2eb01e2f378a3bfdf0ee2ebeb571cc87512ca4f38dec6 jq-linux-mipsr6el
d60c33574fdeab53ae15feb37598249ce4ab6a344adde6f22abba38cf7a8de6e jq-linux-powerpc
0dba61281e525ced2111bc00c8bd8078100e8822c33bfb35feee95314bbeeea2 jq-linux-ppc64el
a96e5a78a7b2c5a0575bc2a10dda4b20d84efd8c02c8806539ee5f5e57603e8d jq-linux-riscv64
42b3306c786e3352e3097b8aa03ca0e5631bdc7a6bf133bb8ddd9e4b148d20c8 jq-linux-s390x
b1c22172dd303f3be49e935aa56aa48a8b7a46e0bc838b4997d3bb451495870f jq-linux64
e94b266e3c26690550006abe63152b782280f4e14374accdf04cbde844f00bc0 jq-macos-amd64
2d75340ba57a4b4b4c8708a21c2dc8e958a48aaa8bba13b27f77f6e4c0eca07e jq-macos-arm64
e94b266e3c26690550006abe63152b782280f4e14374accdf04cbde844f00bc0 jq-osx-amd64
a6fc67fedaf9128a3309a1e2ebb8b986aeccf70122ee46d2cb4849e423f0c627 jq-win64.exe
a6fc67fedaf9128a3309a1e2ebb8b986aeccf70122ee46d2cb4849e423f0c627 jq-windows-amd64.exe
083b5377392bc57cf27052b6d20a2d927770683bca844632901ff38b4b7b0ac7 jq-windows-arm64.exe
a99cb668f95bdd788d9ee20529613b115e5d2a0d7f9127ee6976607e878558ba jq-windows-i386.exe
+115 -49
View File
@@ -32,6 +32,7 @@
#include "bytecode.h"
#include "linker.h"
#include "locfile.h"
#include "iso8601.h"
#include "jv_unicode.h"
#include "jv_alloc.h"
#include "jv_dtoa.h"
@@ -105,6 +106,13 @@ jv binop_plus(jv a, jv b) {
}
}
// drem is an obsolete alias of remainder, and is missing from the static
// libm of some platforms (e.g. i386 glibc 2.43), so use remainder instead
#ifdef HAVE_REMAINDER
#define HAVE_DREM 1
#define drem remainder
#endif
#ifdef __APPLE__
// macOS has a bunch of libm deprecation warnings, so let's clean those up
#ifdef HAVE_TGAMMA
@@ -115,10 +123,6 @@ jv binop_plus(jv a, jv b) {
#define HAVE_EXP10
#define exp10 __exp10
#endif
#ifdef HAVE_REMAINDER
#define HAVE_DREM
#define drem remainder
#endif
// We replace significand with our own, since there's not a rename-replacement
#ifdef HAVE_FREXP
@@ -235,9 +239,9 @@ static jv f_ ## name(jq_state *jq, jv input) { \
#undef LIBM_DD
#undef LIBM_DA
#undef drem
#ifdef __APPLE__
#undef gamma
#undef drem
#undef significand
#undef exp10
#endif
@@ -1086,8 +1090,14 @@ static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
onig_foreach_name(reg, f_match_name_iter, &captures);
match = jv_object_set(match, jv_string("captures"), captures);
result = jv_array_append(result, match);
// ensure '"qux" | match("(?=u)"; "g")' matches just once
start = (const UChar*)(input_string+region->end[0]+1);
// ensure '"qux" | match("(?=u)"; "g")' matches just once; advance the
// search start past the whole codepoint, not a single byte, so we don't
// land in the middle of a multibyte character (which would yield a
// spurious duplicate match at the same offset).
start = (const UChar*)(input_string + region->end[0] +
((size_t)region->end[0] < length
? jvp_utf8_decode_length(input_string[region->end[0]])
: 1));
continue;
}
@@ -1348,6 +1358,36 @@ static jv f_string_explode(jq_state *jq, jv a) {
return jv_string_explode(a);
}
// Only the letters from..to change case. Bytes of multibyte UTF-8 sequences
// are all >= 0x80, so they are copied unchanged.
static void ascii_case_copy(char *dst, const char *src, int len, char from,
char to) {
for (int i = 0; i < len; i++) {
char c = src[i];
dst[i] = (c >= from && c <= to) ? c ^ 0x20 : c; // flip case: 'A' <-> 'a'
}
}
static jv ascii_case(jv input, char from, char to, const char *errmsg) {
if (jv_get_kind(input) != JV_KIND_STRING)
return ret_error(input, jv_string(errmsg));
int len = jv_string_length_bytes(jv_copy(input));
char *result = jv_mem_alloc((size_t)len + 1);
ascii_case_copy(result, jv_string_value(input), len, from, to);
jv ret = jv_string_sized(result, len);
free(result);
jv_free(input);
return ret;
}
static jv f_ascii_downcase(jq_state *jq, jv input) {
return ascii_case(input, 'A', 'Z', "ascii_downcase input must be a string");
}
static jv f_ascii_upcase(jq_state *jq, jv input) {
return ascii_case(input, 'a', 'z', "ascii_upcase input must be a string");
}
static jv f_string_indexes(jq_state *jq, jv a, jv b) {
if (jv_get_kind(a) != JV_KIND_STRING) {
jv_free(b);
@@ -1532,20 +1572,23 @@ static int setenv(const char *var, const char *val, int ovr)
* Our wrapper tries to use timegm() if available, or mktime() and
* correct for its side-effects if possible.
*
* Returns (time_t)-2 if mktime()'s side-effects cannot be corrected.
* Returns (time_t)-1 on failure, which is also the valid result for
* 1969-12-31T23:59:59Z. Tell them apart by tm_wday, which is set to -1 here
* and overwritten by the conversion only on success.
*/
static time_t my_mktime(struct tm *tm) {
tm->tm_wday = -1;
#ifdef HAVE_TIMEGM
return timegm(tm);
#elif HAVE_TM_TM_GMT_OFF
time_t t = mktime(tm);
if (t == (time_t)-1)
if (t == (time_t)-1 && tm->tm_wday == -1)
return t;
return t + tm->tm_gmtoff;
#elif HAVE_TM___TM_GMT_OFF
time_t t = mktime(tm);
if (t == (time_t)-1)
if (t == (time_t)-1 && tm->tm_wday == -1)
return t;
return t + tm->__tm_gmtoff;
#elif WIN32
@@ -1571,16 +1614,15 @@ static void set_tm_wday(struct tm *tm) {
* https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Gauss.27s_algorithm
* https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html
*
* Tested with dates from 1900-01-01 through 2100-01-01. This
* algorithm produces the wrong day-of-the-week number for dates in
* the range 1900-01-01..1900-02-28, and for 2100-01-01..2100-02-28.
* Since this is only needed on OS X and *BSD, we might just document
* this.
* Tested against gmtime() for every date from 1600-01-01 through
* 2400-12-31.
*/
int century = (1900 + tm->tm_year) / 100;
int year = (1900 + tm->tm_year) % 100;
if (tm->tm_mon < 2)
year--;
if (tm->tm_mon < 2 && --year < 0) {
year += 100;
century--;
}
/*
* The month value in the wday computation below is shifted so that
* March is 1, April is 2, .., January is 11, and February is 12.
@@ -1593,7 +1635,10 @@ static void set_tm_wday(struct tm *tm) {
if (wday < 0)
wday += 7;
#if 0
/* See commentary above */
/*
* Off: the bundled strptime() can leave a wrong weekday here, and %a
* or %u can name one that does not match the date.
*/
assert(wday == tm->tm_wday || tm->tm_wday == 8);
#endif
tm->tm_wday = wday;
@@ -1629,6 +1674,7 @@ static jv f_strptime(jq_state *jq, jv a, jv b) {
struct tm tm;
memset(&tm, 0, sizeof(tm));
tm.tm_mday = 1; // a format without a day of the month means the 1st
tm.tm_wday = 8; // sentinel
tm.tm_yday = 367; // sentinel
@@ -1661,6 +1707,8 @@ static jv f_strptime(jq_state *jq, jv a, jv b) {
set_tm_yday(&tm);
#elif defined(WIN32) || !defined(HAVE_STRPTIME)
set_tm_wday(&tm);
if (tm.tm_yday == 367)
set_tm_yday(&tm);
#else
if (tm.tm_wday == 8 && tm.tm_mday != 0 && tm.tm_mon >= 0 && tm.tm_mon <= 11)
set_tm_wday(&tm);
@@ -1674,6 +1722,17 @@ static jv f_strptime(jq_state *jq, jv a, jv b) {
return r;
}
static jv f_fromdateiso8601(jq_state *jq, jv a) {
if (jv_get_kind(a) != JV_KIND_STRING)
return ret_error(a, jv_string("fromdateiso8601 requires string inputs"));
double t;
if (!iso8601_parse(jv_string_value(a), jv_string_length_bytes(jv_copy(a)), &t))
return ret_error(a, jv_string_fmt("date \"%s\" is not a valid ISO 8601 datetime",
jv_string_value(a)));
jv_free(a);
return jv_number(t);
}
static int jv2tm(jv a, struct tm *tm, int localtime) {
memset(tm, 0, sizeof(*tm));
static const size_t offsets[] = {
@@ -1737,10 +1796,8 @@ static jv f_mktime(jq_state *jq, jv a) {
if (!jv2tm(a, &tm, 0))
return jv_invalid_with_msg(jv_string("mktime requires parsed datetime inputs"));
time_t t = my_mktime(&tm);
if (t == (time_t)-1)
if (t == (time_t)-1 && tm.tm_wday == -1)
return jv_invalid_with_msg(jv_string("invalid gmtime representation"));
if (t == (time_t)-2)
return jv_invalid_with_msg(jv_string("mktime not supported on this platform"));
return jv_number(t);
}
@@ -1751,7 +1808,7 @@ static jv f_gmtime(jq_state *jq, jv a) {
struct tm tm, *tmp;
memset(&tm, 0, sizeof(tm));
double fsecs = jv_number_value(a);
time_t secs = fsecs;
time_t secs = floor(fsecs);
jv_free(a);
tmp = gmtime_r(&secs, &tm);
if (tmp == NULL)
@@ -1765,7 +1822,7 @@ static jv f_gmtime(jq_state *jq, jv a) {
struct tm tm, *tmp;
memset(&tm, 0, sizeof(tm));
double fsecs = jv_number_value(a);
time_t secs = fsecs;
time_t secs = floor(fsecs);
jv_free(a);
tmp = gmtime(&secs);
if (tmp == NULL)
@@ -1786,7 +1843,7 @@ static jv f_localtime(jq_state *jq, jv a) {
struct tm tm, *tmp;
memset(&tm, 0, sizeof(tm));
double fsecs = jv_number_value(a);
time_t secs = fsecs;
time_t secs = floor(fsecs);
jv_free(a);
tmp = localtime_r(&secs, &tm);
if (tmp == NULL)
@@ -1800,7 +1857,7 @@ static jv f_localtime(jq_state *jq, jv a) {
struct tm tm, *tmp;
memset(&tm, 0, sizeof(tm));
double fsecs = jv_number_value(a);
time_t secs = fsecs;
time_t secs = floor(fsecs);
jv_free(a);
tmp = localtime(&secs);
if (tmp == NULL)
@@ -1831,8 +1888,10 @@ static jv f_strftime(jq_state *jq, jv a, jv b) {
if (!jv2tm(a, &tm, 0))
return ret_error(b, jv_string("strftime/1 requires parsed datetime inputs"));
/* Prepend a character so that strftime() returning 0 means the result
* did not fit, even if the format expands to nothing; it is trimmed below. */
b = jv_string_concat(jv_string(" "), b);
const char *fmt = jv_string_value(b);
int fmt_not_empty = *fmt != '\0';
size_t max_size = strlen(fmt) + 100;
char *buf = jv_mem_alloc(max_size);
#if defined(__APPLE__) || defined(__sun)
@@ -1847,7 +1906,13 @@ static jv f_strftime(jq_state *jq, jv a, jv b) {
* account ... */
tzset();
#endif
#ifdef __NetBSD__
timezone_t tz_utc = tzalloc("UTC");
size_t n = strftime_z(tz_utc, buf, max_size, fmt, &tm);
tzfree(tz_utc);
#else
size_t n = strftime(buf, max_size, fmt, &tm);
#endif
#if defined(__APPLE__) || defined(__sun)
if (tz) {
setenv("TZ", tz, 1);
@@ -1860,12 +1925,11 @@ static jv f_strftime(jq_state *jq, jv a, jv b) {
tzset();
#endif
jv_free(b);
/* POSIX doesn't provide errno values for strftime() failures; weird */
if ((n == 0 && fmt_not_empty) || n > max_size) {
if (n == 0 || n > max_size) {
free(buf);
return jv_invalid_with_msg(jv_string("strftime/1: unknown system failure"));
return jv_invalid_with_msg(jv_string("strftime/1: result too long"));
}
jv ret = jv_string_sized(buf, n);
jv ret = jv_string_sized(buf + 1, n - 1);
free(buf);
return ret;
}
@@ -1893,18 +1957,19 @@ static jv f_strflocaltime(jq_state *jq, jv a, jv b) {
struct tm tm;
if (!jv2tm(a, &tm, 1))
return ret_error(b, jv_string("strflocaltime/1 requires parsed datetime inputs"));
/* Prepend a character so that strftime() returning 0 means the result
* did not fit, even if the format expands to nothing; it is trimmed below. */
b = jv_string_concat(jv_string(" "), b);
const char *fmt = jv_string_value(b);
int fmt_not_empty = *fmt != '\0';
size_t max_size = strlen(fmt) + 100;
char *buf = jv_mem_alloc(max_size);
size_t n = strftime(buf, max_size, fmt, &tm);
jv_free(b);
/* POSIX doesn't provide errno values for strftime() failures; weird */
if ((n == 0 && fmt_not_empty) || n > max_size) {
if (n == 0 || n > max_size) {
free(buf);
return jv_invalid_with_msg(jv_string("strflocaltime/1: unknown system failure"));
return jv_invalid_with_msg(jv_string("strflocaltime/1: result too long"));
}
jv ret = jv_string_sized(buf, n);
jv ret = jv_string_sized(buf + 1, n - 1);
free(buf);
return ret;
}
@@ -1989,6 +2054,8 @@ BINOPS
CFUNC(f_string_split, "split", 2),
CFUNC(f_string_explode, "explode", 1),
CFUNC(f_string_implode, "implode", 1),
CFUNC(f_ascii_downcase, "ascii_downcase", 1),
CFUNC(f_ascii_upcase, "ascii_upcase", 1),
CFUNC(f_string_indexes, "_strindices", 2),
CFUNC(f_string_trim, "trim", 1),
CFUNC(f_string_ltrim, "ltrim", 1),
@@ -2029,6 +2096,7 @@ BINOPS
CFUNC(f_input, "input", 1),
CFUNC(f_debug, "debug", 1),
CFUNC(f_stderr, "stderr", 1),
CFUNC(f_fromdateiso8601, "fromdateiso8601", 1),
CFUNC(f_strptime, "strptime", 2),
CFUNC(f_strftime, "strftime", 2),
CFUNC(f_strflocaltime, "strflocaltime", 2),
@@ -2105,21 +2173,19 @@ static block bind_bytecoded_builtins(block b) {
}
}
{
// Note that we can now define `range` as a jq-coded function
block rangevar = gen_op_var_fresh(STOREV, "rangevar");
block rangestart = gen_op_var_fresh(STOREV, "rangestart");
block range = BLOCK(gen_op_simple(DUP),
gen_call("start", gen_noop()),
rangestart,
gen_call("end", gen_noop()),
gen_op_simple(DUP),
gen_op_bound(LOADV, rangestart),
// Reset rangevar for every value generated by "end"
rangevar,
gen_op_bound(RANGE, rangevar));
builtins = BLOCK(builtins, gen_function("range",
BLOCK(gen_param("start"), gen_param("end")),
range));
builtins = BLOCK(builtins,
gen_function("range",
BLOCK(gen_param_regular("start"),
gen_param_regular("end"),
gen_param_regular("step")),
BLOCK(gen_op_unbound(LOADV, "step"),
gen_op_simple(DUP),
gen_op_unbound(LOADV, "end"),
gen_op_simple(DUP),
gen_op_unbound(LOADV, "start"),
rangevar,
gen_op_bound(RANGE, rangevar))));
}
return BLOCK(builtins, b);
}
+8 -17
View File
@@ -39,10 +39,10 @@ def recurse(f; cond): def r: ., (f | select(cond) | r); r;
def recurse: recurse(.[]?);
def to_entries: [keys_unsorted[] as $k | {key: $k, value: .[$k]}];
def from_entries: map({ (.key // .Key // .name // .Name):
if has("value") then .value else .Value end }) | add // {};
def from_entries: add(.[] | { (.key // .Key // .name // .Name):
if has("value") then .value else .Value end }) // {};
def with_entries(f): to_entries | map(f) | from_entries;
def reverse: [.[length - 1 - range(0;length)]];
def reverse: [.[range(length-1;-1;-1)]];
def indices($i): if type == "array" and ($i|type) == "array" then .[$i]
elif type == "array" then .[[$i]]
elif type == "string" and ($i|type) == "string" then _strindices($i)
@@ -63,15 +63,17 @@ def strings: select(type == "string");
def nulls: select(. == null);
def values: select(. != null);
def scalars: select(type|. != "array" and . != "object");
# Keep the accumulator the only reference on the left of + so the string is
# appended in place; a nested + or a // inside the reduce copies it every step.
def join($x): reduce .[] as $i (null;
(if .==null then "" else .+$x end) +
($i | if type=="boolean" or type=="number" then tostring else .//"" end)
(if .==null then "" else .+$x end) |
. + ($i | if type=="boolean" or type=="number" then tostring end)
) // "";
def _flatten($x): reduce .[] as $i ([]; if $i | type == "array" and $x != 0 then . + ($i | _flatten($x-1)) else . + [$i] end);
def flatten($x): if $x < 0 then error("flatten depth must not be negative") else _flatten($x) end;
def flatten: _flatten(-1);
def range($x;$y): range($x;$y;1);
def range($x): range(0;$x);
def fromdateiso8601: strptime("%Y-%m-%dT%H:%M:%SZ")|mktime;
def todateiso8601: strftime("%Y-%m-%dT%H:%M:%SZ");
def fromdate: fromdateiso8601;
def todate: todateiso8601;
@@ -148,11 +150,6 @@ def skip($n; expr):
if $n > 0 then foreach expr as $item ($n; . - 1; if . < 0 then $item else empty end)
elif $n == 0 then expr
else error("skip doesn't support negative count") end;
# range/3, with a `by` expression argument
def range($init; $upto; $by):
if $by > 0 then $init|while(. < $upto; . + $by)
elif $by < 0 then $init|while(. > $upto; . + $by)
else empty end;
def first(g): label $out | g | ., break $out;
def isempty(g): first((g|false), true);
def all(generator; condition): isempty(generator|condition and empty);
@@ -187,12 +184,6 @@ def repeat(exp):
exp, _repeat;
_repeat;
def inputs: try repeat(input) catch if .=="break" then empty else error end;
# like ruby's downcase - only characters A to Z are affected
def ascii_downcase:
explode | map( if 65 <= . and . <= 90 then . + 32 else . end) | implode;
# like ruby's upcase - only characters a to z are affected
def ascii_upcase:
explode | map( if 97 <= . and . <= 122 then . - 32 else . end) | implode;
# Streaming utilities
def truncate_stream(stream):
+10 -3
View File
@@ -832,8 +832,7 @@ static block bind_alternation_matchers(block matchers, block body) {
block gen_reduce(block source, block matcher, block init, block body) {
block res_var = gen_op_var_fresh(STOREV, "reduce");
block loop = BLOCK(gen_op_simple(DUPN),
source,
block loop = BLOCK(source,
bind_alternation_matchers(matcher,
BLOCK(gen_op_bound(LOADVN, res_var),
body,
@@ -842,8 +841,10 @@ block gen_reduce(block source, block matcher, block init, block body) {
return BLOCK(gen_op_simple(DUP),
init,
res_var,
gen_op_simple(DUP),
gen_op_target(FORK, loop),
loop,
gen_op_simple(POP),
gen_op_bound(LOADVN, res_var));
}
@@ -1305,12 +1306,18 @@ static int compile(struct bytecode* bc, block b, struct locfile* lf, jv args, jv
bc->nsubfunctions = 0;
bc->subfunctions = 0;
}
if (errors) {
bc->code = 0;
bc->constants = jv_invalid();
block_free(b);
return errors;
}
uint16_t* code = jv_mem_calloc(bc->codelen, sizeof(uint16_t));
bc->code = code;
pos = 0;
jv constant_pool = jv_array();
int maxvar = -1;
if (!errors) for (inst* curr = b.first; curr; curr = curr->next) {
for (inst* curr = b.first; curr; curr = curr->next) {
const struct opcode_description* op = opcode_describe(curr->op);
if (op->length == 0)
continue;
+12 -14
View File
@@ -428,13 +428,6 @@ jv jq_next(jq_state *jq) {
break;
}
case DUPN: {
jv v = stack_popn(jq);
stack_push(jq, jv_copy(v));
stack_push(jq, v);
break;
}
case DUP2: {
jv keep = stack_pop(jq);
jv v = stack_pop(jq);
@@ -516,24 +509,29 @@ jv jq_next(jq_state *jq) {
uint16_t v = *pc++;
jv* var = frame_local_var(jq, v, level);
jv max = stack_pop(jq);
jv step = stack_pop(jq);
if (raising) {
jv_free(max);
jv_free(step);
goto do_backtrack;
}
if (jv_get_kind(*var) != JV_KIND_NUMBER ||
jv_get_kind(max) != JV_KIND_NUMBER) {
set_error(jq, jv_invalid_with_msg(jv_string_fmt("Range bounds must be numeric")));
}
if (jv_get_kind(*var) != JV_KIND_NUMBER || jv_get_kind(max) != JV_KIND_NUMBER ||
jv_get_kind(step) != JV_KIND_NUMBER) {
set_error(jq, jv_invalid_with_msg(jv_string("Range bounds and step must be numeric")));
jv_free(max);
jv_free(step);
goto do_backtrack;
} else if (jv_number_value(*var) >= jv_number_value(max)) {
/* finished iterating */
} else if (jv_cmp(jv_copy(*var), jv_copy(max)) * jv_cmp(jv_copy(step), jv_number(0)) >= 0) {
jv_free(max);
jv_free(step);
goto do_backtrack;
} else {
jv curr = *var;
*var = jv_number(jv_number_value(*var) + 1);
*var = jv_number(jv_number_value(curr) + jv_number_value(step));
struct stack_pos spos = stack_get_pos(jq);
stack_push(jq, step);
stack_push(jq, max);
stack_save(jq, pc - 3, spos);
+342
View File
@@ -0,0 +1,342 @@
/*
* A self-contained ISO 8601 date and time parser.
*
* The C library is of no help here: strptime() has no format specifier for
* fractional seconds, and no portable way to parse week dates (glibc
* consumes %G and %V but then discards them). The results would also
* differ between the host strptime() and the copy bundled in util.c.
* Everything below is plain integer arithmetic instead, which also keeps
* the computation clear of the range of a 32-bit time_t.
*
* The accepted grammar is
*
* datetime := date [ ("T"|"t"|" ") time ]
* date := year "-" MM "-" DD | year MMDD
* | year "-" DDD | year DDD
* | year "-" ("W"|"w") ww "-" d | year ("W"|"w") ww d
* year := YYYY | ("+"|"-") YYYYYY
* time := hms [ ("."|",") digits ] [ offset ]
* hms := hh [ ":" mm [ ":" ss ] ] | hh [ mm [ ss ] ]
* offset := ("Z"|"z") | ("+"|"-") hh [ [":"] mm ]
*
* As in the standard's own notation a run of letters stands for that many
* decimal digits -- DDD is the three-digit day of the year, d the one-digit
* day of the week -- while "digits" is one or more of them.
*
* The decimal fraction belongs to the lowest component of the hms that is
* present, so "23,5" is half past 23 and "2320,8" is 23:20:48.
*
* The date must always be complete, so "2015-03" is an error even though it
* is a valid ISO 8601 date. The time may drop its seconds, or its minutes
* and seconds, or be omitted altogether, in which case the value is
* midnight UTC. The date and the time must agree on whether separators are
* used, as ISO 8601 requires -- "2026-08-28T093015Z" is not a valid
* representation. The offset is exempt from that rule, since "+0900" after
* an extended time is common in the wild.
*/
#include <stdint.h>
#include "iso8601.h"
/*
* Days since 1970-01-01 of the civil date y-m-d in the proleptic Gregorian
* calendar, negative before the epoch, after Howard Hinnant's
* days_from_civil(). Requires 1 <= m <= 12 and 1 <= d <= days_in_month(y, m);
* the callers check both.
*/
static int64_t days_from_civil(int64_t y, int m, int d) {
y -= m <= 2;
int64_t era = (y >= 0 ? y : y - 399) / 400;
int64_t yoe = y - era * 400; /* [0, 399] */
int64_t doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; /* [0, 365] */
int64_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; /* [0, 146096] */
return era * 146097 + doe - 719468;
}
static int is_leap(int64_t y) {
return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}
static int days_in_month(int64_t y, int m) {
static const int d[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return m == 2 && is_leap(y) ? 29 : d[m - 1];
}
/* ISO weekday (1 = Monday .. 7 = Sunday) of a day count since the epoch. */
static int iso_wday(int64_t days) {
int64_t w = (days + 3) % 7;
if (w < 0)
w += 7;
return (int)w + 1;
}
/*
* An ISO year has 53 weeks if it starts on a Thursday, or if it is a leap
* year starting on a Wednesday; otherwise it has 52.
*/
static int iso_weeks_in_year(int64_t y) {
int jan1 = iso_wday(days_from_civil(y, 1, 1));
return jan1 == 4 || (jan1 == 3 && is_leap(y)) ? 53 : 52;
}
static int civil_to_days(int64_t y, int mon, int mday, int64_t *days) {
if (mon < 1 || mon > 12 || mday < 1 || mday > days_in_month(y, mon))
return 0;
*days = days_from_civil(y, mon, mday);
return 1;
}
static int ordinal_to_days(int64_t y, int yday, int64_t *days) {
if (yday < 1 || yday > (is_leap(y) ? 366 : 365))
return 0;
*days = days_from_civil(y, 1, 1) + yday - 1;
return 1;
}
static int week_to_days(int64_t y, int week, int wday, int64_t *days) {
if (week < 1 || week > iso_weeks_in_year(y) || wday < 1 || wday > 7)
return 0;
int64_t jan4 = days_from_civil(y, 1, 4);
*days = jan4 - (iso_wday(jan4) - 1) + (int64_t)(week - 1) * 7 + (wday - 1);
return 1;
}
/*
* The scanner works over an explicit [p, end) range rather than a C string, so
* that a NUL byte embedded in the input is a parse error instead of silently
* truncating the value.
*/
typedef struct {
const char *p;
const char *end;
} iso8601_scanner;
static int scan_at_end(iso8601_scanner *s) {
return s->p == s->end;
}
static int scan_peek(iso8601_scanner *s) {
return scan_at_end(s) ? -1 : (unsigned char)*s->p;
}
static int scan_eat(iso8601_scanner *s, char c) {
if (scan_at_end(s) || *s->p != c)
return 0;
s->p++;
return 1;
}
/*
* W, T and Z are what ISO 8601 calls designators. They are written in upper
* case, but the standard notes that "lower case characters may be used when
* upper case characters are not available", so match either.
*/
static int scan_designator(iso8601_scanner *s, char c) {
if (scan_at_end(s) || (*s->p != c && *s->p != c + ('a' - 'A')))
return 0;
s->p++;
return 1;
}
static size_t scan_count_digits(iso8601_scanner *s) {
size_t n = 0;
while (s->p + n < s->end && s->p[n] >= '0' && s->p[n] <= '9')
n++;
return n;
}
static int scan_digits(iso8601_scanner *s, int n, int *out) {
if (s->end - s->p < n)
return 0;
int v = 0;
for (int i = 0; i < n; i++) {
unsigned char c = (unsigned char)s->p[i];
if (c < '0' || c > '9')
return 0;
v = v * 10 + (c - '0');
}
s->p += n;
*out = v;
return 1;
}
/*
* A plain year is exactly four digits. An expanded year carries a mandatory
* sign and exactly six digits, which is what makes it unambiguous in front of
* a date in the basic form.
*/
static int parse_year(iso8601_scanner *s, int64_t *year) {
int64_t sign = 1;
int digits = 4;
if (scan_peek(s) == '+' || scan_peek(s) == '-') {
sign = *s->p == '-' ? -1 : 1;
s->p++;
digits = 6;
}
if (s->end - s->p < digits)
return 0;
int64_t v = 0;
for (int i = 0; i < digits; i++) {
unsigned char c = (unsigned char)s->p[i];
if (c < '0' || c > '9')
return 0;
v = v * 10 + (c - '0');
}
s->p += digits;
*year = sign * v;
return 1;
}
/* Sets *extended to whether the date was written with "-" separators. */
static int parse_date(iso8601_scanner *s, int64_t *days, int *extended) {
int64_t year;
int week, wday, mon, mday, yday;
if (!parse_year(s, &year))
return 0;
if (scan_eat(s, '-')) {
*extended = 1;
if (scan_designator(s, 'W')) {
return scan_digits(s, 2, &week) && scan_eat(s, '-') &&
scan_digits(s, 1, &wday) && week_to_days(year, week, wday, days);
}
switch (scan_count_digits(s)) {
case 3:
return scan_digits(s, 3, &yday) && ordinal_to_days(year, yday, days);
case 2:
return scan_digits(s, 2, &mon) && scan_eat(s, '-') &&
scan_digits(s, 2, &mday) && civil_to_days(year, mon, mday, days);
default:
return 0;
}
}
*extended = 0;
if (scan_designator(s, 'W')) {
return scan_digits(s, 2, &week) && scan_digits(s, 1, &wday) &&
week_to_days(year, week, wday, days);
}
switch (scan_count_digits(s)) {
case 4:
return scan_digits(s, 2, &mon) && scan_digits(s, 2, &mday) &&
civil_to_days(year, mon, mday, days);
case 3:
return scan_digits(s, 3, &yday) && ordinal_to_days(year, yday, days);
default:
/* A bare "YYYYMM" is ambiguous with "YYMMDD"; the standard forbids it. */
return 0;
}
}
/*
* Parses the time of day, storing the seconds since midnight in *secs. A
* time of "24:00:00" is midnight of the following day, which *carry reports.
*
* The minutes and seconds may be omitted, in which case the decimal fraction
* belongs to the lowest component that is present -- "23,5" is half past 23
* -- so *unit* records how many seconds that component is worth.
*/
static int parse_time(iso8601_scanner *s, int extended, double *secs,
int64_t *carry) {
int hh, mm = 0, ss = 0, unit = 3600;
if (!scan_digits(s, 2, &hh))
return 0;
if (extended ? scan_eat(s, ':') : scan_count_digits(s) >= 2) {
if (!scan_digits(s, 2, &mm))
return 0;
unit = 60;
if (extended ? scan_eat(s, ':') : scan_count_digits(s) >= 2) {
if (!scan_digits(s, 2, &ss))
return 0;
unit = 1;
}
}
double frac = 0;
if (scan_peek(s) == '.' || scan_peek(s) == ',') {
static const double pow10[] = {
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15
};
s->p++;
if (scan_count_digits(s) == 0)
return 0;
uint64_t num = 0;
int digits = 0;
while (scan_peek(s) >= '0' && scan_peek(s) <= '9') {
if (digits < 15) {
num = num * 10 + (uint64_t)(*s->p - '0');
digits++;
}
s->p++;
}
frac = (double)num / pow10[digits];
}
*carry = 0;
if (hh == 24) {
if (mm != 0 || ss != 0 || frac != 0)
return 0;
hh = 0;
*carry = 1;
} else if (hh > 24 || mm > 59 || ss > 60) {
return 0;
} else if (ss == 60) {
ss = 59;
}
*secs = hh * 3600 + mm * 60 + ss + frac * unit;
return 1;
}
/* An absent offset means UTC, which is what jq has always assumed. */
static int parse_offset(iso8601_scanner *s, int *offset) {
if (scan_designator(s, 'Z')) {
*offset = 0;
return 1;
}
int sign = scan_peek(s);
if (sign != '+' && sign != '-') {
*offset = 0;
return 1;
}
s->p++;
int oh, om = 0;
if (!scan_digits(s, 2, &oh))
return 0;
int had_colon = scan_eat(s, ':');
if (!scan_digits(s, 2, &om) && had_colon)
return 0;
if (oh > 23 || om > 59)
return 0;
*offset = (sign == '+' ? 1 : -1) * (oh * 3600 + om * 60);
return 1;
}
int iso8601_parse(const char *buf, size_t len, double *out) {
iso8601_scanner s = {buf, buf + len};
int64_t days, carry = 0;
int extended, offset = 0, sep;
double secs = 0;
if (!parse_date(&s, &days, &extended))
return 0;
sep = scan_peek(&s);
if (sep == 'T' || sep == 't' || sep == ' ') {
s.p++;
if (!parse_time(&s, extended, &secs, &carry) || !parse_offset(&s, &offset))
return 0;
}
if (!scan_at_end(&s))
return 0;
*out = (double)(days + carry) * 86400.0 + secs - offset;
return 1;
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef JQ_ISO8601_H
#define JQ_ISO8601_H
#include <stddef.h>
/*
* Parses [buf, buf + len) as an ISO 8601 date and time of day.
*
* On success stores the number of seconds since the Unix epoch in *out and
* returns 1. On failure returns 0 and leaves *out untouched.
*/
int iso8601_parse(const char *buf, size_t len, double *out);
#endif /* JQ_ISO8601_H */
+13 -8
View File
@@ -758,7 +758,7 @@ jv jv_number_negate(jv n) {
if (JVP_HAS_FLAGS(n, JVP_FLAGS_NUMBER_LITERAL)) {
jvp_literal_number* m = jvp_literal_number_alloc(jvp_dec_number_ptr(n)->digits);
decNumberMinus(&m->num_decimal, jvp_dec_number_ptr(n), DEC_CONTEXT());
decNumberCopyNegate(&m->num_decimal, jvp_dec_number_ptr(n));
jv r = {JVP_FLAGS_NUMBER_LITERAL, 0, 0, 0, {&m->refcnt}};
return r;
}
@@ -1210,12 +1210,18 @@ static pthread_once_t hash_seed_once = PTHREAD_ONCE_INIT;
static void jvp_hash_seed_init(void) {
uint32_t seed;
#if defined(HAVE_ARC4RANDOM)
seed = arc4random();
#elif defined(HAVE_GETENTROPY)
if (getentropy(&seed, sizeof(seed)) != 0)
seed = (uint32_t)getpid() ^ (uint32_t)time(NULL);
#else
/* Prefer getentropy() over arc4random(): glibc's arc4random() aborts the
* process when the kernel lacks getrandom(2) (#3584), while getentropy()
* merely fails, letting us fall back to /dev/urandom. */
#if defined(HAVE_GETENTROPY)
if (getentropy(&seed, sizeof(seed)) == 0) {
hash_seed = seed;
return;
}
#elif defined(HAVE_ARC4RANDOM)
hash_seed = arc4random();
return;
#endif
int fd = open("/dev/urandom", O_RDONLY);
if (fd >= 0) {
if (read(fd, &seed, sizeof(seed)) != 4)
@@ -1224,7 +1230,6 @@ static void jvp_hash_seed_init(void) {
} else {
seed = (uint32_t)getpid() ^ (uint32_t)time(NULL);
}
#endif
hash_seed = seed;
}
+15 -2
View File
@@ -43,17 +43,23 @@ typedef struct {
} jv;
/*
* All jv_* functions consume (decref) input and produce (incref) output
* Except jv_copy
* Unless noted otherwise, functions consume their jv arguments. Returned jv
* values are owned. Pass jv_copy(value) to retain a value across a consuming
* call, and release each owned value with jv_free() when no longer needed.
* Borrowed arguments are not consumed; the caller retains ownership.
* Returned jv values are owned even when the arguments are borrowed.
*/
/* These functions borrow their jv arguments. */
jv_kind jv_get_kind(jv);
const char* jv_kind_name(jv_kind);
static int jv_is_valid(jv x) { return jv_get_kind(x) != JV_KIND_INVALID; }
/* Borrows its argument and returns a new reference to the same value. */
jv jv_copy(jv);
void jv_free(jv);
/* Borrows its argument. */
int jv_get_refcnt(jv);
int jv_equal(jv, jv);
@@ -72,12 +78,15 @@ jv jv_bool(int);
jv jv_number(double);
jv jv_number_with_literal(const char*);
/* These functions borrow their jv arguments. */
double jv_number_value(jv);
int jv_is_integer(jv);
jv jv_number_abs(jv);
jv jv_number_negate(jv);
/* Borrows its argument. */
int jv_number_has_literal(jv);
/* Borrows its argument; the returned string belongs to the number. */
const char* jv_number_get_literal(jv);
jv jv_array(void);
@@ -127,6 +136,7 @@ jv jv_string_empty(int len);
int jv_string_length_bytes(jv);
int jv_string_length_codepoints(jv);
unsigned long jv_string_hash(jv);
/* Borrows its argument; the returned string belongs to the value. */
const char* jv_string_value(jv);
jv jv_string_indexes(jv j, jv k);
jv jv_string_slice(jv j, int start, int end);
@@ -150,6 +160,7 @@ int jv_object_length(jv object);
jv jv_object_merge(jv, jv);
jv jv_object_merge_recursive(jv, jv);
/* Object iteration borrows the object; returned keys and values are owned. */
int jv_object_iter(jv);
int jv_object_iter_next(jv, int);
int jv_object_iter_valid(jv, int);
@@ -213,6 +224,7 @@ jv jv_object_iter_value(jv, int);
/* Borrows its argument. */
int jv_get_refcnt(jv);
enum jv_print_flags {
@@ -232,6 +244,7 @@ enum jv_print_flags {
((n) < 0 || (n) > 7 ? JV_PRINT_TAB | JV_PRINT_PRETTY : (n) << 8 | JV_PRINT_PRETTY)
void jv_dumpf(jv, FILE *f, int flags);
void jv_dump(jv, int flags);
/* Borrows its argument, unlike jv_dump() and jv_dumpf(). */
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);
+8 -4
View File
@@ -260,11 +260,14 @@ jv jv_has(jv t, jv k) {
jv_free(elem);
} else if (jv_get_kind(t) == JV_KIND_ARRAY &&
jv_get_kind(k) == JV_KIND_NUMBER) {
if (jvp_number_is_nan(k)) {
double nv = jv_number_value(k);
if (isnan(nv)) {
jv_free(t);
ret = jv_false();
} else {
jv elem = jv_array_get(t, (int)jv_number_value(k));
if (nv < INT_MIN) nv = INT_MIN;
if (nv > INT_MAX) nv = INT_MAX;
jv elem = jv_array_get(t, (int)nv);
ret = jv_bool(jv_is_valid(elem));
jv_free(elem);
}
@@ -294,9 +297,10 @@ static jv jv_dels(jv t, jv keys) {
jv starts = jv_array(), ends = jv_array();
jv_array_foreach(keys, i, key) {
if (jv_get_kind(key) == JV_KIND_NUMBER) {
if (jvp_number_is_nan(key)) {
double nv = jv_number_value(key);
if (isnan(nv) || nv < INT_MIN || nv > INT_MAX) {
jv_free(key);
} else if (jv_number_value(key) < 0) {
} else if (nv < 0) {
neg_keys = jv_array_append(neg_keys, key);
} else {
nonneg_keys = jv_array_append(nonneg_keys, key);
+13 -2
View File
@@ -43,6 +43,7 @@ jv jv_load_file(const char* filename, int raw) {
// buffer, we need to be able to read the remainder of a sequence and add that
// before appending.
char buf[4096 + 4];
int at_file_start = 1;
while (!feof(file) && !ferror(file)) {
size_t n = fread(buf, 1, sizeof(buf) - 4, file);
if (n == 0)
@@ -55,12 +56,22 @@ jv jv_load_file(const char* filename, int raw) {
n += fread(end, 1, len, file);
}
char *p = buf;
if (at_file_start) {
// Strip UTF-8 BOM at the start of the file
if (n >= 3 && !memcmp(buf, "\xEF\xBB\xBF", 3)) {
p += 3;
n -= 3;
}
at_file_start = 0;
}
if (raw) {
data = jv_string_append_buf(data, buf, n);
data = jv_string_append_buf(data, p, n);
if (!jv_is_valid(data))
break;
} else {
jv_parser_set_buf(parser, buf, n, !feof(file));
jv_parser_set_buf(parser, p, n, !feof(file));
jv value;
while (jv_is_valid((value = jv_parser_next(parser))))
data = jv_array_append(data, value);
+8 -28
View File
@@ -37,7 +37,6 @@ struct jv_parser {
int curr_buf_pos;
int curr_buf_is_partial;
int eof;
unsigned bom_strip_position;
int flags;
@@ -90,7 +89,6 @@ static void parser_init(struct jv_parser* p, int flags) {
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;
@@ -563,6 +561,11 @@ typedef enum {
static chclass classify(char c) {
switch (c) {
case '\0':
// RFC 8259 forbids raw NUL in JSON text. Treating it as a literal lets it
// slip into the token buffer, where check_literal() reads the buffer as a
// NUL-terminated C string and silently truncates the token. Reject it.
return INVALID;
case ' ':
case '\t':
case '\r':
@@ -724,8 +727,6 @@ void jv_parser_free(struct jv_parser* 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;
@@ -735,22 +736,6 @@ int jv_parser_remaining(struct jv_parser* p) {
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 (length > 0 && p->bom_strip_position < sizeof(UTF8_BOM)) {
if ((unsigned char)*buf == UTF8_BOM[p->bom_strip_position]) {
// matched a BOM character
buf++;
length--;
p->bom_strip_position++;
} else {
if (p->bom_strip_position == 0) {
// no BOM in this document
p->bom_strip_position = sizeof(UTF8_BOM);
} else {
// malformed BOM (prefix present, rest missing)
p->bom_strip_position = 0xff;
}
}
}
p->curr_buf = buf;
p->curr_buf_length = length;
p->curr_buf_pos = 0;
@@ -774,12 +759,6 @@ jv jv_parser_next(struct jv_parser* p) {
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;
@@ -805,10 +784,11 @@ jv jv_parser_next(struct jv_parser* p) {
} else if (msg) {
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);
// Skip to the next RS. This must come after parser_reset(), which
// sets the state back to JV_PARSER_NORMAL.
p->st = JV_PARSER_WAITING_FOR_RS;
return value;
}
value = make_error(p, "%s at line %d, column %d", msg, p->line, p->column);
+13 -25
View File
@@ -3,12 +3,6 @@
#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_dtoa_tsd.h"
@@ -99,26 +93,9 @@ 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) {
wchar_t *ws;
size_t wl;
if (len == -1)
len = strlen(s);
wl = MultiByteToWideChar(CP_UTF8, 0, s, len, NULL, 0);
ws = jv_mem_calloc(wl + 1, sizeof(*ws));
if (!ws)
return;
wl = MultiByteToWideChar(CP_UTF8, 0, s, len, ws, wl + 1);
ws[wl] = 0;
WriteConsoleW((HANDLE)_get_osfhandle(fileno(fout)), ws, wl, NULL, NULL);
free(ws);
} else
fwrite(s, 1, len, fout);
#else
fwrite(s, 1, len, fout);
#endif
priv_fwrite(s, len, fout, is_tty); /* see util.h */
}
}
@@ -149,7 +126,18 @@ static void jvp_dump_string(jv str, int ascii_only, FILE* F, jv* S, int T) {
int c = 0;
char buf[32];
put_char('"', F, S, T);
while ((i = jvp_utf8_next((cstart = i), end, &c))) {
while (i < end) {
// Write each run of bytes that need no escaping with a single call.
for (cstart = i; cstart < end; cstart++) {
unsigned char b = *cstart;
if (b < 0x20 || b == '"' || b == '\\' || b == 0x7F || (ascii_only && b >= 0x80))
break;
}
if (cstart > i)
put_buf(i, cstart - i, F, S, T);
if (cstart == end)
break;
i = jvp_utf8_next(cstart, end, &c);
assert(c != -1);
int unicode_escape = 0;
if (0x20 <= c && c <= 0x7E) {
+10 -12
View File
@@ -27,24 +27,22 @@ const char* jvp_utf8_backtrack(const char* start, const char* min, int *missing_
return start;
}
const char* jvp_utf8_next(const char* in, const char* end, int* codepoint_ret) {
assert(in <= end);
if (in == end) {
return 0;
}
// The rest of jvp_utf8_next(), for a first byte that is not ASCII.
const char* jvp_utf8_next_multibyte(const char* in, const char* end, int* codepoint_ret) {
assert(in < end);
int codepoint = -1;
unsigned char first = (unsigned char)in[0];
assert(first & 0x80);
int length = utf8_coding_length[first];
if ((first & 0x80) == 0) {
/* Fast-path for ASCII */
codepoint = first;
length = 1;
} else if (length == 0 || length == UTF8_CONTINUATION_BYTE) {
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 (length > end - in) {
/* String ends before UTF8 sequence ends */
length = end - in;
/* String ends before UTF8 sequence ends, so skip only its continuation bytes */
for (length = 1; in + length < end; length++) {
if (utf8_coding_length[(unsigned char)in[length]] != UTF8_CONTINUATION_BYTE)
break;
}
} else {
codepoint = ((unsigned)in[0]) & utf8_coding_bits[first];
for (int i=1; i<length; i++) {
+18 -1
View File
@@ -1,10 +1,27 @@
#ifndef JV_UNICODE_H
#define JV_UNICODE_H
#include <assert.h>
const char* jvp_utf8_backtrack(const char* start, const char* min, int *missing_bytes);
const char* jvp_utf8_next(const char* in, const char* end, int* codepoint);
const char* jvp_utf8_next_multibyte(const char* in, const char* end, int* codepoint);
int jvp_utf8_is_valid(const char* in, const char* end);
// Decode one codepoint. ASCII is handled here so that callers looping over
// a string do not make a call per byte; everything else goes to
// jvp_utf8_next_multibyte().
static inline const char* jvp_utf8_next(const char* in, const char* end, int* codepoint) {
if (in >= end) {
assert(in == end);
return 0;
}
if (!(*in & 0x80)) {
*codepoint = (unsigned char)*in;
return in + 1;
}
return jvp_utf8_next_multibyte(in, end, codepoint);
}
int jvp_utf8_decode_length(char startchar);
int jvp_utf8_encode_length(int codepoint);
Generated
+182 -187
View File
@@ -1,6 +1,6 @@
#line 2 "src/lexer.c"
#line 1 "src/lexer.c"
#line 4 "src/lexer.c"
#line 3 "src/lexer.c"
#define YY_INT_ALIGNED short int
@@ -573,8 +573,8 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
#define YY_NUM_RULES 53
#define YY_END_OF_BUFFER 54
#define YY_NUM_RULES 52
#define YY_END_OF_BUFFER 53
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -582,26 +582,26 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static const flex_int16_t yy_accept[171] =
static const flex_int16_t yy_accept[168] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 54, 52, 51, 51, 52, 42,
1, 37, 37, 38, 39, 37, 37, 37, 37, 37,
37, 41, 37, 37, 37, 37, 52, 48, 48, 48,
48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
37, 46, 46, 44, 47, 2, 3, 2, 2, 51,
4, 50, 50, 31, 29, 27, 28, 35, 41, 49,
20, 30, 41, 41, 0, 33, 5, 34, 0, 40,
48, 0, 48, 6, 48, 48, 48, 48, 48, 48,
11, 48, 48, 48, 48, 16, 48, 48, 48, 26,
0, 0, 0, 0, 53, 51, 50, 50, 51, 41,
1, 36, 36, 37, 38, 36, 36, 36, 36, 36,
36, 40, 36, 36, 36, 51, 47, 47, 47, 47,
47, 47, 47, 47, 47, 47, 47, 47, 47, 36,
45, 45, 43, 46, 2, 3, 2, 2, 50, 4,
49, 49, 31, 29, 27, 28, 35, 40, 48, 20,
30, 40, 40, 0, 33, 5, 34, 39, 47, 0,
47, 6, 47, 47, 47, 47, 47, 47, 11, 47,
47, 47, 47, 16, 47, 47, 47, 26, 45, 44,
46, 45, 43, 45, 3, 2, 0, 50, 0, 50,
49, 32, 41, 0, 41, 36, 0, 15, 48, 48,
10, 48, 48, 17, 48, 48, 48, 48, 48, 48,
48, 21, 0, 45, 0, 50, 48, 48, 48, 14,
13, 48, 48, 48, 48, 48, 48, 12, 45, 50,
24, 22, 48, 48, 48, 23, 48, 48, 45, 50,
48, 7, 48, 9, 18, 50, 19, 8, 25, 0
42, 44, 3, 2, 0, 49, 0, 49, 48, 32,
40, 0, 40, 0, 15, 47, 47, 10, 47, 47,
17, 47, 47, 47, 47, 47, 47, 47, 21, 0,
44, 0, 49, 47, 47, 47, 14, 13, 47, 47,
47, 47, 47, 47, 12, 44, 49, 24, 22, 47,
47, 47, 23, 47, 47, 44, 49, 47, 7, 47,
9, 18, 49, 19, 8, 25, 0
} ;
static const YY_CHAR yy_ec[256] =
@@ -646,147 +646,147 @@ static const YY_CHAR yy_meta[54] =
1, 1, 1
} ;
static const flex_int16_t yy_base[186] =
static const flex_int16_t yy_base[183] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51, 52, 56, 58, 340, 341, 61, 64, 317, 341,
341, 307, 315, 341, 341, 314, 313, 341, 312, 53,
53, 56, 311, 310, 309, 313, 0, 310, 54, 57,
58, 59, 63, 65, 70, 67, 72, 69, 60, 79,
306, 0, 0, 341, 83, 341, 341, 324, 107, 116,
341, 307, 83, 341, 341, 341, 341, 341, 103, 0,
303, 341, 104, 108, 128, 341, 341, 341, 307, 0,
304, 301, 110, 297, 114, 75, 115, 108, 118, 119,
293, 109, 123, 129, 132, 290, 137, 130, 139, 341,
51, 52, 56, 58, 338, 339, 61, 64, 315, 339,
339, 305, 313, 339, 339, 312, 311, 339, 310, 53,
53, 56, 309, 308, 307, 0, 309, 54, 57, 58,
59, 63, 65, 70, 67, 72, 69, 60, 79, 305,
0, 0, 339, 83, 339, 339, 323, 107, 116, 339,
306, 83, 339, 339, 339, 339, 339, 103, 0, 302,
339, 104, 108, 128, 339, 339, 339, 0, 304, 301,
110, 297, 114, 75, 115, 108, 118, 119, 293, 109,
123, 129, 132, 290, 137, 130, 139, 339, 0, 276,
0, 276, 341, 273, 341, 341, 297, 278, 265, 140,
0, 341, 142, 261, 258, 341, 0, 252, 142, 145,
250, 149, 144, 247, 151, 152, 154, 156, 157, 158,
165, 245, 172, 231, 0, 166, 222, 164, 171, 221,
220, 169, 172, 174, 175, 178, 179, 218, 206, 180,
215, 214, 181, 183, 192, 213, 184, 186, 201, 193,
198, 210, 206, 209, 89, 207, 86, 81, 37, 341,
242, 250, 253, 259, 264, 269, 277, 285, 290, 295,
300, 302, 307, 311, 315
339, 273, 339, 339, 297, 278, 265, 140, 0, 339,
142, 261, 258, 0, 252, 142, 145, 250, 149, 144,
247, 151, 152, 154, 156, 157, 158, 165, 245, 172,
231, 0, 166, 222, 164, 171, 221, 220, 169, 172,
174, 175, 178, 179, 218, 206, 180, 215, 214, 181,
183, 192, 213, 184, 186, 201, 193, 198, 210, 206,
209, 89, 207, 86, 81, 37, 339, 242, 250, 253,
259, 264, 269, 277, 285, 290, 295, 300, 302, 307,
311, 315
} ;
static const flex_int16_t yy_def[186] =
static const flex_int16_t yy_def[183] =
{ 0,
170, 1, 1, 1, 1, 1, 1, 1, 1, 1,
171, 171, 172, 172, 170, 170, 170, 170, 170, 170,
170, 173, 170, 170, 170, 170, 170, 170, 170, 174,
170, 170, 170, 170, 170, 170, 175, 176, 176, 176,
176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
170, 177, 177, 170, 178, 170, 170, 170, 170, 170,
170, 179, 179, 170, 170, 170, 170, 170, 170, 180,
170, 170, 170, 170, 170, 170, 170, 170, 170, 175,
176, 170, 176, 176, 176, 176, 176, 176, 176, 176,
176, 176, 176, 176, 176, 176, 176, 176, 176, 170,
167, 1, 1, 1, 1, 1, 1, 1, 1, 1,
168, 168, 169, 169, 167, 167, 167, 167, 167, 167,
167, 170, 167, 167, 167, 167, 167, 167, 167, 171,
167, 167, 167, 167, 167, 172, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 167,
174, 174, 167, 175, 167, 167, 167, 167, 167, 167,
176, 176, 167, 167, 167, 167, 167, 167, 177, 167,
167, 167, 167, 167, 167, 167, 167, 172, 173, 167,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 167, 174, 167,
177, 170, 170, 181, 170, 170, 170, 179, 170, 179,
180, 170, 170, 170, 170, 170, 182, 176, 176, 176,
176, 176, 176, 176, 176, 176, 176, 176, 176, 176,
176, 176, 178, 183, 173, 179, 176, 176, 176, 176,
176, 176, 176, 176, 176, 176, 176, 176, 184, 179,
176, 176, 176, 176, 176, 176, 176, 176, 185, 179,
176, 176, 176, 176, 176, 179, 176, 176, 179, 0,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170
167, 178, 167, 167, 167, 176, 167, 176, 177, 167,
167, 167, 167, 179, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 175,
180, 170, 176, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 181, 176, 173, 173, 173,
173, 173, 173, 173, 173, 182, 176, 173, 173, 173,
173, 173, 176, 173, 173, 176, 0, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167
} ;
static const flex_int16_t yy_nxt[395] =
static const flex_int16_t yy_nxt[393] =
{ 0,
16, 17, 18, 17, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 28, 28,
33, 34, 35, 36, 37, 38, 38, 24, 16, 25,
38, 39, 40, 41, 42, 43, 44, 38, 45, 38,
46, 47, 38, 48, 38, 49, 38, 50, 38, 38,
24, 51, 25, 53, 53, 109, 54, 54, 57, 58,
57, 58, 60, 60, 60, 60, 60, 60, 68, 71,
69, 73, 82, 74, 72, 82, 82, 82, 82, 55,
55, 82, 75, 82, 59, 82, 59, 82, 82, 86,
82, 75, 103, 82, 87, 97, 83, 82, 94, 82,
33, 34, 35, 28, 36, 37, 37, 24, 16, 25,
37, 38, 39, 40, 41, 42, 43, 37, 44, 37,
45, 46, 37, 47, 37, 48, 37, 49, 37, 37,
24, 50, 25, 52, 52, 107, 53, 53, 56, 57,
56, 57, 59, 59, 59, 59, 59, 59, 67, 70,
68, 72, 80, 73, 71, 80, 80, 80, 80, 54,
54, 80, 74, 80, 58, 80, 58, 80, 80, 84,
80, 74, 101, 80, 85, 95, 81, 80, 92, 80,
84, 109, 85, 88, 82, 89, 91, 82, 90, 106,
107, 92, 93, 110, 96, 95, 98, 60, 60, 60,
69, 113, 120, 73, 99, 74, 82, 82, 82, 75,
75, 104, 82, 82, 75, 106, 82, 82, 75, 75,
114, 82, 114, 75, 118, 115, 122, 82, 82, 119,
82, 121, 124, 126, 123, 82, 127, 82, 109, 113,
82, 128, 82, 82, 125, 131, 129, 82, 75, 82,
82, 130, 82, 138, 82, 82, 82, 75, 139, 141,
136, 170, 82, 82, 109, 140, 142, 82, 132, 82,
82, 145, 82, 82, 144, 143, 82, 82, 109, 82,
82, 107, 83, 86, 80, 87, 89, 80, 88, 104,
105, 90, 91, 108, 94, 93, 96, 59, 59, 59,
68, 111, 117, 72, 97, 73, 80, 80, 80, 74,
74, 102, 80, 80, 74, 104, 80, 80, 74, 74,
112, 80, 112, 74, 115, 113, 119, 80, 80, 116,
80, 118, 121, 123, 120, 80, 124, 80, 107, 111,
80, 125, 80, 80, 122, 128, 126, 80, 74, 80,
80, 127, 80, 135, 80, 80, 80, 74, 136, 138,
133, 167, 80, 80, 107, 137, 139, 80, 129, 80,
80, 142, 80, 80, 141, 140, 80, 80, 107, 80,
153, 82, 82, 151, 82, 146, 147, 148, 152, 150,
82, 109, 158, 160, 161, 156, 82, 154, 157, 164,
104, 165, 155, 166, 82, 109, 163, 82, 82, 133,
162, 82, 82, 82, 133, 167, 82, 169, 82, 82,
82, 168, 52, 52, 52, 52, 52, 52, 52, 52,
56, 56, 56, 56, 56, 56, 56, 56, 62, 133,
62, 70, 70, 82, 70, 82, 70, 80, 82, 80,
82, 80, 81, 81, 81, 115, 81, 101, 115, 101,
101, 101, 101, 135, 101, 102, 102, 102, 102, 102,
102, 102, 102, 108, 108, 108, 109, 108, 111, 106,
150, 80, 80, 148, 80, 143, 144, 145, 149, 147,
80, 107, 155, 157, 158, 153, 80, 151, 154, 161,
102, 162, 152, 163, 80, 107, 160, 80, 80, 130,
159, 80, 80, 80, 130, 164, 80, 166, 80, 80,
80, 165, 51, 51, 51, 51, 51, 51, 51, 51,
55, 55, 55, 55, 55, 55, 55, 55, 61, 130,
61, 69, 69, 80, 69, 80, 69, 78, 80, 78,
80, 78, 79, 79, 79, 113, 79, 99, 113, 99,
99, 99, 99, 132, 99, 100, 100, 100, 100, 100,
100, 100, 100, 106, 106, 106, 107, 106, 109, 104,
111, 133, 111, 134, 133, 134, 134, 137, 82, 137,
149, 82, 149, 149, 159, 82, 159, 159, 102, 117,
102, 102, 82, 116, 112, 109, 105, 100, 82, 79,
78, 77, 76, 67, 66, 65, 64, 63, 61, 170,
15, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170
109, 130, 109, 131, 130, 131, 131, 134, 80, 134,
146, 80, 146, 146, 156, 80, 156, 156, 100, 114,
100, 100, 80, 110, 107, 103, 98, 80, 77, 76,
75, 66, 65, 64, 63, 62, 60, 167, 15, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167
} ;
static const flex_int16_t yy_chk[395] =
static const flex_int16_t yy_chk[393] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 11, 12, 169, 11, 12, 13, 13,
1, 1, 1, 11, 12, 166, 11, 12, 13, 13,
14, 14, 17, 17, 17, 18, 18, 18, 30, 31,
30, 32, 39, 32, 31, 40, 41, 42, 49, 11,
12, 43, 32, 44, 13, 46, 14, 48, 45, 41,
47, 32, 55, 86, 42, 49, 39, 50, 46, 168,
30, 32, 38, 32, 31, 39, 40, 41, 48, 11,
12, 42, 32, 43, 13, 45, 14, 47, 44, 40,
46, 32, 54, 84, 41, 48, 38, 49, 45, 165,
39, 63, 40, 43, 167, 43, 45, 165, 44, 59,
59, 45, 45, 63, 48, 47, 50, 60, 60, 60,
69, 73, 86, 74, 50, 74, 88, 92, 83, 69,
73, 55, 85, 87, 74, 59, 89, 90, 69, 73,
75, 93, 75, 74, 83, 75, 88, 94, 98, 85,
95, 87, 89, 92, 88, 97, 93, 99, 110, 113,
119, 94, 123, 120, 90, 98, 95, 122, 113, 125,
126, 97, 127, 119, 128, 129, 130, 113, 120, 123,
110, 133, 138, 131, 136, 122, 125, 142, 99, 139,
143, 128, 144, 145, 127, 126, 146, 147, 150, 153,
38, 62, 39, 42, 164, 42, 44, 162, 43, 58,
58, 44, 44, 62, 47, 46, 49, 59, 59, 59,
68, 72, 84, 73, 49, 73, 86, 90, 81, 68,
72, 54, 83, 85, 73, 58, 87, 88, 68, 72,
74, 91, 74, 73, 81, 74, 86, 92, 96, 83,
93, 85, 87, 90, 86, 95, 91, 97, 108, 111,
116, 92, 120, 117, 88, 96, 93, 119, 111, 122,
123, 95, 124, 116, 125, 126, 127, 111, 117, 120,
108, 130, 135, 128, 133, 119, 122, 139, 97, 136,
140, 125, 141, 142, 124, 123, 143, 144, 147, 150,
142, 154, 157, 138, 158, 129, 130, 131, 139, 136,
155, 160, 147, 150, 153, 145, 161, 143, 146, 157,
133, 158, 144, 160, 163, 166, 155, 164, 162, 159,
154, 156, 152, 151, 149, 161, 148, 166, 141, 140,
137, 163, 171, 171, 171, 171, 171, 171, 171, 171,
172, 172, 172, 172, 172, 172, 172, 172, 173, 134,
173, 174, 174, 132, 174, 124, 174, 175, 121, 175,
118, 175, 176, 176, 176, 115, 176, 177, 114, 177,
177, 177, 177, 109, 177, 178, 178, 178, 178, 178,
178, 178, 178, 179, 179, 179, 108, 179, 180, 107,
139, 151, 154, 135, 155, 126, 127, 128, 136, 133,
152, 157, 144, 147, 150, 142, 158, 140, 143, 154,
130, 155, 141, 157, 160, 163, 152, 161, 159, 156,
151, 153, 149, 148, 146, 158, 145, 163, 138, 137,
134, 160, 168, 168, 168, 168, 168, 168, 168, 168,
169, 169, 169, 169, 169, 169, 169, 169, 170, 131,
170, 171, 171, 129, 171, 121, 171, 172, 118, 172,
115, 172, 173, 173, 173, 113, 173, 174, 112, 174,
174, 174, 174, 107, 174, 175, 175, 175, 175, 175,
175, 175, 175, 176, 176, 176, 106, 176, 177, 105,
180, 104, 180, 181, 102, 181, 181, 182, 96, 182,
183, 91, 183, 183, 184, 84, 184, 184, 185, 82,
185, 185, 81, 79, 71, 62, 58, 51, 38, 36,
35, 34, 33, 29, 27, 26, 23, 22, 19, 15,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
170, 170, 170, 170
177, 102, 177, 178, 100, 178, 178, 179, 94, 179,
180, 89, 180, 180, 181, 82, 181, 181, 182, 80,
182, 182, 79, 70, 61, 57, 50, 37, 35, 34,
33, 29, 27, 26, 23, 22, 19, 15, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167
} ;
@@ -814,14 +814,14 @@ struct lexer_param;
yyset_extra(yylloc->end, yyscanner); \
} while (0);
#line 818 "src/lexer.c"
#line 817 "src/lexer.c"
#line 26 "src/lexer.l"
static int enter(int opening, int state, yyscan_t yyscanner);
static int try_exit(int closing, int state, yyscan_t yyscanner);
#line 823 "src/lexer.c"
#line 822 "src/lexer.c"
#define YY_NO_INPUT 1
#line 825 "src/lexer.c"
#line 824 "src/lexer.c"
#define INITIAL 0
#define IN_PAREN 1
@@ -1116,7 +1116,7 @@ YY_DECL
#line 39 "src/lexer.l"
#line 1120 "src/lexer.c"
#line 1119 "src/lexer.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -1143,13 +1143,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 171 )
if ( yy_current_state >= 168 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 341 );
while ( yy_base[yy_current_state] != 339 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -1359,69 +1359,64 @@ YY_RULE_SETUP
case 36:
YY_RULE_SETUP
#line 80 "src/lexer.l"
{ return ALTERNATION; }
{ return yytext[0];}
YY_BREAK
case 37:
YY_RULE_SETUP
#line 81 "src/lexer.l"
{ return yytext[0];}
YY_BREAK
case 38:
YY_RULE_SETUP
#line 83 "src/lexer.l"
#line 82 "src/lexer.l"
{
return enter(yytext[0], YY_START, yyscanner);
}
YY_BREAK
case 39:
case 38:
YY_RULE_SETUP
#line 87 "src/lexer.l"
#line 86 "src/lexer.l"
{
return try_exit(yytext[0], YY_START, yyscanner);
}
YY_BREAK
case 40:
case 39:
YY_RULE_SETUP
#line 91 "src/lexer.l"
#line 90 "src/lexer.l"
{
yylval->literal = jv_string_sized(yytext + 1, yyleng - 1); return FORMAT;
}
YY_BREAK
case 41:
case 40:
YY_RULE_SETUP
#line 95 "src/lexer.l"
#line 94 "src/lexer.l"
{
yylval->literal = jv_parse_sized(yytext, yyleng); return LITERAL;
}
YY_BREAK
case 42:
case 41:
YY_RULE_SETUP
#line 99 "src/lexer.l"
#line 98 "src/lexer.l"
{
yy_push_state(IN_QQSTRING, yyscanner);
return QQSTRING_START;
}
YY_BREAK
case 43:
case 42:
YY_RULE_SETUP
#line 105 "src/lexer.l"
#line 104 "src/lexer.l"
{
return enter(QQSTRING_INTERP_START, YY_START, yyscanner);
}
YY_BREAK
case 44:
case 43:
YY_RULE_SETUP
#line 108 "src/lexer.l"
#line 107 "src/lexer.l"
{
yy_pop_state(yyscanner);
return QQSTRING_END;
}
YY_BREAK
case 45:
/* rule 45 can match eol */
case 44:
/* rule 44 can match eol */
YY_RULE_SETUP
#line 112 "src/lexer.l"
#line 111 "src/lexer.l"
{
/* pass escapes to the json parser */
jv escapes = jv_string_fmt("\"%.*s\"", (int)yyleng, yytext);
@@ -1430,55 +1425,55 @@ YY_RULE_SETUP
return QQSTRING_TEXT;
}
YY_BREAK
case 46:
/* rule 46 can match eol */
case 45:
/* rule 45 can match eol */
YY_RULE_SETUP
#line 119 "src/lexer.l"
#line 118 "src/lexer.l"
{
yylval->literal = jv_string_sized(yytext, yyleng);
return QQSTRING_TEXT;
}
YY_BREAK
case 47:
case 46:
YY_RULE_SETUP
#line 123 "src/lexer.l"
#line 122 "src/lexer.l"
{
return INVALID_CHARACTER;
}
YY_BREAK
case 47:
YY_RULE_SETUP
#line 128 "src/lexer.l"
{ yylval->literal = jv_string(yytext); return IDENT;}
YY_BREAK
case 48:
YY_RULE_SETUP
#line 129 "src/lexer.l"
{ yylval->literal = jv_string(yytext); return IDENT;}
{ yylval->literal = jv_string(yytext+1); return FIELD;}
YY_BREAK
case 49:
YY_RULE_SETUP
#line 130 "src/lexer.l"
{ yylval->literal = jv_string(yytext+1); return FIELD;}
YY_BREAK
case 50:
YY_RULE_SETUP
#line 131 "src/lexer.l"
{ yylval->literal = jv_string(yytext+1); return BINDING;}
YY_BREAK
case 51:
/* rule 51 can match eol */
case 50:
/* rule 50 can match eol */
YY_RULE_SETUP
#line 133 "src/lexer.l"
#line 132 "src/lexer.l"
{}
YY_BREAK
case 51:
YY_RULE_SETUP
#line 134 "src/lexer.l"
{ return INVALID_CHARACTER; }
YY_BREAK
case 52:
YY_RULE_SETUP
#line 135 "src/lexer.l"
{ return INVALID_CHARACTER; }
YY_BREAK
case 53:
YY_RULE_SETUP
#line 137 "src/lexer.l"
#line 136 "src/lexer.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
#line 1482 "src/lexer.c"
#line 1476 "src/lexer.c"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(IN_PAREN):
case YY_STATE_EOF(IN_BRACKET):
@@ -1782,7 +1777,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 171 )
if ( yy_current_state >= 168 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1811,11 +1806,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 171 )
if ( yy_current_state >= 168 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 170);
yy_is_jam = (yy_current_state == 167);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
@@ -2650,7 +2645,7 @@ static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
#line 137 "src/lexer.l"
#line 136 "src/lexer.l"
/* perhaps these should be calls... */
/*
Generated
+4 -4
View File
@@ -2,9 +2,9 @@
#define jq_yyHEADER_H 1
#define jq_yyIN_HEADER 1
#line 6 "src/lexer.h"
#line 5 "src/lexer.h"
#line 8 "src/lexer.h"
#line 7 "src/lexer.h"
#define YY_INT_ALIGNED short int
@@ -732,9 +732,9 @@ extern int yylex \
#undef yyTABLES_NAME
#endif
#line 137 "src/lexer.l"
#line 136 "src/lexer.l"
#line 739 "src/lexer.h"
#line 738 "src/lexer.h"
#undef jq_yyIN_HEADER
#endif /* jq_yyHEADER_H */
-1
View File
@@ -77,7 +77,6 @@ struct lexer_param;
"<=" { return LESSEQ; }
">=" { return GREATEREQ; }
".." { return REC; }
"?//" { return ALTERNATION; }
"."|"?"|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"%"|"\$"|"<"|">" { return yytext[0];}
"["|"{"|"(" {
+30 -23
View File
@@ -23,11 +23,15 @@
struct lib_entry {
char *name;
block def;
int loading;
};
struct loading_lib {
const char *name;
struct loading_lib *next;
};
struct lib_loading_state {
struct lib_entry *entries;
uint64_t ct;
struct loading_lib *loading;
};
static int load_library(jq_state *jq, jv lib_path,
int is_data, int raw, int optional,
@@ -312,16 +316,6 @@ static int process_dependencies(jq_state *jq, jv jq_origin, jv lib_origin, block
}
if (state_idx < lib_state->ct) { // Found
if (lib_state->entries[state_idx].loading) {
jq_report_error(jq, jv_string_fmt("jq: error: circular import of %s\n",
jv_string_value(resolved)));
jv_free(resolved);
jv_free(as);
jv_free(deps);
jv_free(jq_origin);
jv_free(lib_origin);
return 1;
}
jv_free(resolved);
// Bind the library to the program
bk = block_bind_library(lib_state->entries[state_idx].def, bk, OP_IS_CALL_PSEUDO, as_str);
@@ -351,11 +345,20 @@ static int load_library(jq_state *jq, jv lib_path, int is_data, int raw, int opt
struct locfile* src = NULL;
block program;
jv data;
for (struct loading_lib *l = lib_state->loading; l; l = l->next) {
if (strcmp(l->name, jv_string_value(lib_path)) == 0) {
jq_report_error(jq, jv_string_fmt("jq: error: circular import of %s\n",
jv_string_value(lib_path)));
*out_block = gen_noop();
jv_free(lib_path);
return 1;
}
}
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;
uint64_t state_idx;
if (!jv_is_valid(data)) {
program = gen_noop();
if (!optional) {
@@ -373,29 +376,33 @@ static int load_library(jq_state *jq, jv lib_path, int is_data, int raw, int opt
lib_state->entries = jv_mem_realloc(lib_state->entries, lib_state->ct * sizeof(struct lib_entry));
lib_state->entries[state_idx].name = strdup(jv_string_value(lib_path));
lib_state->entries[state_idx].def = program;
lib_state->entries[state_idx].loading = 0;
} 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);
locfile_free(src);
if (nerrors == 0) {
// Register the library before processing its dependencies so that
// circular imports can be detected.
state_idx = lib_state->ct++;
lib_state->entries = jv_mem_realloc(lib_state->entries, lib_state->ct * sizeof(struct lib_entry));
lib_state->entries[state_idx].name = strdup(jv_string_value(lib_path));
lib_state->entries[state_idx].def = gen_noop();
lib_state->entries[state_idx].loading = 1;
// Mark the library as being loaded while its dependencies are processed,
// so that a recursive reference to it is reported as a circular import.
// The node lives on this frame and is popped before lib_path is freed,
// so it can borrow the path string.
struct loading_lib loading = { jv_string_value(lib_path), lib_state->loading };
lib_state->loading = &loading;
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);
lib_state->loading = loading.next;
program = block_bind_self(program, OP_IS_CALL_PSEUDO);
// Register the library only once its dependencies have been processed,
// to keep lib_state->entries in dependency order. Register it even when
// its dependencies failed, so that other importers reuse this entry
// rather than loading and diagnosing the same library again.
state_idx = lib_state->ct++;
lib_state->entries = jv_mem_realloc(lib_state->entries, lib_state->ct * sizeof(struct lib_entry));
lib_state->entries[state_idx].name = strdup(jv_string_value(lib_path));
lib_state->entries[state_idx].def = program;
lib_state->entries[state_idx].loading = 0;
}
}
*out_block = program;
@@ -435,7 +442,7 @@ jv load_module_meta(jq_state *jq, jv mod_relpath) {
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};
struct lib_loading_state lib_state = {0,0,0};
nerrors = jq_parse(src, &program);
if (nerrors)
return nerrors;
+19 -11
View File
@@ -212,21 +212,26 @@ static int process(jq_state *jq, jv value, int flags, int dumpopts, int options)
jv exit_code = jq_get_exit_code(jq);
if (!jv_is_valid(exit_code))
ret = JQ_OK;
else if (jv_get_kind(exit_code) == JV_KIND_NUMBER)
else if (jv_get_kind(exit_code) == JV_KIND_NUMBER) {
ret = jv_number_value(exit_code);
else
// Negative values would be mistaken for JQ_OK_NULL_KIND and friends,
// so keep the low 8 bits, like exit(3) does on POSIX systems.
if (ret < 0)
ret &= 0xff;
} else
ret = JQ_ERROR_UNKNOWN;
jv_free(exit_code);
jv error_message = jq_get_error_message(jq);
if (jv_get_kind(error_message) == JV_KIND_STRING) {
// No prefix should be added to the output of `halt_error`.
priv_fwrite(jv_string_value(error_message), jv_string_length_bytes(jv_copy(error_message)),
stderr, dumpopts & JV_PRINT_ISATTY);
} else if (jv_get_kind(error_message) == JV_KIND_NULL) {
if (jv_get_kind(error_message) == JV_KIND_NULL) {
// Halt with no output
} else if (jv_is_valid(error_message)) {
error_message = jv_dump_string(error_message, 0);
fprintf(stderr, "%s\n", jv_string_value(error_message));
if (jv_get_kind(error_message) != JV_KIND_STRING) {
error_message = jv_dump_string(error_message, 0);
}
// No prefix or trailing newline should be added to the output of
// `halt_error`.
priv_fwrite(jv_string_value(error_message), jv_string_length_bytes(jv_copy(error_message)),
stderr, dumpopts & JV_PRINT_ISATTY);
} // else no message on stderr; use --debug-trace to see a message
fflush(stderr);
jv_free(error_message);
@@ -437,7 +442,7 @@ int main(int argc, char* argv[]) {
errno = 0;
long indent = strtol(argv[i+1], &end, 10);
if (errno || indent < -1 || indent > 7 ||
isspace(*argv[i+1]) || end == argv[i+1] || *end) {
isspace((unsigned char)*argv[i+1]) || end == argv[i+1] || *end) {
fprintf(stderr, "jq: --indent takes a number between -1 and 7\n");
die();
}
@@ -539,7 +544,10 @@ int main(int argc, char* argv[]) {
#ifdef USE_ISATTY
if (isatty(STDOUT_FILENO)) {
#ifndef WIN32
dumpopts |= JV_PRINT_ISATTY | JV_PRINT_COLOR;
dumpopts |= JV_PRINT_ISATTY;
char *term = getenv("TERM");
if (term != NULL && term[0] != '\0' && strcmp(term, "dumb"))
dumpopts |= JV_PRINT_COLOR;
#else
/* Verify we actually have the console, as the NUL device is also regarded as
tty. Windows can handle color if ANSICON (or ConEmu) is installed, or
-1
View File
@@ -1,6 +1,5 @@
OP(LOADK, CONSTANT, 1, 1)
OP(DUP, NONE, 1, 2)
OP(DUPN, NONE, 1, 2)
OP(DUP2, NONE, 2, 3)
OP(PUSHK_UNDER, CONSTANT, 1, 2)
OP(POP, NONE, 1, 0)
Generated
+1067 -1083
View File
File diff suppressed because it is too large. Load diff
Generated
+15 -17
View File
@@ -111,14 +111,13 @@ struct lexer_param;
SETDEFINEDOR = 293, /* "//=" */
LESSEQ = 294, /* "<=" */
GREATEREQ = 295, /* ">=" */
ALTERNATION = 296, /* "?//" */
QQSTRING_START = 297, /* QQSTRING_START */
QQSTRING_TEXT = 298, /* QQSTRING_TEXT */
QQSTRING_INTERP_START = 299, /* QQSTRING_INTERP_START */
QQSTRING_INTERP_END = 300, /* QQSTRING_INTERP_END */
QQSTRING_END = 301, /* QQSTRING_END */
FUNCDEF = 302, /* FUNCDEF */
NONOPT = 303 /* NONOPT */
QQSTRING_START = 296, /* QQSTRING_START */
QQSTRING_TEXT = 297, /* QQSTRING_TEXT */
QQSTRING_INTERP_START = 298, /* QQSTRING_INTERP_START */
QQSTRING_INTERP_END = 299, /* QQSTRING_INTERP_END */
QQSTRING_END = 300, /* QQSTRING_END */
FUNCDEF = 301, /* FUNCDEF */
NONOPT = 302 /* NONOPT */
};
typedef enum yytokentype yytoken_kind_t;
#endif
@@ -165,14 +164,13 @@ struct lexer_param;
#define SETDEFINEDOR 293
#define LESSEQ 294
#define GREATEREQ 295
#define ALTERNATION 296
#define QQSTRING_START 297
#define QQSTRING_TEXT 298
#define QQSTRING_INTERP_START 299
#define QQSTRING_INTERP_END 300
#define QQSTRING_END 301
#define FUNCDEF 302
#define NONOPT 303
#define QQSTRING_START 296
#define QQSTRING_TEXT 297
#define QQSTRING_INTERP_START 298
#define QQSTRING_INTERP_END 299
#define QQSTRING_END 300
#define FUNCDEF 301
#define NONOPT 302
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@@ -183,7 +181,7 @@ union YYSTYPE
jv literal;
block blk;
#line 187 "src/parser.h"
#line 185 "src/parser.h"
};
typedef union YYSTYPE YYSTYPE;
+4 -5
View File
@@ -85,7 +85,6 @@ struct lexer_param;
%token SETDEFINEDOR "//="
%token LESSEQ "<="
%token GREATEREQ ">="
%token ALTERNATION "?//"
%token QQSTRING_START
%token <literal> QQSTRING_TEXT
@@ -746,16 +745,16 @@ Query {
}
RepPatterns:
RepPatterns "?//" Pattern {
$$ = BLOCK($1, gen_destructure_alt($3));
RepPatterns '?' "//" Pattern {
$$ = BLOCK($1, gen_destructure_alt($4));
} |
Pattern {
$$ = gen_destructure_alt($1);
}
Patterns:
RepPatterns "?//" Pattern {
$$ = BLOCK($1, $3);
RepPatterns '?' "//" Pattern {
$$ = BLOCK($1, $4);
} |
Pattern {
$$ = $1;
+10
View File
@@ -193,6 +193,7 @@ struct jq_util_input_state {
size_t buf_valid_len;
jv current_filename;
size_t current_line;
int at_file_start;
};
static void fprinter(void *data, const char *fname) {
@@ -277,6 +278,7 @@ static int jq_util_input_read_more(jq_util_input_state *state) {
if (f != NULL) {
jv_free(state->current_filename);
state->current_line = 0;
state->at_file_start = 1;
if (!strcmp(f, "-")) {
state->current_input = stdin;
state->current_filename = jv_string("<stdin>");
@@ -343,6 +345,14 @@ static int jq_util_input_read_more(jq_util_input_state *state) {
state->buf_valid_len = (p - state->buf) + 1;
}
}
if (state->at_file_start) {
// Strip UTF-8 BOM at the start of each file
if (state->buf_valid_len >= 3 && !memcmp(state->buf, "\xEF\xBB\xBF", 3)) {
state->buf_valid_len -= 3;
memmove(state->buf, state->buf + 3, state->buf_valid_len);
}
state->at_file_start = 0;
}
}
return state->curr_file == state->nfiles && !state->current_input;
}
+38 -16
View File
@@ -2,11 +2,13 @@
#define UTIL_H
#ifdef WIN32
/* For WriteFile() below */
/* For WriteConsoleW() below */
#include <windows.h>
#include <io.h>
#include <limits.h>
#include <processenv.h>
#include <shellapi.h>
#include <stdlib.h>
#include <wchar.h>
#include <wtypes.h>
#endif
@@ -18,27 +20,47 @@ jv get_home(void);
jv jq_realpath(jv);
/*
* The Windows CRT and console are something else. In order for the
* console to get UTF-8 written to it correctly we have to bypass stdio
* completely. No amount of fflush()ing helps. If the first byte of a
* buffer being written with fwrite() is non-ASCII UTF-8 then the
* console misinterprets the byte sequence. But one must not
* WriteFile() if stdout is a file!1!!
* The Windows console does not do UTF-8. Bytes written to it, with
* fwrite() or with WriteFile() alike, are decoded with the console's
* output code page, so anything but ASCII comes out as mojibake unless
* the user happened to run `chcp 65001` first. The wide character
* console API is code page independent, so convert to UTF-16 and use
* WriteConsoleW() instead. We must not call SetConsoleOutputCP(): the
* code page belongs to the console rather than to us, so changing it
* also changes the shell we were started from (see #1121 and #1184).
*
* We carry knowledge of whether the FILE * is a tty everywhere we
* output to it just so we can write with WriteFile() if stdout is a
* console on WIN32.
* Only a console needs this; a file or a pipe wants the UTF-8 bytes.
* The is_tty flag alone cannot tell the two apart, as it is computed
* once, from stdout, and passed along even for writes to stderr, so
* ask the handle we are about to write to.
*/
static void priv_fwrite(const char *s, size_t len, FILE *fout, int is_tty) {
#ifdef WIN32
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);
if (is_tty && len > 0 && len <= INT_MAX / sizeof(wchar_t)) {
HANDLE h = (HANDLE)_get_osfhandle(fileno(fout));
DWORD mode;
if (GetConsoleMode(h, &mode)) {
int wlen = MultiByteToWideChar(CP_UTF8, 0, s, (int)len, NULL, 0);
wchar_t *ws = wlen > 0 ? malloc(wlen * sizeof(*ws)) : NULL;
if (ws != NULL) {
wlen = MultiByteToWideChar(CP_UTF8, 0, s, (int)len, ws, wlen);
fflush(fout); /* keep our order with stdio writes to this stream */
for (int done = 0; done < wlen;) {
DWORD written;
/* WriteConsoleW() may write fewer characters than asked for. */
if (!WriteConsoleW(h, ws + done, wlen - done, &written, NULL) ||
written == 0)
break;
done += written;
}
free(ws);
return;
}
}
}
#endif
fwrite(s, 1, len, fout);
}
const void *_jq_memmem(const void *haystack, size_t haystacklen,
+269 -8
View File
@@ -42,13 +42,6 @@ null
{"x":-1}
{"x":1}
# The input line starts with a 0xFEFF (byte order mark) codepoint
# No, there is no reason to have a byte order mark in UTF8 text.
# But apparently people do, so jq shouldn't break on it.
.
"byte order mark"
"byte order mark"
# We test escapes by matching them against Unicode codepoints
# FIXME: more tests needed for weird unicode stuff (e.g. utf16 pairs)
"Aa\r\n\t\b\f\u03bc"
@@ -91,6 +84,16 @@ null
"Zm/Ds2Jhcgo="
"foóbar\n"
# Invalid UTF-8 next to ASCII runs is still replaced
map(@base64d)
["YWJjZGVmZ2hpav9rbG1ub3A=", "YWJjZGVmZ2hpasOpa2xtbm9w5pel", "/2FiY2RlZmdoaWo=", "YWJjZGVmZ2hpauaX", "YWJjZGVmZ2hpau2ggHh5eg=="]
["abcdefghij�klmnop","abcdefghijéklmnop日","�abcdefghij","abcdefghij�","abcdefghij�xyz"]
# Truncated UTF-8 sequence keeps the characters after it
map(@base64d)
["8Fo=", "4mE=", "8J9a", "YfBaYg==", "8J+Y"]
["�Z","�a","�Z","a�Zb","�"]
@uri
"\u03bc"
"%CE%BC"
@@ -107,6 +110,15 @@ null
["foo", 1, ["a", 1, "b", 2, {"foo":"bar"}]]
["foo",1,["a",1,"b",2,{"foo":"bar"}]]
# Put escapes on both sides of runs of bytes that need no escaping
map(tojson)
["abcdefg\"", "abcdefgh\\", "abcdefghi\u0001j", "abcdefghijklmno\u007f", "abcdefgh\té", "abcdefghijklmnop\n"]
["\"abcdefg\\\"\"","\"abcdefgh\\\\\"","\"abcdefghi\\u0001j\"","\"abcdefghijklmno\\u007f\"","\"abcdefgh\\té\"","\"abcdefghijklmnop\\n\""]
[range(18) as $i | ("\"", "\\", "\u0001", "\u007f", "é", "😀") as $c | "abcdefghijklmnopq"[:$i] + $c + "abcdefghijklmnopq"[$i:] | (tojson | fromjson) == .] | all
null
true
#
# Dictionary construction syntax
#
@@ -304,10 +316,30 @@ null
null
[0,-1,-2,-3,-4]
[range(0;-10;-3)]
null
[0,-3,-6,-9]
[range(0;10;0)]
null
[]
[range(0,1;4,5;1,2)]
null
[0,1,2,3,0,2, 0,1,2,3,4,0,2,4, 1,2,3,1,3, 1,2,3,4,1,3]
try range(.) catch .
null
"Range bounds and step must be numeric"
try range(0;"") catch .
null
"Range bounds and step must be numeric"
try range(0;1;[]) catch .
null
"Range bounds and step must be numeric"
[while(.<100; .*2)]
1
[1,2,4,8,16,32,64]
@@ -1465,6 +1497,11 @@ try error(0) // 1
null
1
# Lex token test #3589, like error(0)? // 1
error(0) ?// 1
null
1
1, try error(2), 3
null
1
@@ -1734,6 +1771,38 @@ has(nan)
[0,1,2]
false
has(infinite)
[0,1,2]
false
has(-infinite)
[0,1,2]
false
del(.[infinite])
[1,2,3]
[1,2,3]
del(.[-infinite])
[1,2,3]
[1,2,3]
has(1e10)
[0,1,2]
false
has(-1e10)
[0,1,2]
false
del(.[1e10])
[1,2,3]
[1,2,3]
del(.[-1e10])
[1,2,3]
[1,2,3]
keys
[42,3,35]
[0,1,2]
@@ -1824,6 +1893,24 @@ ascii_upcase
"useful but not for é"
"USEFUL BUT NOT FOR é"
# Only A-Z and a-z change; the neighbouring bytes @ [ ` { and non-ASCII do not
[ascii_downcase, ascii_upcase]
"@AZ[`az{ ÀÉé Dž 日本 😀 0123456789 THE QUICK brown fox JUMPS over"
["@az[`az{ ÀÉé Dž 日本 😀 0123456789 the quick brown fox jumps over","@AZ[`AZ{ ÀÉé Dž 日本 😀 0123456789 THE QUICK BROWN FOX JUMPS OVER"]
[ascii_downcase, ascii_upcase]
""
["",""]
# An embedded NUL does not end the string
[ascii_downcase, ascii_upcase]
"A\u0000z"
["a\u0000z","A\u0000Z"]
[.[] | try ascii_downcase catch ., try ascii_upcase catch .]
[null, ["A"]]
["ascii_downcase input must be a string","ascii_upcase input must be a string","ascii_downcase input must be a string","ascii_upcase input must be a string"]
bsearch(0,1,2,3,4)
[1,2,3]
-1
@@ -1886,16 +1973,154 @@ try ["OK", strflocaltime({})] catch ["KO", .]
0
["KO","strflocaltime/1 requires a string format"]
[strftime("", " %Y ")]
0
["", " 1970 "]
try strftime("%c" * 10) catch .
0
"strftime/1: result too long"
[strflocaltime("", " %Y ")]
[2015,2,5,23,51,47,4,63]
["", " 2015 "]
try strflocaltime("%c" * 10) catch .
[2015,2,5,23,51,47,4,63]
"strflocaltime/1: result too long"
[strptime("%Y-%m-%dT%H:%M:%SZ")|(.,mktime)]
"2015-03-05T23:51:47Z"
[[2015,2,5,23,51,47,4,63],1425599507]
# a format without a day of the month gives the first of the month
[("2024-06" | strptime("%Y-%m")), ("2024" | strptime("%Y")) | ., todate]
null
[[2024,5,1,0,0,0,6,152],"2024-06-01T00:00:00Z",[2024,0,1,0,0,0,1,0],"2024-01-01T00:00:00Z"]
"10:15" | strptime("%H:%M")
null
[1900,0,1,10,15,0,1,0]
[-3,-2,-1,0,1 | gmtime | mktime]
null
[-3,-2,-1,0,1]
[1970,0,0,23,59,59,0,0] | mktime
null
-1
# Check day-of-week and day of year computations
# (should trip an assert if this fails)
last(range(365 * 67)|("1970-03-01T01:02:03Z"|strptime("%Y-%m-%dT%H:%M:%SZ")|mktime) + (86400 * .)|strftime("%Y-%m-%dT%H:%M:%SZ")|strptime("%Y-%m-%dT%H:%M:%SZ"))
null
[2037,1,11,1,2,3,3,41]
# fromdateiso8601 accepts the calendar, ordinal and week date forms,
# in both the extended and the basic representation
[("2015-03-05T23:51:47Z", "20150305T235147Z", "2015-064T23:51:47Z", "2015064T235147Z", "2015-W10-4T23:51:47Z", "2015W104T235147Z") | fromdateiso8601]
null
[1425599507,1425599507,1425599507,1425599507,1425599507,1425599507]
# fractional seconds, with either decimal sign
[("2015-03-05T23:51:47.25Z", "2015-03-05T23:51:47,25Z", "20150305T235147.25Z") | fromdateiso8601]
null
[1425599507.25,1425599507.25,1425599507.25]
# UTC offsets; an absent offset means UTC
[("2015-03-06T08:51:47+09:00", "2015-03-06T08:51:47+0900", "2015-03-06T08:51:47+09", "2015-03-05T18:21:47-05:30", "2015-03-05T23:51:47z", "2015-03-05T23:51:47") | fromdateiso8601]
null
[1425599507,1425599507,1425599507,1425599507,1425599507,1425599507]
# the date and the time may be separated by "T", "t" or a space
[("2015-03-05t23:51:47Z", "2015-03-05 23:51:47Z") | fromdateiso8601]
null
[1425599507,1425599507]
# the W, T and Z designators may be written in lower case
[("2015-w10-4t23:51:47z", "2015w104t235147z", "2015-03-05t23:51:47z") | fromdateiso8601]
null
[1425599507,1425599507,1425599507]
# expanded years carry a sign and exactly six digits
[("+012015-03-05T23:51:47Z", "-000001-01-01T00:00:00Z", "+0020150305T235147Z", "+2025-03-05", "+02025-03-05", "+0002025-03-05") | try fromdateiso8601 catch "ERR"]
null
[316995119507,-62198755200,1425599507,"ERR","ERR","ERR"]
# "24:00:00" is midnight of the following day, at any precision
[("2015-03-05T24:00:00Z", "2015-03-05T24:00Z", "2015-03-05T24Z") | fromdateiso8601 | todate]
null
["2015-03-06T00:00:00Z","2015-03-06T00:00:00Z","2015-03-06T00:00:00Z"]
# leap seconds are dropped rather than rejected
"2015-06-30T23:59:60Z" | fromdateiso8601 | todate
null
"2015-06-30T23:59:59Z"
# 2015 starts on a Thursday, so it has 53 ISO weeks
"2015-W53-1T00:00:00Z" | fromdateiso8601 | todate
null
"2015-12-28T00:00:00Z"
# 2016 is a leap year starting on a Friday: 366 days, but only 52 ISO weeks
[("2016-366T00:00:00Z", "2016-W52-7T00:00:00Z") | fromdateiso8601 | todate]
null
["2016-12-31T00:00:00Z","2017-01-01T00:00:00Z"]
# fromdateiso8601 is not limited by the range of a 32-bit time_t (#3276)
fromdate
"2038-01-19T03:14:08Z"
2147483648
# the time may drop its seconds, or its minutes and seconds
[("2015-03-05T23:51Z", "2015-03-05T23Z", "20150305T2351Z", "20150305T23Z") | fromdateiso8601]
null
[1425599460,1425596400,1425599460,1425596400]
# a decimal fraction belongs to the lowest component present
[("2015-03-05T23:51:47,5Z", "2015-03-05T23:51,5Z", "2015-03-05T23,5Z") | fromdateiso8601]
null
[1425599507.5,1425599490,1425598200]
# a date on its own is midnight UTC
[("2015-03-05", "20150305", "2015-064", "2015064", "2015-W10-4", "2015W104") | fromdateiso8601]
null
[1425513600,1425513600,1425513600,1425513600,1425513600,1425513600]
# the zone designator belongs to the time, so a bare date cannot carry one
[("2015-03-05Z", "2015-03-05+09:00", "2015-03-05T") | try fromdateiso8601 catch "ERR"]
null
["ERR","ERR","ERR"]
# the date must be complete, and a time must not be empty
[("2015", "2015-03", "2015-W10", "2015-03T00:00:00Z", "T23:51:47Z", "T23:51:47", "23:51:47", "") | try fromdateiso8601 catch "ERR"]
null
["ERR","ERR","ERR","ERR","ERR","ERR","ERR","ERR"]
# the date and the time must agree on whether separators are used,
# and "YYYYMM" is ambiguous with "YYMMDD"
[("2015-03-05T235147Z", "20150305T23:51:47Z", "201503T00:00:00Z", "2015-03-05T2351Z", "20150305T23:51Z", "20150305T23205Z") | try fromdateiso8601 catch "ERR"]
null
["ERR","ERR","ERR","ERR","ERR","ERR"]
# out-of-range components are rejected
[("2015-02-30T00:00:00Z", "2015-13-01T00:00:00Z", "2015-00-01T00:00:00Z", "2015-366T00:00:00Z", "2016-W53-1T00:00:00Z", "2015-W10-8T00:00:00Z", "2015-W00-1T00:00:00Z", "2015-03-05T25:00:00Z", "2015-03-05T24:00:01Z", "2015-03-05T24:01Z", "2015-03-05T23:60:00Z", "2015-03-05T23:51:47+24:00", "2015-03-05T23:51:47+09:") | try fromdateiso8601 catch "ERR"]
null
["ERR","ERR","ERR","ERR","ERR","ERR","ERR","ERR","ERR","ERR","ERR","ERR","ERR"]
# the input must be exactly a datetime: no surrounding whitespace
[(" 2015-03-05T23:51:47Z", "2015-03-05T23:51:47Z ") | try fromdateiso8601 catch "ERR"]
null
["ERR","ERR"]
try fromdateiso8601 catch .
123
"fromdateiso8601 requires string inputs"
try fromdateiso8601 catch .
"not a date"
"date \"not a date\" is not a valid ISO 8601 datetime"
# module system
import "a" as foo; import "b" as bar; def fooa: foo::a; [fooa, bar::a, bar::b, foo::a]
null
@@ -1930,6 +2155,23 @@ import "shadow1" as f; import "shadow2" as f; import "shadow1" as e; [e::e, f::e
null
[2,3]
# A module reached only through another module must be linked before its
# importers, or dead-code elimination drops the definitions that only the
# importer's body references (#3597)
include "deep1"; f
null
[1,[21,3],[22,3,1]]
# ... including when the shared dependency is pulled in first by an importer
# whose own definitions end up unused, in either import order
import "deep2a" as a; import "deep2b" as b; b::f
null
[22,3,1]
import "deep2b" as b; import "deep2a" as a; b::f
null
[22,3,1]
%%FAIL
module (.+1); 0
jq: error: Module metadata must be constant at <top-level>, line 1, column 8:
@@ -2039,6 +2281,14 @@ try join(",") catch .
["1","2",[3,4,5]]
"string (\"1,2,\") and array ([3,4,5]) cannot be added"
join("-")
{"a":"x","b":1,"c":null,"d":false}
"x-1--false"
try join(1) catch .
["a","b"]
"string (\"a\") and number (1) cannot be added"
{if:0,and:1,or:2,then:3,else:4,elif:5,end:6,as:7,def:8,reduce:9,foreach:10,try:11,catch:12,label:13,import:14,include:15,module:16}
null
{"if":0,"and":1,"or":2,"then":3,"else":4,"elif":5,"end":6,"as":7,"def":8,"reduce":9,"foreach":10,"try":11,"catch":12,"label":13,"import":14,"include":15,"module":16}
@@ -2233,6 +2483,11 @@ true
null
true
# Unary negation keeps the sign of zero
[-0, -(-0), (.[] | -.)] | map(tojson)
[0, -0]
["-0","0","-0","0"]
. |= try . catch .
1
1
@@ -2534,7 +2789,13 @@ try ["OK", setpath([[1]]; 1)] catch ["KO", .]
[]
["KO","Cannot update field at array index of array"]
# regression test for #3227
# regression test for #3227 (reduce)
[] | reduce .[] as $x (0, 1; .)
null
0
1
# regression test for #3227 (foreach)
foreach .[] as $x (0, 1; . + $x)
[1, 2]
1
+37
View File
@@ -643,6 +643,10 @@ join(" ")
["a",1,2.3,true,null,false]
"a 1 2.3 true false"
join(", ")
{"a":1,"b":2}
"1, 2"
ascii_upcase
"useful but not for é"
"USEFUL BUT NOT FOR é"
@@ -743,6 +747,14 @@ fromdate
"2015-03-05T23:51:47Z"
1425599507
fromdateiso8601
"2015-03-06T08:51:47.25+09:00"
1425599507.25
map(fromdateiso8601)
["20150305T235147Z","2015-064T23:51:47Z","2015-W10-4T23:51:47Z"]
[1425599507,1425599507,1425599507]
strptime("%Y-%m-%dT%H:%M:%SZ")
"2015-03-05T23:51:47Z"
[2015,2,5,23,51,47,4,63]
@@ -876,6 +888,14 @@ def addvalue(f): f as $x | map(. + $x); addvalue(.[0])
[[1,2],[10,20]]
[[1,2,1,2], [10,20,1,2]]
def f(a; b): [a, b]; f(.x; .y)
{"x":1,"y":2}
[1,2]
def f(a): [a]; f(.x, .y)
{"x":1,"y":2}
[1,2]
isempty(empty)
null
true
@@ -966,6 +986,14 @@ null
[0,[1,{"a":1},{"b":2}]]
true
.foo |= . + 1
{"foo": 41, "bar": "unchanged"}
{"foo": 42, "bar": "unchanged"}
.user.age |= . + 1
{"user": {"name": "alice", "age": 30}, "active": true}
{"user": {"name": "alice", "age": 31}, "active": true}
(..|select(type=="boolean")) |= if . then 1 else 0 end
[true,false,[5,true,[true,[false]],false]]
[1,0,[5,1,[1,[0]],0]]
@@ -974,6 +1002,15 @@ true
{"foo": 42}
{"foo": 43}
.a += .b
{"a": 1, "b": 2}
{"a": 3, "b": 2}
.a += (1,2)
{"a": 0}
{"a": 1}
{"a": 2}
.a = .b
{"a": {"b": 10}, "b": 20}
{"a":20,"b":20}
+3
View File
@@ -0,0 +1,3 @@
import "deep2a" as a;
import "deep2b" as b;
def f: [1, a::f, b::f];
+2
View File
@@ -0,0 +1,2 @@
import "deep3" as m;
def f: [21, m::f];
+3
View File
@@ -0,0 +1,3 @@
import "deep3" as m;
import "data" as $d;
def f: [22, m::f, ($d | length)];
+2
View File
@@ -0,0 +1,2 @@
def _f: 3;
def f: _f;
+13
View File
@@ -11,6 +11,19 @@
"ab"
[{"offset":0,"length":0,"string":"","captures":[]},{"offset":1,"length":0,"string":"","captures":[]},{"offset":2,"length":0,"string":"","captures":[]}]
# global zero-width matches must not land inside a multibyte character
[match(""; "g") | .offset]
"aé€🚀b"
[0,1,2,3,4,5]
gsub(""; "-")
"aé"
"-a-é-"
[splits("")]
"aé"
["","a","é",""]
[match("a"; "gi")]
"āáàä"
[]
+8 -5
View File
@@ -1,12 +1,15 @@
# See tests/jq.test and the jq manual for more information.
# Regression test for #3276 (fails on mingw/WIN32)
fromdate
"2038-01-19T03:14:08Z"
2147483648
# %e is not available on mingw/WIN32
strftime("%A, %B %e, %Y")
1435677542.822351
"Tuesday, June 30, 2015"
# Timestamps before the epoch are not supported on mingw/WIN32
gmtime
-1.25
[1969,11,31,23,59,58.75,3,364]
map(gmtime) | . == sort
[-1.5,-1,-0.5,0,0.5,1,1.5]
true
+178 -6
View File
@@ -5,10 +5,12 @@
msys=false
mingw=false
sunos=false
netbsd=false
case "$(uname -s)" in
MSYS*) msys=true;;
MINGW*) mingw=true;;
SunOS*) sunos=true;;
NetBSD*) netbsd=true;;
esac
JQ_NO_B=$JQ
@@ -57,6 +59,79 @@ for exp in '1+1' '1-1' '2*3' '9/3' '9%3' '9==3' '9!=3' \
fi
done
## Test UTF-8 BOM is stripped at the start of each input file
printf '\357\273\277[{"foo": 1}\n,{"foo": 2}\n]\n' > $d/bom1.json
printf '\357\273\277[{"foo": 3}\n,{"foo": 4}\n]\n' > $d/bom2.json
$VALGRIND $Q $JQ -e '.[0].foo == 1' $d/bom1.json
$VALGRIND $Q $JQ -se '. == [[{"foo":1},{"foo":2}],[{"foo":3},{"foo":4}]]' $d/bom1.json $d/bom2.json
$VALGRIND $Q $JQ -ne '[inputs] == [[{"foo":1},{"foo":2}],[{"foo":3},{"foo":4}]]' $d/bom1.json $d/bom2.json
$VALGRIND $Q $JQ -ne '[inputs] == [[{"foo":1},{"foo":2}],[{"foo":3},{"foo":4}]]' $d/bom1.json - < $d/bom2.json
$VALGRIND $Q $JQ -Rne '[inputs] == ["[{\"foo\": 1}", ",{\"foo\": 2}", "]", "[{\"foo\": 3}", ",{\"foo\": 4}", "]"]' $d/bom1.json $d/bom2.json
$VALGRIND $Q $JQ -ne --slurpfile x $d/bom1.json '$x == [[{"foo":1},{"foo":2}]]'
$VALGRIND $Q $JQ -ne --rawfile x $d/bom1.json '$x == "[{\"foo\": 1}\n,{\"foo\": 2}\n]\n"'
## Test that --run-tests reports failures (#2765)
cat > $d/passing.test <<'EOF'
.
1
1
EOF
cat > $d/passing.expected <<'EOF'
Test #1: '.' at line number 1
1 of 1 tests passed (0 malformed, 0 skipped)
EOF
$VALGRIND $Q $JQ --run-tests $d/passing.test > $d/out 2>&1
head -n 2 $d/out | cmp $d/passing.expected -
cat > $d/erroneous-result.test <<'EOF'
.
1
2
EOF
cat > $d/erroneous-result.expected <<'EOF'
Test #1: '.' at line number 1
*** Expected 2, but got 1 for test at line number 3: .
0 of 1 tests passed (0 malformed, 0 skipped)
EOF
cat > $d/insufficient-results.test <<'EOF'
empty
null
{"expected":true}
EOF
cat > $d/insufficient-results.expected <<'EOF'
Test #1: 'empty' at line number 1
*** Insufficient results for test at line number 3: empty
0 of 1 tests passed (0 malformed, 0 skipped)
EOF
cat > $d/superfluous-result.test <<'EOF'
., .
1
1
EOF
cat > $d/superfluous-result.expected <<'EOF'
Test #1: '., .' at line number 1
*** Superfluous result: 1 for test at line number 3, ., .
0 of 1 tests passed (1 malformed, 0 skipped)
EOF
for test in erroneous-result insufficient-results superfluous-result; do
ret=0
# Keep memory errors distinct from the expected test failure status.
if [ -n "$VALGRIND" ]; then
$VALGRIND $Q --error-exitcode=99 $JQ --run-tests $d/$test.test > $d/out 2>&1 || ret=$?
else
$JQ --run-tests $d/$test.test > $d/out 2>&1 || ret=$?
fi
if [ "$ret" -ne 1 ]; then
cat $d/out
echo "Expected --run-tests to report $test with status 1, got $ret" >&2
exit 1
fi
cmp $d/out $d/$test.expected
done
## Test JSON sequence support
cat > $d/expected <<EOF
jq: ignoring parse error: Truncated value at line 2, column 5
@@ -74,6 +149,14 @@ EOF
printf '1\0362 3\n[0,1\036[4,5]true"ab"{"c":4\036{}{"d":5,"e":6"false\n\036null'|$VALGRIND $Q $JQ -ces --seq '. == [2,3,[4,5],true,"ab",{},null]' > /dev/null 2> $d/out
cmp $d/out $d/expected
# A syntax error skips the rest of the text, up to the next RS
cat > $d/expected <<EOF
jq: ignoring parse error: Invalid numeric literal at line 1, column 8 (need RS to resync)
jq: ignoring parse error: Unmatched '}' at line 2, column 5 (need RS to resync)
EOF
printf '\036{"a":x,"b":7}\n\036[1,}2\n\0363\n' | $VALGRIND $Q $JQ -ces --seq '. == [3]' > /dev/null 2> $d/out
cmp $d/out $d/expected
# Note that here jq sees no inputs at all but it still succeeds because
# --seq ignores parse errors
cat > $d/expected <<EOF
@@ -119,6 +202,27 @@ printf '" ~\\u007f"\n' > $d/expected
printf "\"$(printf '\\%03o' 32 126 127)\"" | $JQ '.' > $d/out 2>&1
cmp $d/out $d/expected
# Regression test for #3110: a raw NUL byte outside of a string must be a clean
# parse error, not silently truncate the surrounding token. Previously
# `printf '12\0003'` printed 12 and dropped the trailing 3.
cat > $d/expected <<EOF
jq: parse error: Invalid character at line 1, column 3
EOF
if printf '12\0003' | $JQ '.' > $d/out 2>&1; then
printf 'Error expected but jq exited successfully\n' 1>&2
exit 2
fi
cmp $d/out $d/expected
# A NUL at the very start of the input is rejected too.
cat > $d/expected <<EOF
jq: parse error: Invalid character at line 1, column 1
EOF
if printf '\000' | $JQ '.' > $d/out 2>&1; then
printf 'Error expected but jq exited successfully\n' 1>&2
exit 2
fi
cmp $d/out $d/expected
## Test --exit-status
data='{"i": 1}\n{"i": 2}\n{"i": 3}\n'
printf "$data" | $JQ --exit-status 'select(.i==1)' > /dev/null 2>&1
@@ -437,6 +541,15 @@ elif [ $? -ne 11 ]; then
echo "jq halt_error(11) had wrong error code" 1>&2
exit 1
fi
for opt in '' -e; do
if $VALGRIND $Q $VG_EXIT0 $JQ $opt -n 'halt_error(-1)'; then
echo "jq $opt halt_error(-1) didn't work as expected" 1>&2
exit 1
elif [ $? -ne 255 ]; then
echo "jq $opt halt_error(-1) had wrong error code" 1>&2
exit 1
fi
done
if [ -n "$($VALGRIND $Q $JQ -n 'halt_error(1)' 2>&1)" ]; then
echo "jq halt_error(1) had unexpected output" 1>&2
exit 1
@@ -453,7 +566,7 @@ if [ "$($VALGRIND $Q $JQ -n '"x\u0000y\u0000z" | halt_error(1)' 2>&1 | tr '\0' '
echo "jq halt_error(1) had unexpected output" 1>&2
exit 1
fi
if [ "$($VALGRIND $Q $JQ -n '{"a":"xyz"} | halt_error(1)' 2>&1)" != '{"a":"xyz"}' ]; then
if [ "$($VALGRIND $Q $JQ -n '{"a":"xyz"} | halt_error(1)' 2>&1 || echo "z")" != '{"a":"xyz"}z' ]; then
echo "jq halt_error(1) had unexpected output" 1>&2
exit 1
fi
@@ -640,11 +753,15 @@ for colors in '/' '[30' '30m' '30:31m:32' '30:*:31' 'invalid'; do
done
unset JQ_COLORS
# Check $NO_COLOR
# Check $NO_COLOR and $TERM
test_no_color=true
$msys && test_no_color=false
$mingw && test_no_color=false
$sunos && test_no_color=false
# NetBSD's script(1) intermittently loses the whole session output (the
# output file comes back empty for fast commands about half the time), so
# the pty checks cannot run reliably there.
$netbsd && test_no_color=false
if $test_no_color && command -v script >/dev/null 2>&1; then
if script -qc echo /dev/null >/dev/null 2>&1; then
faketty() { script -qec "$*" /dev/null; }
@@ -653,22 +770,52 @@ if $test_no_color && command -v script >/dev/null 2>&1; then
sed 's/^\x5E\x44\x08\x08//'; }
fi
faketty $JQ_NO_B -n . > $d/color
faketty env TERM=xterm-256color $JQ_NO_B -n . > $d/color
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
faketty env NO_COLOR= $JQ_NO_B -n . > $d/color
faketty env TERM=xterm-256color NO_COLOR= $JQ_NO_B -n . > $d/color
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
faketty env NO_COLOR=1 $JQ_NO_B -n . > $d/color
faketty env TERM=xterm-256color NO_COLOR=1 $JQ_NO_B -n . > $d/color
printf 'null\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
faketty env NO_COLOR=1 $JQ_NO_B -Cn . > $d/color
faketty env TERM=xterm-256color NO_COLOR=1 $JQ_NO_B -Cn . > $d/color
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
faketty env TERM=dumb $JQ_NO_B -n . > $d/color
printf 'null\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
faketty env TERM=dumb $JQ_NO_B -Cn . > $d/color
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
faketty env TERM= $JQ_NO_B -n . > $d/color
printf 'null\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
faketty env TERM= $JQ_NO_B -Cn . > $d/color
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
(unset TERM; faketty $JQ_NO_B -n . > $d/color)
printf 'null\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
cmp $d/color $d/expect
(unset TERM; faketty $JQ_NO_B -Cn . > $d/color)
printf '\033[0;90mnull\033[0m\r\n' > $d/expect
od -tc $d/expect
od -tc $d/color
@@ -711,6 +858,8 @@ $locales
EOF
if [ -z "$l" ]; then
echo "WARNING: Not testing localization"
elif [ "$(LC_ALL=C date +%a%b)" = "$(LC_ALL=$l date +%a%b)" ]; then
echo "WARNING: Date does not produce locale-dependent output for $l, skipping localization test"
else
dt1=$(LC_ALL=$l date +'%a %d %b %Y at %H:%M:%S')
dt2=$(LC_ALL=$l $JQ -nr 'now | strflocaltime("%a %d %b %Y at %H:%M:%S")')
@@ -722,6 +871,15 @@ EOF
fi
fi
# strflocaltime/1 allows a format that expands to an empty string
l=fr_FR.UTF-8
if ! $msys && ! $mingw && [ -z "$(LC_ALL=$l date +%p 2>/dev/null)" ]; then
if ! out=$(LC_ALL=$l $VALGRIND $Q $JQ -n '0 | strflocaltime("%p")' 2>&1) || [ "$out" != '""' ]; then
echo "strflocaltime(\"%p\") in $l should output an empty string but got: $out"
exit 1
fi
fi
# Test syntax error messages of multiline filter (we can't test in jq.test)
if $VALGRIND $Q $JQ -n '[
try if .
@@ -903,6 +1061,20 @@ $JQ -nf $d/prog.jq 2> $d/out && {
}
diff $d/out $d/expected
# Test 3: Too many function parameters in a nested function (issue #3661)
echo "Testing function parameter limit in a nested function..."
cat > $d/expected <<EOF
jq: error: function has too many parameters (max 4095)
jq: error: too many function parameters or local function definitions (max 4095)
jq: 2 compile errors
EOF
$JQ -rn '"def g(\([range(4097) | "a\(.)"] | join(";"))): .; def f: g(\([range(4097)] | join(";"))); f"' > $d/prog.jq
$JQ -nf $d/prog.jq 2> $d/out && {
echo "Expected compile error for too many parameters in a nested function"
exit 1
}
diff $d/out $d/expected
# CVE-2026-33948: No NUL truncation in the JSON parser
if printf '{}\x00{}' | $JQ >/dev/null 2> /dev/null; then
printf 'Error expected but jq exited successfully\n' 1>&2
+14
View File
@@ -21,4 +21,18 @@ for l in 1 2 3 4; do
fi
done
# --ascii-output escapes non-ASCII characters on both sides of runs of
# bytes that need no escaping
$VALGRIND $Q $JQ -cn '[range(18) as $i | ("é", "😀", "\u007f") as $c |
"abcdefghijklmnopq"[:$i] + $c + "abcdefghijklmnopq"[$i:]]' > $d/input
$VALGRIND $Q $JQ -ac . $d/input > $d/out
if LC_ALL=C grep -q '[^ -~]' $d/out; then
echo "--ascii-output printed a non-ASCII byte"
exit 1
fi
if ! $VALGRIND $Q $JQ -e --slurpfile a $d/input '. == $a[0]' $d/out > /dev/null; then
echo "--ascii-output changed a string"
exit 1
fi
exit 0