Compare commits

..
Author SHA1 Message Date
Owen Ou 69e27dde73 Only enable CI when push to master & tag 2023-07-01 12:03:29 -07:00
Owen Ou 6cce62dfa9 Select gcc binaries to release 2023-07-01 11:46:41 -07:00
Owen Ou 25a0608a64 Run brew update-reset when brew update fails
`brew update` can fail for "Error: Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask failed!"

Ref: https://github.com/owenthereal/jq/actions/runs/5432314910/jobs/9879266028#step:3:19
2023-07-01 11:23:31 -07:00
Owen Ou 4c15a17bf6 Enable all tests for Windows 2023-07-01 11:23:31 -07:00
Owen Ou d295348dcb Add matrix to test all available GH Actions images 2023-07-01 11:23:31 -07:00
Owen Ou b47d0162c0 Also install flex for Windows build 2023-07-01 11:23:31 -07:00
Owen Ou fc505694a7 Locate bison for Windows build 2023-07-01 11:23:31 -07:00
Owen Ou 493ca3e252 Release pipeline
* Group CI builds for different OSes into `ci.yml`.
* Add release job to release `jq` when tag is in the format of v*.
* Use `clang` as the only compiler on CI.
* Provide extensible matrix for future cross-compile builds, e.g.
  for https://github.com/jqlang/jq/pull/2618.
2023-07-01 11:23:31 -07:00
28 changed files with 1934 additions and 2328 deletions

No files matched your search

-4
View File
@@ -1,7 +1,3 @@
.gitattributes export-ignore
.gitignore export-ignore
* text=auto eol=lf
# generated files
src/lexer.[ch] linguist-generated=true
src/parser.[ch] linguist-generated=true
+67 -222
View File
@@ -4,78 +4,19 @@ on:
branches:
- master
tags:
- "jq-*"
- "v*"
pull_request:
jobs:
linux:
strategy:
fail-fast: false
matrix:
arch:
[
amd64,
arm64,
armel,
armhf,
i386,
mips,
mips64,
mips64el,
mips64r6,
mips64r6el,
mipsel,
mipsr6,
mipsr6el,
powerpc,
ppc64el,
s390x,
riscv64,
]
include:
- arch: amd64
CC: "x86_64-linux-gnu"
- arch: arm64
CC: "aarch64-linux-gnu"
- arch: armel
CC: "arm-linux-gnueabi"
- arch: armhf
CC: "arm-linux-gnueabihf"
- arch: i386
CC: "i686-linux-gnu"
- arch: mips
CC: "mips-linux-gnu"
- arch: mips64
CC: "mips64-linux-gnuabi64"
- arch: mips64el
CC: "mips64el-linux-gnuabi64"
- arch: mips64r6
CC: "mipsisa64r6-linux-gnuabi64"
- arch: mips64r6el
CC: "mipsisa64r6el-linux-gnuabi64"
- arch: mipsel
CC: "mipsel-linux-gnu"
- arch: mipsr6
CC: "mipsisa32r6-linux-gnu"
- arch: mipsr6el
CC: "mipsisa32r6el-linux-gnu"
- arch: powerpc
CC: "powerpc-linux-gnu"
- arch: ppc64el
CC: "powerpc64le-linux-gnu"
- arch: s390x
CC: "s390x-linux-gnu"
- arch: riscv64
CC: "riscv64-linux-gnu"
runs-on: ubuntu-22.04
compiler: [gcc, clang]
image: [ubuntu-20.04, ubuntu-22.04]
runs-on: ${{ matrix.image }}
env:
AR: ${{ matrix.CC }}-ar
CHOST: ${{ matrix.cc }}
CC: ${{ matrix.cc }}-gcc
CPP: ${{ matrix.cc }}-cpp
CXX: ${{ matrix.cc }}-g++
LDFLAGS: -s
SUFFIX: linux-${{ matrix.arch }}
CC: ${{ matrix.compiler }}
SUFFIX: linux-${{ matrix.image}}-${{ matrix.compiler }}
steps:
- name: Clone repository
uses: actions/checkout@v3
@@ -83,29 +24,27 @@ jobs:
submodules: true
- name: Install packages
run: |
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install -y automake autoconf libtool crossbuild-essential-${{ matrix.arch }}
sudo apt-get update -qq
sudo apt-get install -y \
automake \
autoconf \
bison \
flex \
gdb \
python3
- name: Build
run: |
autoreconf -i
./configure \
--host=${{ matrix.CC }} \
--disable-docs \
autoreconf -fi
./configure --disable-dependency-tracking \
--disable-silent-rules \
--disable-maintainer-mode \
--disable-valgrind \
--with-oniguruma=builtin \
--enable-static \
--enable-all-static
make -j$(nproc)
file ./jq
cp ./jq jq-${{ env.SUFFIX }}
YACC="$(which bison) -y"
make
- name: Test
# Only run tests for amd64 matching the CI machine arch
if: ${{ matrix.arch == 'amd64' }}
run: |
make check
git diff --exit-code
- name: Upload Test Logs
if: ${{ failure() }}
uses: actions/upload-artifact@v3
@@ -119,28 +58,20 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: jq-${{ env.SUFFIX }}
path: jq-${{ env.SUFFIX }}
if-no-files-found: error
retention-days: 7
path: |
jq
macos:
strategy:
fail-fast: false
matrix:
arch:
[
amd64,
arm64,
]
include:
- arch: amd64
target: "x86_64-apple-darwin"
- arch: arm64
target: "arm64-apple-darwin"
runs-on: macos-13
compiler: [gcc, clang]
image: [macos-11, macos-12, macos-13]
runs-on: ${{ matrix.image }}
env:
LDFLAGS: -s
SUFFIX: macos-${{ matrix.arch }}
CC: ${{ matrix.compiler }}
SUFFIX: macos-${{ matrix.image}}-${{ matrix.compiler }}
steps:
- name: Clone repository
uses: actions/checkout@v3
@@ -150,30 +81,26 @@ jobs:
run: |
# brew update sometimes fails with "Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask failed!"
brew update || brew update-reset
brew install autoconf automake libtool
- name: "Set CC"
run: |
echo "CC=clang -target ${{ matrix.target }}$(uname -r)" >> $GITHUB_ENV
brew install \
autoconf \
automake \
libtool \
flex \
bison
sed -i.bak '/^AM_INIT_AUTOMAKE(\[-Wno-portability 1\.14\])$/s/14/11/' modules/oniguruma/configure.ac
- name: Build
run: |
autoreconf -i
./configure \
--host=${{ matrix.target }}$(uname -r) \
--disable-docs \
autoreconf -fi
./configure --disable-dependency-tracking \
--disable-silent-rules \
--disable-maintainer-mode \
--disable-valgrind \
--with-oniguruma=builtin \
--enable-static \
--enable-all-static
make -j$(nproc)
file ./jq
cp ./jq jq-${{ env.SUFFIX }}
YACC="$(brew --prefix)/opt/bison/bin/bison -y"
make
- name: Test
# Only run tests for amd64 matching the CI machine arch
if: ${{ matrix.arch == 'amd64' }}
run: |
make check
git diff --exit-code
- name: Upload Test Logs
if: ${{ failure() }}
uses: actions/upload-artifact@v3
@@ -187,34 +114,20 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: jq-${{ env.SUFFIX }}
path: jq-${{ env.SUFFIX }}
if-no-files-found: error
retention-days: 7
path: |
jq
windows:
strategy:
fail-fast: false
matrix:
arch:
[
amd64,
i386,
]
include:
- arch: amd64
CC: "x86_64-pc-msys"
toolchain: "gcc"
msystem: msys
- arch: i386
CC: "i686-w64-mingw32"
toolchain: "mingw-w64-i686-toolchain"
msystem: mingw32
runs-on: windows-2022
compiler: [gcc]
image: [windows-2019, windows-2022]
runs-on: ${{ matrix.image }}
env:
CHOST: ${{ matrix.CC }}
CC: ${{ matrix.CC }}-gcc
LDFLAGS: -s
SUFFIX: windows-${{ matrix.arch }}
CC: ${{ matrix.compiler }}
SUFFIX: windows-${{ matrix.image}}-${{ matrix.compiler }}
steps:
- name: Clone repository
uses: actions/checkout@v3
@@ -223,37 +136,33 @@ jobs:
- uses: msys2/setup-msys2@v2
with:
update: true
msystem: ${{ matrix.msystem }}
install: >-
base-devel
git
clang
autoconf
automake
libtool
${{ matrix.toolchain }}
bison
flex
- name: Build
shell: msys2 {0}
run: |
autoreconf -i
./configure \
--host=${{ matrix.CC }} \
--disable-docs \
autoreconf -fi
./configure --disable-dependency-tracking \
--disable-silent-rules \
--disable-maintainer-mode \
--disable-valgrind \
--with-oniguruma=builtin \
--disable-shared \
--enable-static \
--enable-all-static
make -j$(nproc)
file ./jq.exe
cp ./jq.exe jq-${{ env.SUFFIX }}.exe
--enable-all-static \
YACC="$(which bison) -y"
make
- name: Test
# Only run tests for amd64 matching the CI machine arch
if: ${{ matrix.arch == 'amd64' }}
shell: msys2 {0}
run: |
make check
git diff --exit-code --ignore-submodules
- name: Upload Test Logs
if: ${{ failure() }}
uses: actions/upload-artifact@v3
@@ -267,98 +176,34 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: jq-${{ env.SUFFIX }}
path: jq-${{ env.SUFFIX }}.exe
if-no-files-found: error
retention-days: 7
dist:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/jq-')
steps:
- name: Clone repository
uses: actions/checkout@v3
with:
submodules: true
- name: Install packages
run: |
sudo apt-get update -qq
sudo apt-get install -y automake autoconf
- name: Create dist
run: |
autoreconf -i
./configure \
--disable-docs \
--disable-maintainer-mode \
--disable-valgrind \
--with-oniguruma=builtin
make dist dist-zip
git diff --exit-code
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: jq-dist
if-no-files-found: error
retention-days: 7
path: |
jq-*.tar.gz
jq-*.zip
docker:
runs-on: ubuntu-latest
permissions:
packages: write
if: startsWith(github.ref, 'refs/tags/jq-')
steps:
- name: Clone repository
uses: actions/checkout@v3
with:
submodules: true
- name: Docker metadata
uses: docker/metadata-action@v4
id: metadata
with:
images: ghcr.io/${{ github.repository }}
tags: type=match,pattern=jq-(.*),group=1,value=${{ github.ref_name }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and release Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
provenance: false
platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
jq.exe
release:
runs-on: ubuntu-latest
permissions:
contents: write
needs: [linux, macos, windows, dist, docker]
if: startsWith(github.ref, 'refs/tags/jq-')
needs: [linux, macos, windows]
if: startsWith(github.event.ref, 'refs/tags/v')
steps:
- name: Clone repository
uses: actions/checkout@v3
with:
submodules: true
- name: Merge built artifacts
uses: actions/download-artifact@v3
with:
path: artifacts
- name: Upload release
env:
TAG_NAME: ${{ github.ref_name }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir -p "release"
for files in jq-*; do
cp -rf "${files}/"* "release/"
done
mkdir release
cp artifacts/jq-linux-ubuntu-22.04-gcc/jq release/jq-linux-amd64
cp artifacts/jq-macos-macos-13-gcc/jq release/jq-macos-amd64
cp artifacts/jq-windows-windows-2022-gcc/jq.exe release/jq-windows-amd64.exe
gh release create "$TAG_NAME" --draft --title "jq ${TAG_NAME#jq-}" --generate-notes
gh release upload "$TAG_NAME" --clobber release/jq-*
gh release create $TAG_NAME --draft --title "jq ${TAG_NAME#v}" --generate-notes
gh release upload $TAG_NAME --clobber release/jq-*
+1 -1
View File
@@ -48,7 +48,7 @@ jobs:
CC: ${{ matrix.compiler }}
MAKEVARS: ${{ matrix.makevars }}
run: |
autoreconf -i
autoreconf -fi
rm src/lexer.c src/lexer.h
rm src/parser.c src/parser.h
./configure --with-oniguruma=builtin YACC="$(which bison) -y" $COVERAGE
-1
View File
@@ -33,7 +33,6 @@ autom4te.cache
INSTALL
Makefile
jq-*.tar.gz
jq-*.zip
configure
aclocal.m4
Makefile.in
+45 -27
View File
@@ -1,36 +1,54 @@
FROM debian:12-slim AS builder
FROM debian:9
ENV DEBIAN_FRONTEND=noninteractive \
DEBCONF_NONINTERACTIVE_SEEN=true \
LC_ALL=C.UTF-8 \
LANG=C.UTF-8
RUN apt-get update \
&& apt-get install -y \
build-essential \
autoconf \
libtool \
git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . /app
RUN autoreconf -i \
&& ./configure \
--disable-docs \
--disable-maintainer-mode \
--disable-valgrind \
--with-oniguruma=builtin \
--enable-static \
--enable-all-static \
--prefix=/usr/local \
&& make -j$(nproc) \
&& make check \
&& make install-strip
FROM scratch
# get dependencies, build, and remove anything we don't need for running jq.
# valgrind seems to have trouble with pthreads TLS so it's off.
COPY --from=builder /app/AUTHORS /app/COPYING /usr/local/bin/jq /
RUN ["/jq", "--version"]
ENTRYPOINT ["/jq"]
RUN apt-get update && \
apt-get install -y \
build-essential \
autoconf \
libtool \
git \
bison \
flex \
python3 \
python3-pip \
wget && \
pip3 install pipenv && \
(cd /app/docs && pipenv sync) && \
(cd /app && \
git submodule init && \
git submodule update && \
autoreconf -i && \
./configure --disable-valgrind --enable-all-static --prefix=/usr/local && \
make -j8 && \
make check && \
make install ) && \
(cd /app/modules/oniguruma && \
make uninstall ) && \
(cd /app && \
make distclean ) && \
apt-get purge -y \
build-essential \
autoconf \
libtool \
bison \
git \
flex \
python3 \
python3-pip && \
apt-get autoremove -y && \
rm -rf /app/modules/oniguruma/* && \
rm -rf /app/modules/oniguruma/.git && \
rm -rf /app/modules/oniguruma/.gitignore && \
rm -rf /var/lib/apt/lists/* /var/lib/gems
ENTRYPOINT ["/usr/local/bin/jq"]
CMD []
+2 -3
View File
@@ -132,7 +132,7 @@ endif
### Tests (make check)
TESTS = tests/optionaltest tests/mantest tests/jqtest tests/onigtest tests/shtest tests/utf8test tests/base64test tests/commenttest
TESTS = tests/optionaltest tests/mantest tests/jqtest tests/onigtest tests/shtest tests/utf8test tests/base64test
TESTS_ENVIRONMENT = NO_VALGRIND=$(NO_VALGRIND)
# This is a magic make variable that causes it to treat tests/man.test as a
@@ -215,8 +215,7 @@ EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \
tests/optional.test tests/optionaltest \
tests/utf8-truncate.jq tests/utf8test \
tests/base64.test tests/base64test \
tests/jq-f-test.sh tests/shtest \
tests/commenttest
tests/jq-f-test.sh tests/shtest
DISTCHECK_CONFIGURE_FLAGS=--disable-maintainer-mode --with-oniguruma=builtin
+5 -1
View File
@@ -3,6 +3,10 @@ jq
jq is a lightweight and flexible command-line JSON processor.
[![Linux Build](https://github.com/jqlang/jq/actions/workflows/linux.yml/badge.svg?branch=master)](https://github.com/jqlang/jq/actions/workflows/linux.yml?query=branch%3Amaster)
[![macOS Build](https://github.com/jqlang/jq/actions/workflows/macos.yml/badge.svg?branch=master)](https://github.com/jqlang/jq/actions/workflows/macos.yml?query=branch%3Amaster)
[![Windows Build](https://github.com/jqlang/jq/actions/workflows/windows.yml/badge.svg?branch=master)](https://github.com/jqlang/jq/actions/workflows/windows.yml?query=branch%3Amaster)
If you want to learn to use jq, read the documentation at
[https://jqlang.github.io/jq](https://jqlang.github.io/jq). This
documentation is generated from the docs/ folder of this repository.
@@ -24,7 +28,7 @@ git submodule as per the instructions below.
(note that jq's tests require regexp support to pass). To build, run:
git submodule update --init # if building from git to get oniguruma
autoreconf -i # if building from git
autoreconf -fi # if building from git
./configure --with-oniguruma=builtin
make -j8
make check
+41 -69
View File
@@ -559,7 +559,7 @@ sections:
hashes with only string keys), and "null".
Booleans, null, strings and numbers are written the same way as
in JSON. Just like everything else in jq, these simple
in javascript. Just like everything else in jq, these simple
values take an input and produce an output - `42` is a valid jq
expression that takes an input, ignores it, and returns 42
instead.
@@ -779,7 +779,7 @@ sections:
Division by zero raises an error. `x % y` computes x modulo y.
Multiplying a string by a number produces the concatenation of
that string that many times. `"x" * 0` produces `""`.
that string that many times. `"x" * 0` produces **null**.
Dividing a string by another splits the first using the second
as separators.
@@ -925,24 +925,6 @@ sections:
input: '{"a": 1, "b": 2, "c": 3}'
output: ['{"a": 2, "b": 3, "c": 4}']
- title: "`pick(pathexps)`"
body: |
Emit the projection of the input object or array defined by the specified
sequence of path expressions, such that if p is any one of these specifications,
then `(. | p)` will evaluate to the same value as `(. | pick(pathexps) | p)`.
For arrays, negative indices and .[m:n] specifications should not be used.
examples:
- program: 'pick(.a, .b.c, .x)'
input: '{"a": 1, "b": {"c": 2, "d": 3}, "e": 4}'
output: ['{"a":1,"b":{"c":2},"x":null}']
- program: '[1,2,3,4] | pick(.[2], .[0], .[0])'
input: '[1,2,3,4]'
output: ['[1,null,3]']
- title: "`path(path_expression)`"
body: |
@@ -1141,22 +1123,25 @@ sections:
input: 'null'
output: ['"{\"file\":\"<top-level>\",\"line\":1}"']
- title: "`paths`, `paths(node_filter)`"
- title: "`paths`, `paths(node_filter)`, `leaf_paths`"
body: |
`paths` outputs the paths to all the elements in its input
(except it does not output the empty list, representing .
itself).
`paths(f)` outputs the paths to any values for which `f` is `true`.
That is, `paths(type == "number")` outputs the paths to all numeric
`paths(f)` outputs the paths to any values for which `f` is true.
That is, `paths(numbers)` outputs the paths to all numeric
values.
`leaf_paths` is an alias of `paths(scalars)`; `leaf_paths` is
*deprecated* and will be removed in the next major release.
examples:
- program: '[paths]'
input: '[1,[[],{"a":2}]]'
output: ['[[0],[1],[1,0],[1,1],[1,1,"a"]]']
- program: '[paths(type == "number")]'
- program: '[paths(scalars)]'
input: '[1,[[],{"a":2}]]'
output: ['[[0],[1,1,"a"]]']
@@ -1735,7 +1720,7 @@ sections:
output: ['24']
- title: "`recurse(f)`, `recurse`, `recurse(f; condition)`"
- title: "`recurse(f)`, `recurse`, `recurse(f; condition)`, `recurse_down`"
body: |
The `recurse(f)` function allows you to search through a
@@ -1769,6 +1754,10 @@ sections:
to generate all the integers, at least in principle, one
could write `recurse(.+1; true)`.
For legacy reasons, `recurse_down` exists as an alias to
calling `recurse` without arguments. This alias is considered
*deprecated* and will be removed in the next major release.
The recursive calls in `recurse` will not consume additional
memory whenever `f` produces at most a single output for each
input.
@@ -2127,24 +2116,16 @@ sections:
- title: "`==`, `!=`"
body: |
The expression 'a == b' will produce 'true' if the results of evaluating
a and b are equal (that is, if they represent equivalent JSON values) and
The expression 'a == b' will produce 'true' if the result of a and b
are equal (that is, if they represent equivalent JSON documents) and
'false' otherwise. In particular, strings are never considered equal
to numbers. In checking for the equality of JSON objects, the ordering of keys
is irrelevant. If you're coming from JavaScript, please note that jq's `==` is like
JavaScript's `===`, the "strict equality" operator.
to numbers. If you're coming from JavaScript, jq's == is like
JavaScript's === - considering values equal only when they have the
same type as well as the same value.
!= is "not equal", and 'a != b' returns the opposite value of 'a == b'
examples:
- program: '. == false'
input: 'null'
output: ['false']
- program: '. == {"b": {"d": (4 + 1e-20), "c": 3}, "a":1}'
input: '{"a":1, "b": {"c": 3, "d": 4}}'
output: ['true']
- program: '.[] == 1'
input: '[1, 1.0, "1", "banana"]'
output: ['true', 'true', 'false', 'false']
@@ -2158,14 +2139,14 @@ sections:
`if A then B end` is the same as `if A then B else . end`.
That is, the `else` branch is optional, and if absent is the
same as `.`. This also applies to `elif` with absent ending `else` branch.
same as `.`.
Checking for false or null is a simpler notion of
"truthiness" than is found in JavaScript or Python, but it
means that you'll sometimes have to be more explicit about
the condition you want. You can't test whether, e.g. a
string is empty using `if .name then A else B end`; you'll
need something like `if .name == "" then A else B end` instead.
string is empty using `if .name then A else B end`, you'll
need something more like `if .name == "" then A else B end` instead.
If the condition `A` produces multiple results, then `B` is evaluated
once for each result that is not false or null, and `C` is evaluated
@@ -2492,43 +2473,32 @@ sections:
input: '("ab,cd", "ef, gh")'
output: ['"ab"', '"cd"', '"ef"', '"gh"']
- title: "`sub(regex; tostring)`, `sub(regex; tostring; flags)`"
- title: "`sub(regex; tostring)`, `sub(regex; string; flags)`"
body: |
Emit the string obtained by replacing the first match of
regex in the input string with `tostring`, after
interpolation. `tostring` should be a jq string or a stream
of such strings, each of which may contain references to
named captures. The named captures are, in effect, presented
as a JSON object (as constructed by `capture`) to
`tostring`, so a reference to a captured variable named "x"
would take the form: `"\(.x)"`.
Emit the string obtained by replacing the first match of regex in the
input string with `tostring`, after interpolation. `tostring` should
be a jq string, and may contain references to named captures. The
named captures are, in effect, presented as a JSON object (as
constructed by `capture`) to `tostring`, so a reference to a captured
variable named "x" would take the form: `"\(.x)"`.
example:
- program: 'sub("^[^a-z]*(?<x>[a-z]*).*")'
input: '"123abc456"'
output: '"ZabcZabc"'
- program: 'sub("[^a-z]*(?<x>[a-z]*)"; "Z\(.x)"; "g")'
input: '"123abc456def"'
output: ['"ZabcZdef"']
- program: '[sub("(?<a>.)"; "\(.a|ascii_upcase)", "\(.a|ascii_downcase)")]'
input: '"aB"'
output: ['["AB","aB"]']
- title: "`gsub(regex; tostring)`, `gsub(regex; tostring; flags)`"
- title: "`gsub(regex; string)`, `gsub(regex; string; flags)`"
body: |
`gsub` is like `sub` but all the non-overlapping occurrences of the regex are
replaced by `tostring`, after interpolation. If the second argument is a stream
of jq strings, then `gsub` will produce a corresponding stream of JSON strings.
replaced by the string, after interpolation.
example:
- program: 'gsub("(?<x>.)[^a]*"; "+\(.x)-")'
input: '"Abcabc"'
output: ['"+A-+a-"']
- program: '[gsub("p"; "a", "b")]'
input: '"p"'
output: ['["a","b"]']
output: '"+A-+a-"'
- title: Advanced features
@@ -2832,8 +2802,10 @@ sections:
The `first(expr)` and `last(expr)` functions extract the first
and last values from `expr`, respectively.
The `nth(n; expr)` function extracts the nth value output by `expr`.
Note that `nth(n; expr)` doesn't support negative values of `n`.
The `nth(n; expr)` function extracts the nth value output by
`expr`. This can be defined as `def nth(n; expr):
last(limit(n + 1; expr));`. Note that `nth(n; expr)` doesn't
support negative values of `n`.
examples:
- program: '[first(range(.)), last(range(.)), nth(./2; range(.))]'
@@ -3309,8 +3281,8 @@ sections:
For paths starting with `~/`, the user's home directory is
substituted for `~`.
For paths starting with `$ORIGIN/`, the directory where the jq
executable is located is substituted for `$ORIGIN`.
For paths starting with `$ORIGIN/`, the path of the jq executable
is substituted for `$ORIGIN`.
For paths starting with `./` or paths that are `.`, the path of
the including file is substituted for `.`. For top-level programs
+5 -5
View File
@@ -891,8 +891,8 @@ sections:
(except it does not output the empty list, representing .
itself).
`paths(f)` outputs the paths to any values for which `f` is `true`.
That is, `paths(type == "number")` outputs the paths to all numeric
`paths(f)` outputs the paths to any values for which `f` is true.
That is, `paths(numbers)` outputs the paths to all numeric
values.
`leaf_paths` is an alias of `paths(scalars)`; `leaf_paths` is
@@ -902,7 +902,7 @@ sections:
- program: '[paths]'
input: '[1,[[],{"a":2}]]'
output: ['[[0],[1],[1,0],[1,1],[1,1,"a"]]']
- program: '[paths(type == "number")]'
- program: '[paths(scalars)]'
input: '[1,[[],{"a":2}]]'
output: ['[[0],[1,1,"a"]]']
@@ -2765,8 +2765,8 @@ sections:
For paths starting with "~/", the user's home directory is
substituted for "~".
For paths starting with "$ORIGIN/", the directory where the jq
executable is located is substituted for "$ORIGIN".
For paths starting with "$ORIGIN/", the path of the jq executable
is substituted for "$ORIGIN".
For paths starting with "./" or paths that are ".", the path of
the including file is substituted for ".". For top-level programs
+5 -5
View File
@@ -1052,8 +1052,8 @@ sections:
(except it does not output the empty list, representing .
itself).
`paths(f)` outputs the paths to any values for which `f` is `true`.
That is, `paths(type == "number")` outputs the paths to all numeric
`paths(f)` outputs the paths to any values for which `f` is true.
That is, `paths(numbers)` outputs the paths to all numeric
values.
`leaf_paths` is an alias of `paths(scalars)`; `leaf_paths` is
@@ -1063,7 +1063,7 @@ sections:
- program: '[paths]'
input: '[1,[[],{"a":2}]]'
output: ['[[0],[1],[1,0],[1,1],[1,1,"a"]]']
- program: '[paths(type == "number")]'
- program: '[paths(scalars)]'
input: '[1,[[],{"a":2}]]'
output: ['[[0],[1,1,"a"]]']
@@ -3150,8 +3150,8 @@ sections:
For paths starting with "~/", the user's home directory is
substituted for "~".
For paths starting with "$ORIGIN/", the directory where the jq
executable is located is substituted for "$ORIGIN".
For paths starting with "$ORIGIN/", the path of the jq executable
is substituted for "$ORIGIN".
For paths starting with "./" or paths that are ".", the path of
the including file is substituted for ".". For top-level programs
+6 -10
View File
@@ -359,12 +359,9 @@ static jv f_multiply(jq_state *jq, jv input, jv a, jv b) {
str = b;
num = a;
}
jv res;
double d = jv_number_value(num);
if (d < 0 || isnan(d)) {
res = jv_null();
} else {
int n = d;
jv res = jv_null();
int n = jv_number_value(num);
if (n > 0) {
size_t alen = jv_string_length_bytes(jv_copy(str));
res = jv_string_empty(alen * n);
for (; n > 0; n--) {
@@ -384,7 +381,7 @@ static jv f_multiply(jq_state *jq, jv input, jv a, jv b) {
static jv f_divide(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
if (jv_number_value(b) == 0.0 && jv_number_value(a) != 0.0)
if (jv_number_value(b) == 0.0)
return type_error2(a, b, "cannot be divided because the divisor is zero");
jv r = jv_number(jv_number_value(a) / jv_number_value(b));
jv_free(a);
@@ -933,8 +930,7 @@ static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
match = jv_object_set(match, jv_string("string"), jv_string(""));
match = jv_object_set(match, jv_string("captures"), jv_array());
result = jv_array_append(result, match);
// ensure '"qux" | match("(?=u)"; "g")' matches just once
start = (const UChar*)(input_string+region->end[0]+1);
start += 1;
continue;
}
@@ -1002,7 +998,7 @@ static jv f_match(jq_state *jq, jv input, jv regex, jv modifiers, jv testmode) {
jv_string((char*)ebuf)));
break;
}
} while (global && start <= end);
} while (global && start != end);
onig_region_free(region,1);
region = NULL;
if (region)
+53 -40
View File
@@ -12,30 +12,31 @@ def add: reduce .[] as $x (null; . + $x);
def del(f): delpaths([path(f)]);
def _assign(paths; $value): reduce path(paths) as $p (.; setpath($p; $value));
def _modify(paths; update):
reduce path(paths) as $p ([., []];
reduce path(paths) as $p (.;
. as $dot
| null
| label $out
| ($dot[0] | getpath($p)) as $v
| ($dot | getpath($p)) as $v
| (
( $$$$v
| update
| (., break $out) as $v
| $$$$dot
| setpath([0] + $p; $v)
| setpath($p; $v)
),
(
$$$$dot
| setpath([1, (.[1] | length)]; $p)
| delpaths([$p])
)
)
) | . as $dot | $dot[0] | delpaths($dot[1]);
);
def map_values(f): .[] |= f;
# recurse
def recurse(f): def r: ., (f | r); r;
def recurse(f; cond): def r: ., (f | select(cond) | r); r;
def recurse: recurse(.[]?);
def recurse_down: 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 | .//={};
@@ -61,6 +62,7 @@ def strings: select(type == "string");
def nulls: select(. == null);
def values: select(. != null);
def scalars: select(type|. != "array" and . != "object");
def leaf_paths: paths(scalars);
def join($x): reduce .[] as $i (null;
(if .==null then "" else .+$x end) +
($i | if type=="boolean" or type=="number" then tostring else .//"" end)
@@ -88,20 +90,17 @@ def capture($val): ($val|type) as $vt | if $vt == "string" then capture($val; nu
elif $vt == "array" and ($val | length) > 1 then capture($val[0]; $val[1])
elif $vt == "array" and ($val | length) > 0 then capture($val[0]; null)
else error( $vt + " not a string or array") end;
def scan($re; $flags):
match($re; "g" + $flags)
| if (.captures|length > 0)
def scan(re):
match(re; "g")
| if (.captures|length > 0)
then [ .captures | .[] | .string ]
else .string
end;
def scan($re): scan($re; null);
end ;
#
# If input is an array, then emit a stream of successive subarrays of length n (or less),
# and similarly for strings.
def _nwise($n):
def n: if length <= $n then . else .[0:$n] , (.[$n:] | n) end;
n;
def _nwise(a; $n): a | _nwise($n);
def _nwise(a; $n): if a|length <= $n then a else a[0:$n] , _nwise(a[$n:]; $n) end;
def _nwise($n): _nwise(.; $n);
#
# splits/1 produces a stream; split/1 is retained for backward compatibility.
def splits($re; flags): . as $s
@@ -115,26 +114,47 @@ def splits($re): splits($re; null);
# split emits an array for backward compatibility
def split($re; flags): [ splits($re; flags) ];
#
# If s contains capture variables, then create a capture object and pipe it to s, bearing
# in mind that s could be a stream
def sub($re; s; $flags):
. as $in
| (reduce match($re; $flags) as $edit
({result: [], previous: 0};
$in[ .previous: ($edit | .offset) ] as $gap
# create the "capture" objects (one per item in s)
| [reduce ( $edit | .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair
({}; . + $pair) | s ] as $inserts
| reduce range(0; $inserts|length) as $ix (.; .result[$ix] += $gap + $inserts[$ix])
| .previous = ($edit | .offset + .length ) )
| .result[] + $in[.previous:] )
// $in;
# If s contains capture variables, then create a capture object and pipe it to s
def sub($re; s):
. as $in
| [match($re)]
| if length == 0 then $in
else .[0]
| . as $r
# # create the "capture" object:
| reduce ( $r | .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair
({}; . + $pair)
| $in[0:$r.offset] + s + $in[$r.offset+$r.length:]
end ;
#
# If s contains capture variables, then create a capture object and pipe it to s
def sub($re; s; flags):
def subg: [explode[] | select(. != 103)] | implode;
# "fla" should be flags with all occurrences of g removed; gs should be non-nil if flags has a g
def sub1(fla; gs):
def mysub:
. as $in
| [match($re; fla)]
| if length == 0 then $in
else .[0] as $edit
| ($edit | .offset + .length) as $len
# create the "capture" object:
| reduce ( $edit | .captures | .[] | select(.name != null) | { (.name) : .string } ) as $pair
({}; . + $pair)
| $in[0:$edit.offset]
+ s
+ ($in[$len:] | if length > 0 and gs then mysub else . end)
end ;
mysub ;
(flags | index("g")) as $gs
| (flags | if $gs then subg else . end) as $fla
| sub1($fla; $gs);
#
def sub($re; s): sub($re; s; "");
#
# repeated substitution of re (which may contain named captures)
def gsub($re; s; flags): sub($re; s; flags + "g");
def gsub($re; s): sub($re; s; "g");
#
########################################################################
# generic iterator/generator
def while(cond; update):
@@ -163,9 +183,7 @@ def any(condition): any(.[]; condition);
def all: all(.[]; .);
def any: any(.[]; .);
def last(g): reduce g as $item (null; $item);
def nth($n; g):
if $n < 0 then error("nth doesn't support negative indices")
else label $out | foreach g as $item ($n + 1; . - 1; if . <= 0 then $item, break $out else empty end) end;
def nth($n; g): if $n < 0 then error("nth doesn't support negative indices") else last(limit($n + 1; g)) end;
def first: .[0];
def last: .[-1];
def nth($n): .[$n];
@@ -188,7 +206,7 @@ def transpose:
| length as $length
| reduce range(0; $max) as $j
([]; . + [reduce range(0;$length) as $i ([]; . + [ $in[$i][$j] ] )] )
end;
end;
def in(xs): . as $x | xs | has($x);
def inside(xs): . as $x | xs | contains($x);
def repeat(exp):
@@ -219,6 +237,7 @@ def tostream:
getpath($p) |
reduce path(.[]?) as $q ([$p, .]; [$p+$q]);
# Assuming the input array is sorted, bsearch/1 returns
# the index of the target if the target is in the input array; and otherwise
# (-1 - ix), where ix is the insertion point that would leave the array sorted.
@@ -260,12 +279,6 @@ def walk(f):
else f
end;
# pathexps could be a stream of dot-paths
def pick(pathexps):
. as $in
| reduce path(pathexps) as $a (null;
setpath($a; $in|getpath($a)) );
# SQL-ish operators here:
def INDEX(stream; idx_expr):
reduce stream as $row ({}; .[$row|idx_expr|tostring] = $row);
+12 -11
View File
@@ -216,13 +216,17 @@ enum {
#define JVP_FLAGS_NUMBER_NATIVE_STR JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_NATIVE, 1))
#define JVP_FLAGS_NUMBER_LITERAL JVP_MAKE_FLAGS(JV_KIND_NUMBER, JVP_MAKE_PFLAGS(JVP_NUMBER_DECIMAL, 1))
#define STR(x) #x
#define XSTR(x) STR(x)
#define DBL_MAX_STR XSTR(DBL_MAX)
#define DBL_MIN_STR "-" XSTR(DBL_MAX)
// the decimal precision of binary double
#define BIN64_DEC_PRECISION (17)
#define DEC_NUMBER_STRING_GUARD (14)
#include "jv_thread.h"
#include <jv_thread.h>
#ifdef WIN32
#ifndef __MINGW32__
/* Copied from Heimdal: thread-specific keys; see lib/base/dll.c in Heimdal */
/*
@@ -487,9 +491,6 @@ pthread_getspecific(pthread_key_t key)
#else
#include <pthread.h>
#endif
#else
#include <pthread.h>
#endif
static pthread_key_t dec_ctx_key;
static pthread_key_t dec_ctx_dbl_key;
@@ -657,12 +658,12 @@ static const char* jvp_literal_number_literal(jv n) {
}
if (decNumberIsInfinite(pdec)) {
// We cannot preserve the literal data of numbers outside the limited
// range of exponent. Since `decNumberToString` returns "Infinity"
// (or "-Infinity"), and to reduce stack allocations as possible, we
// normalize infinities in the callers instead of printing the maximum
// (or minimum) double here.
return NULL;
// For backward compatibility.
if (decNumberIsNegative(pdec)) {
return DBL_MIN_STR;
} else {
return DBL_MAX_STR;
}
}
if (plit->literal_data == NULL) {
-1
View File
@@ -223,7 +223,6 @@ enum {
JV_PARSE_SEQ = 1,
JV_PARSE_STREAMING = 2,
JV_PARSE_STREAM_ERRORS = 4,
JV_PARSE_STRIP_COMMENTS = 8
};
jv jv_parse(const char* string);
+6 -58
View File
@@ -31,7 +31,6 @@ enum last_seen {
};
struct jv_parser {
pfunc (*scan)(struct jv_parser* p, char ch, jv* out);
const char* curr_buf;
int curr_buf_length;
int curr_buf_pos;
@@ -66,14 +65,9 @@ struct jv_parser {
unsigned int last_ch_was_ws:1;
};
static pfunc scan_json(struct jv_parser* p, char ch, jv* out);
static pfunc scan_line_comment(struct jv_parser* p, char ch, jv* out);
static pfunc scan_slash_comment(struct jv_parser* p, char ch, jv* out);
static pfunc scan_c_comment(struct jv_parser* p, char ch, jv* out);
static void parser_init(struct jv_parser* p, int flags) {
p->flags = flags;
p->scan = scan_json;
if ((p->flags & JV_PARSE_STREAMING)) {
p->path = jv_array();
} else {
@@ -305,7 +299,7 @@ static pfunc stream_token(struct jv_parser* p, char ch) {
p->output = JV_ARRAY(jv_copy(p->path), p->next);
p->next = jv_invalid();
}
p->path = jv_array_set(p->path, p->stacklen - 1, jv_null()); // ready for another key:value pair
p->path = jv_array_set(p->path, p->stacklen - 1, jv_true()); // ready for another name:value pair
p->last_seen = JV_LAST_COMMA;
} else {
assert(k == JV_KIND_NULL);
@@ -619,42 +613,12 @@ static int stream_is_top_num(struct jv_parser* p) {
#define is_top_num(p) \
(((p)->flags & JV_PARSE_STREAMING) ? stream_is_top_num((p)) : parse_is_top_num((p)))
static pfunc scan_line_comment(struct jv_parser* p, char ch, jv* out) {
if(ch == '\n')
p->scan = scan_json;
return OK;
}
static pfunc scan_c_comment_close(struct jv_parser* p, char ch, jv* out) {
if(ch == '/') {
p->scan = scan_json;
} else {
p->scan = scan_c_comment;
static pfunc scan(struct jv_parser* p, char ch, jv* out) {
p->column++;
if (ch == '\n') {
p->line++;
p->column = 0;
}
return OK;
}
static pfunc scan_c_comment(struct jv_parser* p, char ch, jv* out) {
if(ch == '*') {
p->scan = scan_c_comment_close;
}
return OK;
}
static pfunc scan_slash_comment(struct jv_parser* p, char ch, jv* out) {
if(ch == '/') {
p->scan = scan_line_comment;
return OK;
}
if(ch == '*') {
p->scan = scan_c_comment;
return OK;
}
return "Incomplete comment token; slash must be followed by another slash or asterisk";
}
static pfunc scan_json(struct jv_parser* p, char ch, jv* out) {
if (ch == '\036' /* ASCII RS; see draft-ietf-json-sequence-07 */) {
if (check_truncation(p)) {
if (check_literal(p) == 0 && is_top_num(p))
@@ -671,15 +635,9 @@ static pfunc scan_json(struct jv_parser* p, char ch, jv* out) {
*out = jv_invalid();
return OK;
}
presult answer = 0;
p->last_ch_was_ws = 0;
if (p->st == JV_PARSER_NORMAL) {
if(ch == '/' && (p->flags & JV_PARSE_STRIP_COMMENTS)) {
p->scan = scan_slash_comment;
return OK;
}
chclass cls = classify(ch);
if (cls == WHITESPACE)
p->last_ch_was_ws = 1;
@@ -720,16 +678,6 @@ static pfunc scan_json(struct jv_parser* p, char ch, jv* out) {
return answer;
}
static pfunc scan(struct jv_parser* p, char ch, jv* out) {
p->column++;
if (ch == '\n') {
p->line++;
p->column = 0;
}
return p->scan(p, ch, out);
}
struct jv_parser* jv_parser_new(int flags) {
struct jv_parser* p = jv_mem_alloc(sizeof(struct jv_parser));
parser_init(p, flags);
-4
View File
@@ -2,7 +2,6 @@
#define JV_THREAD_H
#ifdef WIN32
#ifndef __MINGW32__
#include <windows.h>
#include <winnt.h>
#include <errno.h>
@@ -70,7 +69,4 @@ void *pthread_getspecific(pthread_key_t);
#else
#include <pthread.h>
#endif
#else
#include <pthread.h>
#endif
#endif /* JV_THREAD_H */
+156 -165
View File
@@ -281,6 +281,7 @@ typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@@ -445,7 +446,7 @@ struct yy_buffer_state
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
int yy_n_chars;
yy_size_t yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
@@ -522,7 +523,7 @@ static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner );
void *yyalloc ( yy_size_t , yyscan_t yyscanner );
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
@@ -569,12 +570,12 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
*/
#define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \
yyleng = (int) (yy_cp - yy_bp); \
yyleng = (yy_size_t) (yy_cp - yy_bp); \
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
#define YY_NUM_RULES 51
#define YY_END_OF_BUFFER 52
#define YY_NUM_RULES 50
#define YY_END_OF_BUFFER 51
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -582,26 +583,25 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static const flex_int16_t yy_accept[163] =
static const flex_int16_t yy_accept[158] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 52, 50, 49, 49, 50, 40, 1, 35,
35, 36, 37, 35, 35, 35, 35, 35, 35, 39,
35, 35, 35, 35, 50, 46, 46, 46, 46, 46,
0, 0, 51, 49, 48, 48, 49, 40, 1, 35,
35, 36, 37, 35, 35, 35, 35, 35, 39, 35,
35, 35, 35, 49, 46, 46, 46, 46, 46, 46,
46, 46, 46, 46, 46, 46, 46, 46, 35, 44,
44, 42, 45, 49, 2, 1, 48, 48, 29, 27,
25, 26, 33, 39, 47, 18, 28, 39, 39, 0,
31, 3, 32, 0, 38, 46, 0, 46, 4, 46,
46, 46, 46, 46, 46, 9, 46, 46, 46, 46,
14, 46, 46, 46, 24, 44, 43, 41, 43, 48,
44, 42, 45, 48, 2, 1, 29, 27, 25, 26,
33, 39, 47, 18, 28, 39, 39, 0, 31, 3,
32, 0, 38, 46, 0, 46, 46, 4, 46, 46,
46, 46, 46, 46, 9, 46, 46, 46, 46, 14,
46, 46, 46, 24, 44, 43, 41, 43, 47, 30,
0, 48, 47, 30, 39, 0, 39, 34, 0, 13,
46, 46, 8, 46, 46, 15, 46, 46, 46, 46,
46, 46, 46, 19, 0, 43, 0, 48, 46, 46,
46, 12, 11, 46, 46, 46, 46, 46, 46, 10,
43, 48, 22, 20, 46, 46, 46, 21, 46, 46,
43, 48, 46, 5, 46, 7, 16, 48, 17, 6,
23, 0
39, 0, 39, 34, 0, 46, 13, 46, 46, 8,
46, 46, 15, 46, 46, 46, 46, 46, 46, 46,
19, 0, 43, 46, 46, 46, 46, 12, 11, 46,
46, 46, 46, 46, 46, 10, 43, 46, 22, 20,
46, 46, 46, 21, 46, 46, 43, 46, 46, 5,
46, 7, 16, 23, 17, 6, 0
} ;
static const YY_CHAR yy_ec[256] =
@@ -646,99 +646,96 @@ static const YY_CHAR yy_meta[54] =
1, 1, 1
} ;
static const flex_int16_t yy_base[178] =
static const flex_int16_t yy_base[171] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51, 52, 329, 330, 57, 59, 306, 330, 0, 296,
304, 330, 330, 303, 302, 330, 301, 47, 47, 50,
300, 299, 298, 302, 0, 299, 48, 37, 52, 51,
53, 54, 60, 56, 55, 59, 57, 63, 295, 0,
0, 330, 75, 87, 330, 0, 297, 73, 330, 330,
330, 330, 330, 89, 0, 293, 330, 90, 94, 100,
330, 330, 330, 297, 0, 294, 291, 87, 287, 92,
81, 95, 100, 101, 104, 283, 108, 112, 115, 114,
280, 116, 118, 119, 330, 0, 266, 330, 263, 271,
51, 52, 319, 320, 57, 59, 296, 320, 0, 320,
295, 320, 320, 294, 293, 292, 47, 47, 50, 291,
290, 289, 293, 0, 290, 48, 51, 37, 52, 53,
54, 55, 59, 56, 63, 57, 68, 71, 286, 0,
0, 320, 75, 89, 320, 0, 320, 320, 320, 320,
320, 87, 0, 285, 320, 92, 95, 103, 320, 320,
320, 289, 0, 286, 285, 74, 101, 284, 89, 81,
93, 87, 108, 113, 283, 116, 114, 118, 119, 282,
120, 121, 122, 320, 0, 271, 320, 270, 0, 320,
268, 121, 0, 330, 125, 255, 250, 330, 0, 245,
123, 122, 240, 126, 138, 238, 139, 140, 125, 141,
145, 146, 148, 235, 158, 223, 0, 152, 229, 153,
151, 220, 208, 154, 157, 159, 160, 161, 163, 207,
196, 164, 204, 203, 166, 162, 169, 202, 173, 180,
191, 186, 168, 200, 192, 199, 196, 193, 195, 194,
171, 330, 228, 237, 240, 246, 251, 256, 265, 274,
279, 284, 289, 291, 296, 300, 304
126, 280, 279, 320, 0, 123, 277, 126, 130, 274,
128, 127, 270, 133, 131, 137, 141, 147, 149, 151,
266, 161, 253, 259, 154, 155, 161, 256, 254, 157,
160, 162, 163, 164, 166, 242, 227, 171, 233, 228,
167, 165, 168, 226, 172, 173, 213, 188, 174, 221,
178, 211, 199, 198, 197, 196, 320, 219, 228, 234,
239, 244, 253, 262, 267, 272, 274, 279, 283, 287
} ;
static const flex_int16_t yy_def[178] =
static const flex_int16_t yy_def[171] =
{ 0,
162, 1, 1, 1, 1, 1, 1, 1, 1, 1,
163, 163, 162, 162, 162, 162, 162, 162, 164, 165,
162, 162, 162, 162, 162, 162, 162, 166, 162, 162,
162, 162, 162, 162, 167, 168, 168, 168, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 162, 169,
169, 162, 170, 162, 162, 164, 171, 171, 162, 162,
162, 162, 162, 162, 172, 162, 162, 162, 162, 162,
162, 162, 162, 162, 167, 168, 162, 168, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
168, 168, 168, 168, 162, 169, 162, 162, 173, 171,
157, 1, 1, 1, 1, 1, 1, 1, 1, 1,
158, 158, 157, 157, 157, 157, 157, 157, 159, 157,
157, 157, 157, 157, 157, 157, 160, 157, 157, 157,
157, 157, 157, 161, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 157, 163,
163, 157, 164, 157, 157, 159, 157, 157, 157, 157,
157, 157, 165, 157, 157, 157, 157, 157, 157, 157,
157, 157, 161, 162, 157, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 157, 163, 157, 157, 166, 165, 157,
162, 171, 172, 162, 162, 162, 162, 162, 174, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
168, 168, 168, 168, 170, 175, 165, 171, 168, 168,
168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
176, 171, 168, 168, 168, 168, 168, 168, 168, 168,
177, 171, 168, 168, 168, 168, 168, 171, 168, 168,
171, 0, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162
157, 157, 157, 157, 167, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 164, 168, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 169, 162, 162, 162,
162, 162, 162, 162, 162, 162, 170, 162, 162, 162,
162, 162, 162, 162, 162, 162, 0, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157
} ;
static const flex_int16_t yy_nxt[384] =
static const flex_int16_t yy_nxt[374] =
{ 0,
14, 15, 16, 14, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 26, 26,
31, 32, 33, 34, 35, 36, 36, 22, 14, 23,
36, 37, 38, 39, 40, 41, 42, 36, 43, 36,
44, 45, 36, 46, 36, 47, 36, 48, 36, 36,
22, 49, 23, 51, 51, 77, 52, 52, 54, 54,
54, 54, 63, 66, 64, 68, 77, 69, 67, 77,
77, 77, 77, 77, 77, 77, 70, 77, 77, 53,
53, 77, 80, 81, 98, 70, 82, 89, 54, 54,
78, 101, 92, 83, 79, 84, 86, 85, 90, 77,
23, 24, 25, 20, 26, 27, 28, 29, 20, 20,
30, 31, 32, 33, 34, 35, 35, 22, 14, 23,
36, 37, 38, 39, 40, 41, 42, 35, 43, 35,
44, 45, 35, 46, 35, 47, 35, 48, 35, 35,
22, 49, 23, 51, 51, 75, 52, 52, 54, 54,
54, 54, 61, 64, 62, 66, 75, 67, 65, 75,
75, 75, 75, 75, 75, 75, 68, 75, 76, 53,
53, 75, 79, 80, 97, 68, 75, 88, 81, 75,
54, 54, 75, 77, 82, 85, 83, 78, 84, 75,
93, 87, 88, 102, 91, 77, 64, 105, 94, 68,
77, 69, 106, 77, 106, 70, 70, 107, 77, 77,
70, 110, 77, 99, 70, 70, 77, 111, 112, 70,
77, 113, 77, 77, 77, 116, 77, 77, 114, 101,
77, 77, 105, 77, 77, 119, 115, 120, 121, 117,
122, 70, 118, 123, 130, 131, 77, 77, 77, 77,
70, 128, 132, 77, 77, 136, 77, 162, 124, 77,
101, 77, 77, 133, 134, 77, 137, 77, 77, 77,
77, 77, 101, 135, 77, 145, 77, 77, 144, 101,
140, 77, 143, 138, 139, 142, 150, 152, 77, 153,
86, 87, 90, 91, 62, 75, 89, 75, 92, 101,
66, 75, 67, 68, 106, 102, 93, 102, 68, 75,
103, 68, 68, 98, 108, 111, 75, 68, 109, 110,
68, 75, 75, 112, 75, 107, 75, 75, 75, 75,
75, 75, 113, 101, 75, 75, 75, 116, 75, 75,
117, 75, 68, 118, 119, 75, 120, 126, 114, 75,
115, 68, 129, 127, 128, 75, 125, 75, 130, 75,
157, 121, 75, 75, 131, 75, 133, 132, 75, 75,
75, 75, 75, 75, 75, 75, 75, 138, 141, 75,
75, 75, 75, 136, 139, 134, 75, 135, 140, 146,
148, 149, 146, 155, 101, 159, 99, 147, 156, 154,
77, 101, 77, 77, 77, 157, 158, 77, 77, 125,
77, 77, 77, 161, 125, 77, 77, 160, 50, 50,
50, 50, 50, 50, 50, 50, 50, 56, 77, 56,
56, 56, 56, 56, 56, 56, 57, 77, 57, 65,
65, 125, 65, 77, 65, 75, 77, 75, 77, 75,
76, 76, 76, 77, 76, 96, 96, 107, 96, 96,
96, 96, 107, 96, 97, 97, 97, 97, 97, 97,
97, 97, 97, 100, 100, 100, 127, 100, 103, 101,
103, 125, 103, 126, 125, 126, 126, 129, 77, 129,
149, 148, 151, 144, 145, 142, 75, 152, 153, 98,
143, 155, 150, 156, 75, 75, 75, 75, 154, 50,
50, 50, 50, 50, 50, 50, 50, 50, 56, 75,
56, 56, 56, 56, 56, 56, 56, 63, 63, 75,
63, 122, 63, 73, 75, 73, 75, 73, 74, 74,
74, 75, 74, 95, 95, 122, 95, 95, 95, 95,
75, 95, 96, 96, 96, 96, 96, 96, 96, 96,
96, 99, 75, 99, 75, 99, 123, 75, 123, 123,
124, 122, 124, 137, 75, 137, 137, 147, 75, 147,
147, 96, 75, 96, 96, 75, 103, 103, 122, 122,
141, 77, 141, 141, 151, 77, 151, 151, 97, 109,
97, 97, 77, 108, 104, 101, 95, 77, 74, 73,
72, 71, 62, 61, 60, 59, 58, 55, 162, 13,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162
75, 75, 75, 105, 75, 104, 100, 94, 75, 72,
71, 70, 69, 60, 59, 58, 57, 55, 157, 13,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157
} ;
static const flex_int16_t yy_chk[384] =
static const flex_int16_t yy_chk[374] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -746,42 +743,41 @@ static const flex_int16_t yy_chk[384] =
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, 38, 11, 12, 15, 15,
16, 16, 28, 29, 28, 30, 37, 30, 29, 40,
39, 41, 42, 45, 44, 47, 30, 46, 43, 11,
12, 48, 38, 39, 53, 30, 40, 44, 54, 54,
37, 58, 47, 41, 37, 41, 43, 42, 45, 81,
16, 16, 27, 28, 27, 29, 36, 29, 28, 37,
39, 40, 41, 42, 44, 46, 29, 43, 36, 11,
12, 45, 38, 39, 53, 29, 47, 44, 40, 48,
54, 54, 76, 37, 41, 43, 41, 37, 42, 80,
48, 43, 43, 58, 46, 78, 64, 68, 48, 69,
80, 69, 70, 82, 70, 64, 68, 70, 83, 84,
69, 78, 85, 53, 64, 68, 87, 80, 81, 69,
88, 82, 90, 89, 92, 84, 93, 94, 83, 102,
112, 111, 105, 119, 114, 88, 83, 89, 90, 85,
92, 105, 87, 93, 111, 112, 115, 117, 118, 120,
105, 102, 114, 121, 122, 119, 123, 125, 94, 131,
128, 130, 134, 115, 117, 135, 120, 136, 137, 138,
146, 139, 142, 118, 145, 134, 153, 147, 131, 161,
123, 149, 130, 121, 122, 128, 139, 142, 150, 145,
43, 43, 46, 47, 62, 82, 45, 79, 48, 66,
67, 81, 67, 62, 76, 68, 48, 68, 66, 77,
68, 67, 62, 53, 79, 82, 83, 66, 80, 81,
67, 84, 87, 82, 86, 77, 88, 89, 91, 92,
93, 106, 83, 101, 108, 112, 111, 87, 109, 115,
88, 114, 101, 89, 91, 116, 92, 108, 84, 117,
86, 101, 112, 109, 111, 118, 106, 119, 114, 120,
122, 93, 125, 126, 115, 130, 117, 116, 131, 127,
132, 133, 134, 142, 135, 141, 143, 125, 130, 138,
145, 146, 149, 120, 126, 118, 151, 119, 127, 135,
137, 138, 135, 147, 152, 153, 125, 136, 149, 146,
155, 158, 160, 159, 157, 150, 152, 156, 154, 151,
148, 144, 143, 158, 141, 140, 133, 155, 163, 163,
163, 163, 163, 163, 163, 163, 163, 164, 132, 164,
164, 164, 164, 164, 164, 164, 165, 129, 165, 166,
166, 126, 166, 124, 166, 167, 116, 167, 113, 167,
168, 168, 168, 110, 168, 169, 169, 107, 169, 169,
169, 169, 106, 169, 170, 170, 170, 170, 170, 170,
170, 170, 170, 171, 171, 171, 101, 171, 172, 100,
172, 99, 172, 173, 97, 173, 173, 174, 91, 174,
141, 138, 143, 133, 134, 131, 148, 145, 146, 122,
132, 149, 142, 151, 156, 155, 154, 153, 148, 158,
158, 158, 158, 158, 158, 158, 158, 158, 159, 152,
159, 159, 159, 159, 159, 159, 159, 160, 160, 150,
160, 147, 160, 161, 144, 161, 140, 161, 162, 162,
162, 139, 162, 163, 163, 137, 163, 163, 163, 163,
136, 163, 164, 164, 164, 164, 164, 164, 164, 164,
164, 165, 129, 165, 128, 165, 166, 124, 166, 166,
167, 123, 167, 168, 121, 168, 168, 169, 113, 169,
169, 170, 110, 170, 170, 107, 103, 102, 98, 96,
175, 86, 175, 175, 176, 79, 176, 176, 177, 77,
177, 177, 76, 74, 66, 57, 49, 36, 34, 33,
32, 31, 27, 25, 24, 21, 20, 17, 13, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162
90, 85, 78, 75, 74, 72, 64, 49, 35, 33,
32, 31, 30, 26, 25, 24, 21, 17, 13, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157, 157, 157, 157, 157, 157, 157, 157,
157, 157, 157
} ;
/* The intent behind this definition is that it'll catch
@@ -808,14 +804,14 @@ struct lexer_param;
yyset_extra(yylloc->end, yyscanner); \
} while (0);
#line 811 "src/lexer.c"
#line 807 "src/lexer.c"
#line 25 "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 816 "src/lexer.c"
#line 812 "src/lexer.c"
#define YY_NO_INPUT 1
#line 818 "src/lexer.c"
#line 814 "src/lexer.c"
#define INITIAL 0
#define IN_PAREN 1
@@ -847,8 +843,8 @@ struct yyguts_t
size_t yy_buffer_stack_max; /**< capacity of stack. */
YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
char yy_hold_char;
int yy_n_chars;
int yyleng_r;
yy_size_t yy_n_chars;
yy_size_t yyleng_r;
char *yy_c_buf_p;
int yy_init;
int yy_start;
@@ -905,7 +901,7 @@ FILE *yyget_out ( yyscan_t yyscanner );
void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
int yyget_leng ( yyscan_t yyscanner );
yy_size_t yyget_leng ( yyscan_t yyscanner );
char *yyget_text ( yyscan_t yyscanner );
@@ -990,7 +986,7 @@ static int input ( yyscan_t yyscanner );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
int n; \
yy_size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -1109,7 +1105,7 @@ YY_DECL
#line 38 "src/lexer.l"
#line 1112 "src/lexer.c"
#line 1108 "src/lexer.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
@@ -1136,13 +1132,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 >= 163 )
if ( yy_current_state >= 158 )
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] != 330 );
while ( yy_base[yy_current_state] != 320 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -1433,27 +1429,22 @@ YY_RULE_SETUP
{ yylval->literal = jv_string(yytext+1); return FIELD;}
YY_BREAK
case 48:
/* rule 48 can match eol */
YY_RULE_SETUP
#line 125 "src/lexer.l"
{ yylval->literal = jv_string(yytext+1); return BINDING;}
#line 126 "src/lexer.l"
{}
YY_BREAK
case 49:
/* rule 49 can match eol */
YY_RULE_SETUP
#line 127 "src/lexer.l"
{}
#line 128 "src/lexer.l"
{ return INVALID_CHARACTER; }
YY_BREAK
case 50:
YY_RULE_SETUP
#line 129 "src/lexer.l"
{ return INVALID_CHARACTER; }
YY_BREAK
case 51:
YY_RULE_SETUP
#line 131 "src/lexer.l"
#line 130 "src/lexer.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
#line 1456 "src/lexer.c"
#line 1447 "src/lexer.c"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(IN_PAREN):
case YY_STATE_EOF(IN_BRACKET):
@@ -1646,7 +1637,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
int num_to_read =
yy_size_t num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
@@ -1660,7 +1651,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( b->yy_is_our_buffer )
{
int new_size = b->yy_buf_size * 2;
yy_size_t new_size = b->yy_buf_size * 2;
if ( new_size <= 0 )
b->yy_buf_size += b->yy_buf_size / 8;
@@ -1718,7 +1709,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
@@ -1757,7 +1748,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 >= 163 )
if ( yy_current_state >= 158 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1786,11 +1777,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 >= 163 )
if ( yy_current_state >= 158 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 162);
yy_is_jam = (yy_current_state == 157);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
@@ -1825,7 +1816,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{ /* need more input */
int offset = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr);
yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) )
@@ -2203,12 +2194,12 @@ YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner)
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len , yyscan_t yyscanner)
YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n;
int i;
yy_size_t i;
/* Get memory for full buffer, including space for trailing EOB's. */
n = (yy_size_t) (_yybytes_len + 2);
@@ -2293,7 +2284,7 @@ static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner)
do \
{ \
/* Undo effects of setting up yytext. */ \
int yyless_macro_arg = (n); \
yy_size_t yyless_macro_arg = (n); \
YY_LESS_LINENO(yyless_macro_arg);\
yytext[yyleng] = yyg->yy_hold_char; \
yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
@@ -2361,7 +2352,7 @@ FILE *yyget_out (yyscan_t yyscanner)
/** Get the length of the current token.
* @param yyscanner The scanner object.
*/
int yyget_leng (yyscan_t yyscanner)
yy_size_t yyget_leng (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng;
@@ -2625,7 +2616,7 @@ static int yy_flex_strlen (const char * s , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
#line 131 "src/lexer.l"
#line 130 "src/lexer.l"
/* perhaps these should be calls... */
/*
+6 -5
View File
@@ -285,6 +285,7 @@ typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
@@ -398,7 +399,7 @@ struct yy_buffer_state
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
int yy_n_chars;
yy_size_t yy_n_chars;
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
@@ -442,7 +443,7 @@ void yypop_buffer_state ( yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner );
void *yyalloc ( yy_size_t , yyscan_t yyscanner );
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
@@ -500,7 +501,7 @@ FILE *yyget_out ( yyscan_t yyscanner );
void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
int yyget_leng ( yyscan_t yyscanner );
yy_size_t yyget_leng ( yyscan_t yyscanner );
char *yyget_text ( yyscan_t yyscanner );
@@ -731,9 +732,9 @@ extern int yylex \
#undef yyTABLES_NAME
#endif
#line 131 "src/lexer.l"
#line 130 "src/lexer.l"
#line 737 "src/lexer.h"
#line 738 "src/lexer.h"
#undef jq_yyIN_HEADER
#endif /* jq_yyHEADER_H */
+1 -2
View File
@@ -60,7 +60,7 @@ struct lexer_param;
"catch" { return CATCH; }
"label" { return LABEL; }
"break" { return BREAK; }
"$__loc__" { return LOC; }
"__loc__" { return LOC; }
"|=" { return SETPIPE; }
"+=" { return SETPLUS; }
"-=" { return SETMINUS; }
@@ -122,7 +122,6 @@ struct lexer_param;
([a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]* { yylval->literal = jv_string(yytext); return IDENT;}
\.[a-zA-Z_][a-zA-Z_0-9]* { yylval->literal = jv_string(yytext+1); return FIELD;}
\$([a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]* { yylval->literal = jv_string(yytext+1); return BINDING;}
[ \n\t]+ {}
+5 -22
View File
@@ -81,7 +81,6 @@ static void usage(int code, int keep_it_short) {
" -M monochrome (don't colorize JSON);\n"
" -S sort keys of objects on output;\n"
" --tab use tabs for indentation;\n"
" --strip-comments accept and strip comments from input;\n"
" --arg a v set variable $a to value <v>;\n"
" --argjson a v set variable $a to JSON value <v>;\n"
" --slurpfile a f set variable $a to an array of JSON texts read from <f>;\n"
@@ -318,12 +317,7 @@ int main(int argc, char* argv[]) {
if (further_args_are_strings) {
ARGS = jv_array_append(ARGS, jv_string(argv[i]));
} else if (further_args_are_json) {
jv v = jv_parse(argv[i]);
if (!jv_is_valid(v)) {
fprintf(stderr, "%s: invalid JSON text passed to --jsonargs\n", progname);
die();
}
ARGS = jv_array_append(ARGS, v);
ARGS = jv_array_append(ARGS, jv_parse(argv[i]));
} else {
jq_util_input_add_input(input_state, argv[i]);
nfiles++;
@@ -336,12 +330,7 @@ int main(int argc, char* argv[]) {
if (further_args_are_strings) {
ARGS = jv_array_append(ARGS, jv_string(argv[i]));
} else if (further_args_are_json) {
jv v = jv_parse(argv[i]);
if (!jv_is_valid(v)) {
fprintf(stderr, "%s: invalid JSON text passed to --jsonargs\n", progname);
die();
}
ARGS = jv_array_append(ARGS, v);
ARGS = jv_array_append(ARGS, jv_parse(argv[i]));
} else {
jq_util_input_add_input(input_state, argv[i]);
nfiles++;
@@ -455,10 +444,6 @@ int main(int argc, char* argv[]) {
parser_flags |= JV_PARSE_STREAMING;
continue;
}
if (isoption(argv[i], 0, "strip-comments", &short_opts)) {
parser_flags |= JV_PARSE_STRIP_COMMENTS;
continue;
}
if (isoption(argv[i], 0, "stream-errors", &short_opts)) {
parser_flags |= JV_PARSE_STREAM_ERRORS;
continue;
@@ -607,7 +592,7 @@ int main(int argc, char* argv[]) {
// Default search path list
lib_search_paths = JV_ARRAY(jv_string("~/.jq"),
jv_string("$ORIGIN/../lib/jq"),
jv_string("$ORIGIN/../lib"));
jv_string("$ORIGIN/lib"));
}
jq_set_attr(jq, jv_string("JQ_LIBRARY_PATH"), lib_search_paths);
@@ -697,20 +682,18 @@ int main(int argc, char* argv[]) {
ret = process(jq, value, jq_flags, dumpopts);
if (ret <= 0 && ret != JQ_OK_NO_OUTPUT)
last_result = (ret != JQ_OK_NULL_KIND);
if (jq_halted(jq))
break;
continue;
}
// Parse error
jv msg = jv_invalid_get_msg(value);
if (!(options & SEQ)) {
ret = JQ_ERROR_UNKNOWN;
// --seq -> errors are not fatal
ret = JQ_OK_NO_OUTPUT;
fprintf(stderr, "jq: parse error: %s\n", jv_string_value(msg));
jv_free(msg);
break;
}
// --seq -> errors are not fatal
fprintf(stderr, "jq: ignoring parse error: %s\n", jv_string_value(msg));
jv_free(msg);
}
+1369 -1335
View File
File diff suppressed because it is too large. Load diff
+85 -87
View File
@@ -76,49 +76,48 @@ struct lexer_param;
INVALID_CHARACTER = 258, /* INVALID_CHARACTER */
IDENT = 259, /* IDENT */
FIELD = 260, /* FIELD */
BINDING = 261, /* BINDING */
LITERAL = 262, /* LITERAL */
FORMAT = 263, /* FORMAT */
REC = 264, /* ".." */
SETMOD = 265, /* "%=" */
EQ = 266, /* "==" */
NEQ = 267, /* "!=" */
DEFINEDOR = 268, /* "//" */
AS = 269, /* "as" */
DEF = 270, /* "def" */
MODULE = 271, /* "module" */
IMPORT = 272, /* "import" */
INCLUDE = 273, /* "include" */
IF = 274, /* "if" */
THEN = 275, /* "then" */
ELSE = 276, /* "else" */
ELSE_IF = 277, /* "elif" */
REDUCE = 278, /* "reduce" */
FOREACH = 279, /* "foreach" */
END = 280, /* "end" */
AND = 281, /* "and" */
OR = 282, /* "or" */
TRY = 283, /* "try" */
CATCH = 284, /* "catch" */
LABEL = 285, /* "label" */
BREAK = 286, /* "break" */
LOC = 287, /* "$__loc__" */
SETPIPE = 288, /* "|=" */
SETPLUS = 289, /* "+=" */
SETMINUS = 290, /* "-=" */
SETMULT = 291, /* "*=" */
SETDIV = 292, /* "/=" */
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 */
LITERAL = 261, /* LITERAL */
FORMAT = 262, /* FORMAT */
REC = 263, /* ".." */
SETMOD = 264, /* "%=" */
EQ = 265, /* "==" */
NEQ = 266, /* "!=" */
DEFINEDOR = 267, /* "//" */
AS = 268, /* "as" */
DEF = 269, /* "def" */
MODULE = 270, /* "module" */
IMPORT = 271, /* "import" */
INCLUDE = 272, /* "include" */
IF = 273, /* "if" */
THEN = 274, /* "then" */
ELSE = 275, /* "else" */
ELSE_IF = 276, /* "elif" */
REDUCE = 277, /* "reduce" */
FOREACH = 278, /* "foreach" */
END = 279, /* "end" */
AND = 280, /* "and" */
OR = 281, /* "or" */
TRY = 282, /* "try" */
CATCH = 283, /* "catch" */
LABEL = 284, /* "label" */
BREAK = 285, /* "break" */
LOC = 286, /* "__loc__" */
SETPIPE = 287, /* "|=" */
SETPLUS = 288, /* "+=" */
SETMINUS = 289, /* "-=" */
SETMULT = 290, /* "*=" */
SETDIV = 291, /* "/=" */
SETDEFINEDOR = 292, /* "//=" */
LESSEQ = 293, /* "<=" */
GREATEREQ = 294, /* ">=" */
ALTERNATION = 295, /* "?//" */
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
@@ -130,49 +129,48 @@ struct lexer_param;
#define INVALID_CHARACTER 258
#define IDENT 259
#define FIELD 260
#define BINDING 261
#define LITERAL 262
#define FORMAT 263
#define REC 264
#define SETMOD 265
#define EQ 266
#define NEQ 267
#define DEFINEDOR 268
#define AS 269
#define DEF 270
#define MODULE 271
#define IMPORT 272
#define INCLUDE 273
#define IF 274
#define THEN 275
#define ELSE 276
#define ELSE_IF 277
#define REDUCE 278
#define FOREACH 279
#define END 280
#define AND 281
#define OR 282
#define TRY 283
#define CATCH 284
#define LABEL 285
#define BREAK 286
#define LOC 287
#define SETPIPE 288
#define SETPLUS 289
#define SETMINUS 290
#define SETMULT 291
#define SETDIV 292
#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 LITERAL 261
#define FORMAT 262
#define REC 263
#define SETMOD 264
#define EQ 265
#define NEQ 266
#define DEFINEDOR 267
#define AS 268
#define DEF 269
#define MODULE 270
#define IMPORT 271
#define INCLUDE 272
#define IF 273
#define THEN 274
#define ELSE 275
#define ELSE_IF 276
#define REDUCE 277
#define FOREACH 278
#define END 279
#define AND 280
#define OR 281
#define TRY 282
#define CATCH 283
#define LABEL 284
#define BREAK 285
#define LOC 286
#define SETPIPE 287
#define SETPLUS 288
#define SETMINUS 289
#define SETMULT 290
#define SETDIV 291
#define SETDEFINEDOR 292
#define LESSEQ 293
#define GREATEREQ 294
#define ALTERNATION 295
#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;
+55 -46
View File
@@ -49,7 +49,6 @@ struct lexer_param;
%token INVALID_CHARACTER
%token <literal> IDENT
%token <literal> FIELD
%token <literal> BINDING
%token <literal> LITERAL
%token <literal> FORMAT
%token REC ".."
@@ -75,7 +74,7 @@ struct lexer_param;
%token CATCH "catch"
%token LABEL "label"
%token BREAK "break"
%token LOC "$__loc__"
%token LOC "__loc__"
%token SETPIPE "|="
%token SETPLUS "+="
%token SETMINUS "-="
@@ -368,6 +367,9 @@ Term "as" Patterns '|' Exp {
"if" Exp "then" Exp ElseBody {
$$ = gen_cond($2, $4, $5);
} |
"if" Exp "then" Exp "end" {
$$ = gen_cond($2, $4, gen_noop());
} |
"if" Exp "then" error {
FAIL(@$, "Possibly unterminated 'if' statement");
$$ = $2;
@@ -386,10 +388,10 @@ Term "as" Patterns '|' Exp {
$$ = $2;
} |
"label" BINDING '|' Exp {
jv v = jv_string_fmt("*label-%s", jv_string_value($2));
$$ = gen_location(@$, locations, gen_label(jv_string_value(v), $4));
jv_free($2);
"label" '$' IDENT '|' Exp {
jv v = jv_string_fmt("*label-%s", jv_string_value($3));
$$ = gen_location(@$, locations, gen_label(jv_string_value(v), $5));
jv_free($3);
jv_free(v);
} |
@@ -526,13 +528,13 @@ ImportWhat Exp ';' {
}
ImportWhat:
"import" ImportFrom "as" BINDING {
"import" ImportFrom "as" '$' IDENT {
jv v = block_const($2);
// XXX Make gen_import take only blocks and the int is_data so we
// don't have to free so much stuff here
$$ = gen_import(jv_string_value(v), jv_string_value($4), 1);
$$ = gen_import(jv_string_value(v), jv_string_value($5), 1);
block_free($2);
jv_free($4);
jv_free($5);
jv_free(v);
} |
"import" ImportFrom "as" IDENT {
@@ -580,9 +582,13 @@ Params ';' Param {
}
Param:
BINDING {
$$ = gen_param_regular(jv_string_value($1));
jv_free($1);
'$' IDENT {
$$ = gen_param_regular(jv_string_value($2));
jv_free($2);
} |
'$' Keyword {
$$ = gen_param_regular(jv_string_value($2));
jv_free($2);
} |
IDENT {
$$ = gen_param(jv_string_value($1));
@@ -619,9 +625,6 @@ ElseBody:
} |
"else" Exp "end" {
$$ = $2;
} |
"end" {
$$ = gen_noop();
}
ExpD:
@@ -643,13 +646,13 @@ Term:
REC {
$$ = gen_call("recurse", gen_noop());
} |
BREAK BINDING {
jv v = jv_string_fmt("*label-%s", jv_string_value($2)); // impossible symbol
BREAK '$' IDENT {
jv v = jv_string_fmt("*label-%s", jv_string_value($3)); // impossible symbol
$$ = gen_location(@$, locations,
BLOCK(gen_op_unbound(LOADV, jv_string_value(v)),
gen_call("error", gen_noop())));
jv_free(v);
jv_free($2);
jv_free($3);
} |
BREAK error {
FAIL(@$, "break requires a label to break to");
@@ -707,12 +710,6 @@ Term '[' ']' '?' {
Term '[' ']' %prec NONOPT {
$$ = block_join($1, gen_op_simple(EACH));
} |
Term '.' '[' ']' '?' {
$$ = block_join($1, gen_op_simple(EACH_OPT));
} |
Term '.' '[' ']' %prec NONOPT {
$$ = block_join($1, gen_op_simple(EACH));
} |
Term '[' Exp ':' Exp ']' '?' {
$$ = gen_slice_index($1, $3, $5, INDEX_OPT);
} |
@@ -771,17 +768,22 @@ FORMAT {
* DO NOT USE!! I will break your jq code if you do use this outside
* src/builtin.jq.
*/
'$' '$' '$' BINDING {
$$ = gen_location(@$, locations, gen_op_unbound(LOADVN, jv_string_value($4)));
jv_free($4);
'$' '$' '$' '$' IDENT {
$$ = gen_location(@$, locations, gen_op_unbound(LOADVN, jv_string_value($5)));
jv_free($5);
} |
BINDING {
$$ = gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($1)));
jv_free($1);
'$' IDENT {
$$ = gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($2)));
jv_free($2);
} |
"$__loc__" {
$$ = gen_const(JV_OBJECT(jv_string("file"), jv_copy(locations->fname),
jv_string("line"), jv_number(locfile_get_line(locations, @$.start) + 1)));
'$' Keyword {
if (strcmp(jv_string_value($2), "__loc__") == 0) {
$$ = gen_const(JV_OBJECT(jv_string("file"), jv_copy(locations->fname),
jv_string("line"), jv_number(locfile_get_line(locations, @$.start) + 1)));
} else {
$$ = gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($2)));
}
jv_free($2);
} |
IDENT {
const char *s = jv_string_value($1);
@@ -835,9 +837,9 @@ Pattern {
}
Pattern:
BINDING {
$$ = gen_op_unbound(STOREV, jv_string_value($1));
jv_free($1);
'$' IDENT {
$$ = gen_op_unbound(STOREV, jv_string_value($2));
jv_free($2);
} |
'[' ArrayPats ']' {
$$ = BLOCK($2, gen_op_simple(POP));
@@ -863,11 +865,11 @@ ObjPats ',' ObjPat {
}
ObjPat:
BINDING {
$$ = gen_object_matcher(gen_const($1), gen_op_unbound(STOREV, jv_string_value($1)));
'$' IDENT {
$$ = gen_object_matcher(gen_const($2), gen_op_unbound(STOREV, jv_string_value($2)));
} |
BINDING ':' Pattern {
$$ = gen_object_matcher(gen_const($1), BLOCK(gen_op_simple(DUP), gen_op_unbound(STOREV, jv_string_value($1)), $3));
'$' IDENT ':' Pattern {
$$ = gen_object_matcher(gen_const($2), BLOCK(gen_op_simple(DUP), gen_op_unbound(STOREV, jv_string_value($2)), $4));
} |
IDENT ':' Pattern {
$$ = gen_object_matcher(gen_const($1), $3);
@@ -945,6 +947,9 @@ Keyword:
} |
"break" {
$$ = jv_string("break");
} |
"__loc__" {
$$ = jv_string("__loc__");
}
MkDict:
@@ -969,13 +974,17 @@ IDENT ':' ExpD {
$$ = gen_dictpair($1, BLOCK(gen_op_simple(POP), gen_op_simple(DUP2),
gen_op_simple(DUP2), gen_op_simple(INDEX)));
}
| BINDING ':' ExpD {
$$ = gen_dictpair(gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($1))),
$3);
| '$' IDENT ':' ExpD {
$$ = gen_dictpair(gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($2))),
$4);
}
| BINDING {
$$ = gen_dictpair(gen_const($1),
gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($1))));
| '$' IDENT {
$$ = gen_dictpair(gen_const($2),
gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($2))));
}
| '$' Keyword {
$$ = gen_dictpair(gen_const($2),
gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($2))));
}
| IDENT {
$$ = gen_dictpair(gen_const(jv_copy($1)),
-15
View File
@@ -1,15 +0,0 @@
#!/bin/sh
. "${0%/*}/setup" "$@"
if [ "$(echo '{"hi":"there"/*comment*/}' | $VALGRIND $Q $JQ --strip-comments '.hi')" != '"there"' ]; then
echo "C-style comment test failed"
exit 1
fi
if [ "$(printf '{"hi"://comment\n"there"}' | $VALGRIND $Q $JQ --strip-comments '.hi')" != '"there"' ]; then
echo "C++-style comment test failed"
exit 1
fi
exit 0
+6 -67
View File
@@ -173,11 +173,6 @@ jq: error: Cannot use number (0) as object key at <top-level>, line 1:
[1,null,true,false,"abcdef",{},{"a":1,"b":2},[],[1,2,3,4,5],[1,2]]
[null,"bc",[],[2,3],[2]]
# chaining/suffix-list, with and without dot
map(try .a[] catch ., try .a.[] catch ., .a[]?, .a.[]?)
[{"a": [1,2]}, {"a": 123}]
[1,2,1,2,1,2,1,2,"Cannot iterate over number (123)","Cannot iterate over number (123)"]
#
# Negative array indices
#
@@ -324,13 +319,9 @@ null
"badness"
[1]
[first(range(.)), last(range(.))]
[first(range(.)), last(range(.)), nth(0; range(.)), nth(5; range(.)), try nth(-1; range(.)) catch .]
10
[0,9]
[nth(0,5,9,10,15; range(.)), try nth(-1; range(.)) catch .]
10
[0,5,9,"nth doesn't support negative indices"]
[0,9,0,5,"nth doesn't support negative indices"]
# Check that first(g) does not extract more than one value from g
first(1,error("foo"))
@@ -961,6 +952,10 @@ path(.a[path(.b)[0]])
[1,[[],{"a":2}]]
[[0],[1],[1,0],[1,1],[1,1,"a"]]
[leaf_paths]
[1,[[],{"a":2}]]
[[0],[1,1,"a"]]
["foo",1] as $p | getpath($p), setpath($p; 20), delpaths([$p])
{"bar": 42, "foo": ["a", "b", "c", "d"]}
"b"
@@ -1053,19 +1048,6 @@ def inc(x): x |= .+1; inc(.[].a)
{"a":[{"b":5}]}
{"a":[{"c":3,"b":5}]}
# #2051, deletion using assigning empty against arrays
(.[] | select(. >= 2)) |= empty
[1,5,3,0,7]
[1,0]
.[] |= select(. % 2 == 0)
[0,1,2,3,4,5]
[0,2,4]
.foo[1,4,2,3] |= empty
{"foo":[0,1,2,3,4,5]}
{"foo":[0,5]}
.[2][3] = 1
[4]
[4, null, [null, null, null, 1]]
@@ -1134,13 +1116,6 @@ null
7
[7]
[if false then 3 elif false then 4 end]
7
[7]
[if false then 3 elif false then 4 else . end]
7
[7]
[.[] | [.foo[] // .bar]]
[{"foo":[1,2], "bar": 42}, {"foo":[1], "bar": null}, {"foo":[null,false,3], "bar": 18}, {"foo":[], "bar":42}, {"foo": [null,false,null], "bar": 41}]
@@ -1293,14 +1268,6 @@ indices(", ")
["a", "ab", "abc"]
["aaa", "ababab", "abcabcabc"]
[.[] * "abc"]
[-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 3.7, 10.0]
[null,null,"","","abc","abc","abcabcabc","abcabcabcabcabcabcabcabcabcabc"]
[. * (nan,-nan)]
"abc"
[null,null]
[.[] / ","]
["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]
[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]
@@ -1604,11 +1571,6 @@ try (1/.) catch .
0
"number (1) and number (0) cannot be divided because the divisor is zero"
0/0, (0 as $x | $x/0) | isnan
0
true
true
try (1%.) catch .
0
"number (1) and number (0) cannot be divided (remainder) because the divisor is zero"
@@ -1769,26 +1731,3 @@ false
. |= try . catch .
1
1
# Using a keyword as variable/label name
123 as $label | $label
null
123
[ label $if | range(10) | ., (select(. == 5) | break $if) ]
null
[0,1,2,3,4,5]
reduce .[] as $then (4 as $else | $else; . as $elif | . + $then * $elif)
[1,2,3]
96
1 as $foreach | 2 as $and | 3 as $or | { $foreach, $and, $or, a }
{"a":4,"b":5}
{"foreach":1,"and":2,"or":3,"a":4}
[ foreach .[] as $try (1 as $catch | $catch - 1; . + $try; .) ]
[10,9,8,7]
[10,19,27,34]
+1 -17
View File
@@ -219,14 +219,6 @@ map_values(.+1)
{"a": 1, "b": 2, "c": 3}
{"a": 2, "b": 3, "c": 4}
pick(.a, .b.c, .x)
{"a": 1, "b": {"c": 2, "d": 3}, "e": 4}
{"a":1,"b":{"c":2},"x":null}
[1,2,3,4] | pick(.[2], .[0], .[0])
[1,2,3,4]
[1,null,3]
path(.a[0].b)
null
["a",0,"b"]
@@ -308,7 +300,7 @@ null
[1,[[],{"a":2}]]
[[0],[1],[1,0],[1,1],[1,1,"a"]]
[paths(type == "number")]
[paths(scalars)]
[1,[[],{"a":2}]]
[[0],[1,1,"a"]]
@@ -676,14 +668,6 @@ strptime("%Y-%m-%dT%H:%M:%SZ")|mktime
"2015-03-05T23:51:47Z"
1425599507
. == false
null
false
. == {"b": {"d": (4 + 1e-20), "c": 3}, "a":1}
{"a":1, "b": {"c": 3, "d": 4}}
true
.[] == 1
[1, 1.0, "1", "banana"]
true
+2 -73
View File
@@ -1,16 +1,12 @@
# match builtin
[match("( )*"; "g")]
"abc"
[{"offset":0, "length":0, "string":"", "captures":[]}, {"offset":1, "length":0, "string":"", "captures":[]}, {"offset":2, "length":0, "string":"", "captures":[]}, {"offset":3, "length":0, "string":"", "captures":[]}]
[{"offset":0, "length":0, "string":"", "captures":[]},{"offset":1, "length":0, "string":"", "captures":[]},{"offset":2, "length":0, "string":"", "captures":[]}]
[match("( )*"; "gn")]
"abc"
[]
[match(""; "g")]
"ab"
[{"offset":0,"length":0,"string":"","captures":[]},{"offset":1,"length":0,"string":"","captures":[]},{"offset":2,"length":0,"string":"","captures":[]}]
[match("a"; "gi")]
"āáàä"
[]
@@ -75,47 +71,10 @@ gsub("a";"b")
"aaaaa"
"bbbbb"
gsub("(.*)"; ""; "x")
gsub( "(.*)"; ""; "x")
""
""
gsub(""; "a"; "g")
""
"a"
gsub("^"; ""; "g")
"a"
"a"
gsub(""; "a"; "g")
"a"
"aaa"
gsub("$"; "a"; "g")
"a"
"aa"
gsub("^"; "a")
""
"a"
gsub("(?=u)"; "u")
"qux"
"quux"
gsub("^.*a"; "b")
"aaa"
"b"
gsub("^.*?a"; "b")
"aaa"
"baa"
# The following is for regression testing and should not be construed as a requirement:
[gsub("a"; "b", "c")]
"a"
["b","c"]
[.[] | scan(", ")]
["a,b, c, d, e,f",", a,b, c, d, e,f, "]
[", ",", ",", ",", ",", ",", ",", ",", "]
@@ -128,42 +87,12 @@ gsub("^.*?a"; "b")
["a,b, c, d, e,f",", a,b, c, d, e,f, "]
[[["a,b:c, d, e,f"],["a,b:c:d:e,f"],[", ",", ",", "]],[[":a,b, c, d, e,f, "],[":a,b:c:d:e,f:"],[", ",", ",", ",", ",", "]]]
[.[] | scan("b+"; "i")]
["","bBb","abcABBBCabbbc"]
["bBb","b","BBB","bbb"]
# reference to named captures
gsub("(?<x>.)[^a]*"; "+\(.x)-")
"Abcabc"
"+A-+a-"
gsub("(?<x>.)(?<y>[0-9])"; "\(.x|ascii_downcase)\(.y)")
"A1 B2 CD"
"a1 b2 CD"
gsub("\\b(?<x>.)"; "\(.x|ascii_downcase)")
"ABC DEF"
"aBC dEF"
# utf-8
sub("(?<x>.)"; "\(.x)!")
"’"
"’!"
[sub("a"; "b", "c")]
"a"
["b","c"]
[sub("(?<a>.)"; "\(.a|ascii_upcase)", "\(.a|ascii_downcase)", "c")]
"aB"
["AB","aB","cB"]
[gsub("(?<a>.)"; "\(.a|ascii_upcase)", "\(.a|ascii_downcase)", "c")]
"aB"
["AB","ab","cc"]
# splits and _nwise
[splits("")]
"ab"
["","a","b",""]
-32
View File
@@ -143,21 +143,6 @@ if $VALGRIND $Q $JQ -e . $d/input; then
exit 2
fi
# Regression test for #2146
if echo "foobar" | $JQ .; then
printf 'Issue #2146 is back?\n' 1>&2
exit 1
elif [ $? -ne 5 ]; then
echo "Invalid input had wrong error code" 1>&2
exit 1
fi
# Regression test for #2367; make sure to call jq twice
if ! echo '{"a": 1E9999999999}' | $JQ . | $JQ -e .a; then
printf 'Issue #2367 is back?\n' 1>&2
exit 1
fi
# Regression test for #1534
echo "[1,2,3,4]" > $d/expected
printf "[1,2][3,4]" | $JQ -cs add > $d/out 2>&1
@@ -218,23 +203,6 @@ else
echo "Not doing torture tests"
fi
## Regression test for issue #2378 assert when stream parse broken object pair
echo '{"a":1,"b",' | $JQ --stream > /dev/null 2> $d/err || true
grep 'Objects must consist of key:value pairs' $d/err > /dev/null
## Regression test for issue #2572 assert when using --jsonargs and invalid JSON
$JQ -n --jsonargs null invalid && EC=$? || EC=$?
if [ "$EC" -ne 2 ]; then
echo "--jsonargs exited with wrong exit code, expected 2 got $EC" 1>&2
exit 1
fi
# this tests the args_done code path "--"
$JQ -n --jsonargs null -- invalid && EC=$? || EC=$?
if [ "$EC" -ne 2 ]; then
echo "--jsonargs exited with wrong exit code, expected 2 got $EC" 1>&2
exit 1
fi
## Fuzz parser
## XXX With a $(urandom) builtin we could move this test into tests/all.test