Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ed2da6d43 | ||
|
|
444f0aacca | ||
|
|
22006172ba |
No files matched your search
@@ -1,12 +1,2 @@
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
* text=auto eol=lf
|
||||
vendor/** linguist-vendored
|
||||
|
||||
# generated files
|
||||
src/lexer.[ch] linguist-generated=true
|
||||
src/parser.[ch] linguist-generated=true
|
||||
tests/man.test linguist-generated=true
|
||||
tests/manonig.test linguist-generated=true
|
||||
jq.1.prebuilt linguist-generated=true
|
||||
docs/Pipfile.lock linguist-generated=true
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
READ THIS FIRST!
|
||||
|
||||
If you have a usage question, please ask us on [Stack Overflow](https://stackoverflow.com/questions/tagged/jq), in the [#jq channel](https://web.libera.chat/#jq) on [Libera.Chat](https://libera.chat/), or in our [Discord server](https://discord.gg/yg6yjNmgAC).
|
||||
|
||||
-->
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Provide a minimal test case to reproduce the behavior.
|
||||
If the input is large, either attach it as a file, or [create a gist](https://gist.github.com) and link to it here.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Environment (please complete the following information):**
|
||||
|
||||
- OS and Version: [e.g. macOS, Windows, Linux (please specify distro)]
|
||||
- jq version [e.g. 1.5]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -1,13 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "pip"
|
||||
directory: "docs/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
groups:
|
||||
official-actions:
|
||||
patterns: ["actions/*"]
|
||||
@@ -1,418 +0,0 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- "jq-*"
|
||||
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
|
||||
- riscv64
|
||||
- s390x
|
||||
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: riscv64
|
||||
CC: riscv64-linux-gnu
|
||||
- arch: s390x
|
||||
CC: s390x-linux-gnu
|
||||
runs-on: ${{ matrix.arch == 'i386' && 'ubuntu-22.04' || 'ubuntu-24.04' }}
|
||||
env:
|
||||
AR: ${{ matrix.CC }}-ar
|
||||
CHOST: ${{ matrix.CC }}
|
||||
CC: ${{ matrix.CC }}-gcc
|
||||
CPP: ${{ matrix.CC }}-cpp
|
||||
LDFLAGS: -s
|
||||
SUFFIX: linux-${{ matrix.arch }}
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y automake autoconf libtool crossbuild-essential-${{ matrix.arch }}
|
||||
- name: Build
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure \
|
||||
--host=${{ matrix.CC }} \
|
||||
--disable-docs \
|
||||
--with-oniguruma=builtin \
|
||||
--enable-static \
|
||||
--enable-all-static \
|
||||
CFLAGS="-O2 -pthread -fstack-protector-all"
|
||||
make -j"$(nproc)"
|
||||
file ./jq
|
||||
cp ./jq jq-${{ env.SUFFIX }}
|
||||
- name: Test
|
||||
# Only run tests for amd64 matching the CI machine arch
|
||||
if: ${{ matrix.arch == 'amd64' }}
|
||||
run: |
|
||||
make check VERBOSE=yes
|
||||
git diff --exit-code
|
||||
- name: Upload Test Logs
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-${{ env.SUFFIX }}
|
||||
retention-days: 7
|
||||
path: |
|
||||
test-suite.log
|
||||
tests/*.log
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: jq-${{ env.SUFFIX }}
|
||||
path: jq-${{ env.SUFFIX }}
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
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-14
|
||||
env:
|
||||
LDFLAGS: -dead_strip
|
||||
SUFFIX: macos-${{ matrix.arch }}
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install packages
|
||||
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"
|
||||
- name: Build
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure \
|
||||
--host="${{ matrix.target }}$(uname -r)" \
|
||||
--disable-docs \
|
||||
--with-oniguruma=builtin \
|
||||
--disable-shared \
|
||||
--enable-static \
|
||||
--enable-all-static \
|
||||
CFLAGS="-O2 -pthread -fstack-protector-all"
|
||||
make -j"$(sysctl -n hw.logicalcpu)"
|
||||
strip ./jq
|
||||
file ./jq
|
||||
cp ./jq jq-${{ env.SUFFIX }}
|
||||
- name: Test
|
||||
run: |
|
||||
make check VERBOSE=yes
|
||||
git diff --exit-code
|
||||
- name: Upload Test Logs
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-${{ env.SUFFIX }}
|
||||
retention-days: 7
|
||||
path: |
|
||||
test-suite.log
|
||||
tests/*.log
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: jq-${{ env.SUFFIX }}
|
||||
path: jq-${{ env.SUFFIX }}
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch:
|
||||
- amd64
|
||||
- i386
|
||||
include:
|
||||
- arch: amd64
|
||||
msystem: UCRT64
|
||||
- arch: i386
|
||||
msystem: MINGW32
|
||||
runs-on: windows-2022
|
||||
env:
|
||||
LDFLAGS: -s
|
||||
SUFFIX: windows-${{ matrix.arch }}
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Prepare git config
|
||||
run: git config --system core.autocrlf false
|
||||
shell: bash
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
msystem: ${{ matrix.msystem }}
|
||||
install: >-
|
||||
base-devel
|
||||
git
|
||||
autoconf
|
||||
automake
|
||||
libtool
|
||||
pacboy: >-
|
||||
toolchain:p
|
||||
- name: Build
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure \
|
||||
--disable-docs \
|
||||
--with-oniguruma=builtin \
|
||||
--disable-shared \
|
||||
--enable-static \
|
||||
--enable-all-static \
|
||||
CFLAGS="-O2 -pthread -fstack-protector-all"
|
||||
make -j$(nproc)
|
||||
file ./jq.exe
|
||||
cp ./jq.exe jq-${{ env.SUFFIX }}.exe
|
||||
- name: Test
|
||||
run: |
|
||||
make check VERBOSE=yes
|
||||
git diff --exit-code
|
||||
- name: Upload Test Logs
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-${{ env.SUFFIX }}
|
||||
retention-days: 7
|
||||
path: |
|
||||
test-suite.log
|
||||
tests/*.log
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: jq-${{ env.SUFFIX }}
|
||||
path: jq-${{ env.SUFFIX }}.exe
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
dist:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
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 \
|
||||
--with-oniguruma=builtin
|
||||
make distcheck
|
||||
make dist dist-zip
|
||||
git diff --exit-code
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: jq-dist
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
path: |
|
||||
jq-*.tar.gz
|
||||
jq-*.zip
|
||||
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
attestations: write
|
||||
packages: write
|
||||
needs: linux
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Download executables
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: jq-linux-*
|
||||
merge-multiple: true
|
||||
- name: Move executables
|
||||
run: |
|
||||
mkdir -p linux/{386,amd64,arm64,mips64le,ppc64le,riscv64,s390x}
|
||||
mv jq-linux-i386 linux/386/jq
|
||||
mv jq-linux-amd64 linux/amd64/jq
|
||||
mv jq-linux-arm64 linux/arm64/jq
|
||||
mv jq-linux-mips64el linux/mips64le/jq
|
||||
mv jq-linux-ppc64el linux/ppc64le/jq
|
||||
mv jq-linux-riscv64 linux/riscv64/jq
|
||||
mv jq-linux-s390x linux/s390x/jq
|
||||
chmod +x linux/*/jq
|
||||
- name: Create Dockerfile
|
||||
run: |
|
||||
cat <<'EOF' >Dockerfile
|
||||
FROM scratch
|
||||
ARG TARGETPLATFORM
|
||||
COPY AUTHORS COPYING $TARGETPLATFORM/jq /
|
||||
RUN ["/jq", "--version"]
|
||||
ENTRYPOINT ["/jq"]
|
||||
EOF
|
||||
- name: Docker metadata
|
||||
uses: docker/metadata-action@v5
|
||||
id: metadata
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}
|
||||
tags: >
|
||||
${{ startsWith(github.ref, 'refs/tags/jq-')
|
||||
&& format('type=match,pattern=jq-(.*),group=1,value={0}', github.ref_name)
|
||||
|| 'type=sha,format=long' }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Build and release Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
id: build-push
|
||||
with:
|
||||
context: .
|
||||
push: ${{ startsWith(github.ref, 'refs/tags/jq-') }}
|
||||
provenance: false
|
||||
platforms: linux/386,linux/amd64,linux/arm64,linux/mips64le,linux/ppc64le,linux/riscv64,linux/s390x
|
||||
tags: ${{ steps.metadata.outputs.tags }}
|
||||
labels: ${{ steps.metadata.outputs.labels }}
|
||||
- name: Generate signed attestations
|
||||
if: startsWith(github.ref, 'refs/tags/jq-')
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ghcr.io/${{ github.repository }}
|
||||
subject-digest: ${{ steps.build-push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
pull-requests: write
|
||||
environment: release
|
||||
needs: [linux, macos, windows, dist, docker]
|
||||
if: startsWith(github.ref, 'refs/tags/jq-')
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: jq-*
|
||||
merge-multiple: true
|
||||
- name: Upload release
|
||||
env:
|
||||
TAG_NAME: ${{ github.ref_name }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
cp jq-linux-amd64 jq-linux64
|
||||
cp jq-macos-amd64 jq-osx-amd64
|
||||
cp jq-windows-amd64.exe jq-win64.exe
|
||||
sha256sum jq-* > sha256sum.txt
|
||||
gh release create "$TAG_NAME" --draft --title "jq ${TAG_NAME#jq-}" --generate-notes
|
||||
gh release upload "$TAG_NAME" --clobber jq-* sha256sum.txt
|
||||
- name: Generate signed attestations
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-path: jq-*
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.JQ_RELEASE_GPG_PRIVATE_KEY }}
|
||||
passphrase: ${{ secrets.JQ_RELEASE_GPG_PASSPHRASE }}
|
||||
- name: Update signatures
|
||||
env:
|
||||
TAG_NAME: ${{ github.ref_name }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
sig_dir="sig/v${TAG_NAME#jq-}"
|
||||
mkdir -p "$sig_dir"
|
||||
mv sha256sum.txt "$sig_dir"
|
||||
for file in jq-*; do
|
||||
gpg --detach-sign --armor --batch --output "${sig_dir}/${file#*/}.asc" "$file"
|
||||
done
|
||||
git add sig
|
||||
git config user.name 'github-actions[bot]'
|
||||
git config user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
title="Update signatures of ${TAG_NAME#jq-}"
|
||||
git commit -m "$title"
|
||||
branch="update-signatures-${TAG_NAME#jq-}"
|
||||
git push origin "HEAD:refs/heads/$branch"
|
||||
gh pr create --title "$title" --body "" --head "$branch"
|
||||
@@ -1,33 +0,0 @@
|
||||
name: decnum
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
disabled:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y automake autoconf libtool
|
||||
- name: Build
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure \
|
||||
--disable-docs \
|
||||
--disable-maintainer-mode \
|
||||
--disable-decnum
|
||||
make -j"$(nproc)"
|
||||
make check
|
||||
file ./jq
|
||||
- name: Test
|
||||
run: |
|
||||
diff <(echo 100000000000000000000 | ./jq) <(echo 1e+20)
|
||||
git diff --exit-code
|
||||
@@ -1,51 +0,0 @@
|
||||
name: Building man page, man.test, manonig.test
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/workflows/manpage.yml'
|
||||
- 'docs/**'
|
||||
- 'tests/man.test'
|
||||
- 'tests/manonig.test'
|
||||
- 'jq.1.prebuilt'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/manpage.yml'
|
||||
- 'docs/**'
|
||||
- 'tests/man.test'
|
||||
- 'tests/manonig.test'
|
||||
- 'jq.1.prebuilt'
|
||||
|
||||
jobs:
|
||||
manpages:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
cache: pipenv
|
||||
- name: Install pipenv
|
||||
run: pip install pipenv
|
||||
- name: Install dependencies
|
||||
run: pipenv sync
|
||||
working-directory: docs
|
||||
- name: Validate manual schema
|
||||
run: pipenv run python3 validate_manual_schema.py content/manual/**/*.yml
|
||||
working-directory: docs
|
||||
- name: Configure
|
||||
run: |
|
||||
autoreconf -i
|
||||
./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
|
||||
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)
|
||||
@@ -1,75 +0,0 @@
|
||||
name: oniguruma
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
# Since builtin oniguruma is tested in the CI workflow,
|
||||
# we test other options for --with-oniguruma here.
|
||||
jobs:
|
||||
installed:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y automake autoconf libtool valgrind libonig-dev
|
||||
- name: Build
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure \
|
||||
--disable-docs \
|
||||
--enable-valgrind \
|
||||
--with-oniguruma=yes
|
||||
make -j"$(nproc)"
|
||||
file ./jq
|
||||
- name: Test
|
||||
run: |
|
||||
./jq -n '"" | test("")'
|
||||
make check VERBOSE=yes
|
||||
git diff --exit-code
|
||||
- name: Upload Test Logs
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-oniguruma-installed
|
||||
retention-days: 7
|
||||
path: |
|
||||
test-suite.log
|
||||
tests/*.log
|
||||
|
||||
disabled:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y automake autoconf libtool valgrind
|
||||
- name: Build
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure \
|
||||
--disable-docs \
|
||||
--enable-valgrind \
|
||||
--with-oniguruma=no
|
||||
make -j"$(nproc)"
|
||||
file ./jq
|
||||
- name: Test
|
||||
run: |
|
||||
! ./jq -n '"" | test("")'
|
||||
make check VERBOSE=yes
|
||||
git diff --exit-code
|
||||
- name: Upload Test Logs
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-oniguruma-disabled
|
||||
retention-days: 7
|
||||
path: |
|
||||
test-suite.log
|
||||
tests/*.log
|
||||
@@ -1,47 +0,0 @@
|
||||
name: Clang scan-build Static Analyzer Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
scan-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y automake autoconf gdb valgrind clang clang-tools
|
||||
echo "CC=clang" >> "$GITHUB_ENV"
|
||||
- name: Build
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure --enable-valgrind CFLAGS="-g -O0"
|
||||
scan-build --keep-going --exclude vendor/ make -j"$(nproc)"
|
||||
- name: Test
|
||||
run: |
|
||||
ulimit -c unlimited
|
||||
scan-build --keep-going --exclude vendor/ make -j"$(nproc)" check
|
||||
- name: Core dump stacks
|
||||
run: |
|
||||
if [[ -f core ]]; then
|
||||
gdb -batch -ex "thread apply all bt" \
|
||||
"$(file core | sed "s/^[^']*'//; s/[ '].*$//")" core
|
||||
exit 1
|
||||
fi
|
||||
- name: Test logs
|
||||
if: ${{ failure() }}
|
||||
run: |
|
||||
cat test-suite.log tests/*.log
|
||||
- name: Upload Logs
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Scan-Build Reports
|
||||
path: /tmp/scan-build*
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
@@ -1,41 +0,0 @@
|
||||
name: valgrind
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y automake autoconf libtool valgrind
|
||||
- name: Build
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure \
|
||||
--disable-docs \
|
||||
--enable-valgrind \
|
||||
--with-oniguruma=builtin
|
||||
make -j"$(nproc)"
|
||||
file ./jq
|
||||
- name: Test
|
||||
run: |
|
||||
make check VERBOSE=yes
|
||||
git diff --exit-code
|
||||
- name: Upload Test Logs
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-logs-valgrind-linux
|
||||
retention-days: 7
|
||||
path: |
|
||||
test-suite.log
|
||||
tests/*.log
|
||||
@@ -1,47 +0,0 @@
|
||||
name: Update website
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'docs/**'
|
||||
concurrency: website
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: docs
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
cache: pipenv
|
||||
- name: Install pipenv
|
||||
run: pip install pipenv
|
||||
- name: Install dependencies
|
||||
run: pipenv sync
|
||||
- name: Build website
|
||||
run: pipenv run python3 build_website.py
|
||||
- name: Upload pages artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: docs/output/
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: actions/deploy-pages@v4
|
||||
id: deployment
|
||||
+9
-41
@@ -1,60 +1,28 @@
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
*.la
|
||||
*.lai
|
||||
*.so
|
||||
*.so.*
|
||||
*.gcda
|
||||
*.gcno
|
||||
*.gcov
|
||||
*~
|
||||
.*.sw[a-p]
|
||||
tags
|
||||
|
||||
jq
|
||||
!tests/modules/lib/jq/
|
||||
jq.1
|
||||
|
||||
# Generated source
|
||||
src/builtin.inc
|
||||
src/config_opts.inc
|
||||
*.pc
|
||||
# Something delightfully recursive happens otherwise
|
||||
docs/content/2.download/source/*
|
||||
|
||||
# Autogenerated
|
||||
lexer.c
|
||||
lexer.h
|
||||
parser.c
|
||||
parser.h
|
||||
|
||||
# Autotools junk
|
||||
.libs
|
||||
.deps
|
||||
.dirstamp
|
||||
libtool
|
||||
*.log
|
||||
stamp-h1
|
||||
config.log
|
||||
config.status
|
||||
autom4te.cache
|
||||
confdefs.h
|
||||
conftest*
|
||||
INSTALL
|
||||
config.h
|
||||
Makefile
|
||||
jq-*.tar.gz
|
||||
jq-*.zip
|
||||
configure
|
||||
aclocal.m4
|
||||
Makefile.in
|
||||
version.h
|
||||
.remake-version-h
|
||||
config.cache
|
||||
*.rpm
|
||||
m4/libtool.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
m4/lt~obsolete.m4
|
||||
tests/*.trs
|
||||
|
||||
# Docs output
|
||||
docs/output
|
||||
|
||||
cscope.in.out
|
||||
cscope.out
|
||||
cscope.po.out
|
||||
jq.dSYM
|
||||
@@ -1,3 +0,0 @@
|
||||
[submodule "vendor/oniguruma"]
|
||||
path = vendor/oniguruma
|
||||
url = https://github.com/kkos/oniguruma.git
|
||||
@@ -1,231 +1,6 @@
|
||||
Created By:
|
||||
Stephen Dolan <mu@netsoc.tcd.ie>
|
||||
|
||||
Maintained by:
|
||||
David Tolnay <dtolnay@gmail.com>
|
||||
Emanuele Torre <torreemanuele6@gmail.com>
|
||||
Leonid S. Usov <leonid@practi.net>
|
||||
Mattias Wadman <mattias.wadman@gmail.com>
|
||||
Muh Muhten <muh.muhten@gmail.com>
|
||||
Nicolas Williams <nico@cryptonector.com>
|
||||
Owen Ou <o@owenou.com>
|
||||
William Langford <wlangfor@gmail.com>
|
||||
itchyny <itchyny@cybozu.co.jp>
|
||||
pkoppstein <pkoppstein@gmail.com>
|
||||
|
||||
Contributions by:
|
||||
13ren <melbourne.research@gmail.com>
|
||||
AJ Jordan <alex@strugee.net>
|
||||
Aaron Peschel <apeschel@zendesk.com>
|
||||
Adam Lindberg <hello@alind.io>
|
||||
Alanscut <wp_scut@163.com>
|
||||
Aleksey Tsalolikhin <atsalolikhin@spokeo.com>
|
||||
Alex Chamberlain <alex@alexchamberlain.co.uk>
|
||||
Alex Jurkiewicz <alex@jurkiewi.cz>
|
||||
Alex Ozdemir <aozdemir@hmc.edu>
|
||||
Alex Wilson <gpg@probablyfine.co.uk>
|
||||
Alexandre Jasmin <ajasmin@transtex-llc.com>
|
||||
Allan Clark <allanc@chickenandporn.com>
|
||||
Andreas Heiduk <asheiduk@users.noreply.github.com>
|
||||
Andrew O'Brien <obrien.andrew@gmail.com>
|
||||
Andrew Rodland <andrew@cleverdomain.org>
|
||||
Andrew Speed <andrew.cspeed@gmail.com>
|
||||
Andy Lester <andy@petdance.com>
|
||||
Ankur <ankz.kothari@gmail.com>
|
||||
Anthony Shortland <anthony@dtosolutions.com>
|
||||
Anthony Sottile <asottile@umich.edu>
|
||||
Assaf Gordon <assafgordon@gmail.com>
|
||||
Attila Fülöp <attila@fueloep.org>
|
||||
Benjamin Wuethrich <benjamin@koho.ca>
|
||||
Benoit de Chezelles <bew@users.noreply.github.com>
|
||||
Bernard Niset <bernard.niset@gmail.com>
|
||||
Bhargava Mummadireddy <kishoreinvits@gmail.com>
|
||||
Bradley Skaggs <bskaggs@acm.org>
|
||||
Brahm Lower <bplower@gmail.com>
|
||||
Brendan Macmillan <melbourne.research@gmail.com>
|
||||
Cameron Sparr <cameronsparr@gmail.com>
|
||||
Chance Zibolski <czibolsk@redhat.com>
|
||||
Charles Merriam <charles.merriam@gmail.com>
|
||||
Chris LaRose <cjlarose@gmail.com>
|
||||
Chris Moore <dooglus@gmail.com>
|
||||
Christoph Anton Mitterer <calestyo@scientia.org>
|
||||
Christopher Degawa <ccom@randomderp.com>
|
||||
Ciaran McNamara <1372986+ciaranmcnamara@users.noreply.github.com>
|
||||
Clément MATHIEU <clement@unportant.info>
|
||||
Colin Leroy-Mira <colin@colino.net>
|
||||
Colin von Heuring <colin@janrain.com>
|
||||
Dag-Erling Smørgrav <des@des.no>
|
||||
Damian Gryski <damian@gryski.com>
|
||||
Dan Church <h3xx@users.noreply.github.com>
|
||||
Daniel Lange <DLange@git.local>
|
||||
David Biesack <David.Biesack@apiture.com>
|
||||
David Fetter <david@fetter.org>
|
||||
David Haguenauer <ml@kurokatta.org>
|
||||
David Korczynski <david@adalogics.com>
|
||||
David R. MacIver <david@drmaciver.com>
|
||||
DavidKorczynski <david@adalogics.com>
|
||||
Dawid Ferenczy Rogožan <ferenczy@users.noreply.github.com>
|
||||
Derrick Pallas <derrick@pallas.us>
|
||||
Doug Luce <doug@github.con.com>
|
||||
Eiichi Sato <sato.eiichi@gmail.com>
|
||||
Eli Schwartz <eschwartz@archlinux.org>
|
||||
Eloy Coto <eloy.coto@gmail.com>
|
||||
Eric Bréchemier <eric@egull.co>
|
||||
Erik Brinkman <erik.brinkman@gmail.com>
|
||||
Eugen <EugenGez@gmail.com>
|
||||
Evan Zacks <zackse@gmail.com>
|
||||
Fabian Dellwing <fabian.dellwing@mbconnectline.de>
|
||||
Felix Wolfsteller <felix.wolfsteller@gmail.com>
|
||||
Filippo Giunchedi <fgiunchedi@gmail.com>
|
||||
Filippo Valsorda <filippo.valsorda@gmail.com>
|
||||
Florian Weimer <fweimer@redhat.com>
|
||||
Frederic Cambus <fcambus@users.sourceforge.net>
|
||||
Gabriel Marin <gbrlmarn@gmail.com>
|
||||
Gaelan Steele <gbs@canishe.com>
|
||||
George Hopkins <george-hopkins@null.net>
|
||||
Gert Van Gool <gertvangool@gmail.com>
|
||||
Gijs Kunze <gwkunze@gmail.com>
|
||||
Gustav <gustav@invoke.se>
|
||||
HE, Tao <sighingnow@gmail.com>
|
||||
Han Jiang <jhcarl0814@gmail.com>
|
||||
Hanfei Shen <qqshfox@gmail.com>
|
||||
Hanson Char <hanson.char@gmail.com>
|
||||
Haochen Xie <haochenx@acm.org>
|
||||
Helmut K. C. Tessarek <tessarek@evermeet.cx>
|
||||
Henré Botha <henrebotha@gmail.com>
|
||||
Ian Miell <ian.miell@gmail.com>
|
||||
Ikko Ashimine <eltociear@gmail.com>
|
||||
J Phani Mahesh <github@phanimahesh.me>
|
||||
J. B. Rainsberger <me@jbrains.ca>
|
||||
Jack Pearkes <jackpearkes@gmail.com>
|
||||
Jakub Jirutka <jakub@jirutka.cz>
|
||||
Jakub Wilk <jwilk@jwilk.net>
|
||||
James Andariese <james.andariese@locationlabs.com>
|
||||
James Pearson Hughes <xiong.chiamiov@gmail.com>
|
||||
Jan Schulz <jasc@gmx.net>
|
||||
Janne Cederberg <janne.cederberg@gmail.com>
|
||||
Jason Hood <jadoxa@yahoo.com.au>
|
||||
Jay Satiro <raysatiro@yahoo.com>
|
||||
Jesper Rønn-Jensen <jesperrr@gmail.com>
|
||||
Jingwen Owen Ou <jingweno@gmail.com>
|
||||
Joe Littlejohn <joe.littlejohn@nokia.com>
|
||||
Joel Nothman <joel.nothman@gmail.com>
|
||||
Joel Purra <code+github@joelpurra.com>
|
||||
Jonathan Chan Kwan Yin <sofe2038@gmail.com>
|
||||
Jonathan Word <argoday@argoday.com>
|
||||
Josh Soref <2119212+jsoref@users.noreply.github.com>
|
||||
Juan Guerrero <juan.guerrero.lozano@gmail.com>
|
||||
Kamontat Chantrachirathumrong <14089557+kamontat@users.noreply.github.com>
|
||||
Kenny Shen <kenny.shen@zalora.com>
|
||||
Kim De Mey <kim.demey@gmail.com>
|
||||
Kim Toms <kim.toms@bplglobal.net>
|
||||
Kirk McKelvey <kirkoman@gmail.com>
|
||||
Klemens Nanni <kn@openbsd.org>
|
||||
LCD 47 <lcd047@gmail.com>
|
||||
Larry Aasen <larryaasen@gmail.com>
|
||||
Lee Thompson <stagr.lee@gmail.com>
|
||||
Loamhoof <soeren.medard@gmail.com>
|
||||
Lucas Trzesniewski <lucas.trzesniewski@gmail.com>
|
||||
Lukas Lansky <lukas.lansky@suse.com>
|
||||
MCApollo <34170230+MCApollo@users.noreply.github.com>
|
||||
Marc Abramowitz <marc@marc-abramowitz.com>
|
||||
Marc Bruggmann <marcbr@spotify.com>
|
||||
Marcin Kłopotek <marcin.klopotek@gmail.com>
|
||||
Marcin Serwin <marcin@serwin.dev>
|
||||
Mark Feit <mfeit@internet2.edu>
|
||||
Mark McKinstry <mmckinst@umich.edu>
|
||||
Markus Lanthaler <mark_lanthaler@gmx.net>
|
||||
Matt Clegg <m@cle.gg>
|
||||
Matt Meyers <matt@mattmeyers.dev>
|
||||
Matti Åstrand <mattiastr@gmail.com>
|
||||
Mattias Hansson <hansson.mattias@gmail.com>
|
||||
Maxime Biais <maxime.biais@gmail.com>
|
||||
Maximilian Roos <5635139+max-sixty@users.noreply.github.com>
|
||||
Michael Daines <michael@mdaines.com>
|
||||
Michael Färber <01mf02@gmail.com>
|
||||
Mike Daines <mdaines@users.noreply.github.com>
|
||||
Mike Fletcher <john.m.fletcher@bankofamerica.com>
|
||||
Mike McCabe <mccabe@archive.org>
|
||||
Nathan Baulch <nathan.baulch@gmail.com>
|
||||
Naïm Favier <n@monade.li>
|
||||
Nicolas Pouillard <nicolas.pouillard@gmail.com>
|
||||
Nicole Wren <nicole@wren.systems>
|
||||
Paul Chvostek <paul+gitkraken@it.ca>
|
||||
Paul Wise <pabs3@bonedaddy.net>
|
||||
Peter van Dijk <peter@7bits.nl>
|
||||
Philipp Hagemeister <phihag@phihag.de>
|
||||
Ricardo Constantino <wiiaboo@gmail.com>
|
||||
Richard Groves <richard@noodlfroot.com>
|
||||
Richard H Lee <richard@webdezign.co.uk>
|
||||
Riley Avron <riley.avron@gmail.com>
|
||||
Rob Wills <rob.wills@gmail.com>
|
||||
Robert Aboukhalil <robert.aboukhalil@gmail.com>
|
||||
Roland C. Dowdeswell <roland.dowdeswell@twosigma.com>
|
||||
Roman Inflianskas <rominf@users.noreply.github.com>
|
||||
Romero Malaquias <romero.malaquias@gmail.com>
|
||||
Ryoichi KATO <ryo1kato@gmail.com>
|
||||
Rémy Léone <remy.leone@gmail.com>
|
||||
SArpnt <sarpnt@ficial.net>
|
||||
Samar Sunkaria <sameesunkaria@me.com>
|
||||
Santiago Lapresta <santiago.lapresta@gmail.com>
|
||||
Sean Wei <me@sean.taipei>
|
||||
Sebastian Freundt <freundt@ga-group.nl>
|
||||
Shaun Guth <sguth@practicefusion.com>
|
||||
Shay Elkin <shay@everything.me>
|
||||
Simon Elsbrock <simon@iodev.org>
|
||||
Stefan <stefan.haubenthal@gmail.com>
|
||||
Stefan Seemayer <stefan@seemayer.de>
|
||||
Stephen Roantree <stroantree@gmail.com>
|
||||
Stephen Shaw <stesh@netsoc.tcd.ie>
|
||||
Steven Ihde <sihde@hamachi.us>
|
||||
Steven Maude <StevenMaude@users.noreply.github.com>
|
||||
Steven Penny <svnpenn@gmail.com>
|
||||
Thalia Archibald <thalia@archibald.dev>
|
||||
Thomas Bozeman th026106 <thomas.bozeman@digitalglobe.com>
|
||||
Thomas R. Hall <trhall@trhall.org>
|
||||
Thomas Sibley <tom@zulutango.org>
|
||||
Tim McCormack <cortex@brainonfire.net>
|
||||
Timothy John Perisho Eccleston <combinatorist@users.noreply.github.com>
|
||||
Tom Wolf <github@incognitox.org>
|
||||
Tomas Halman <thalman@redhat.com>
|
||||
Travis Gockel <travis@gockelhut.com>
|
||||
Tyler Rockwood <rockwotj@users.noreply.github.com>
|
||||
Ulrich Eckhardt <ulrich.eckhardt@base-42.de>
|
||||
W-Mark Kubacki <wmark@hurrikane.de>
|
||||
William Chargin <wchargin@gmail.com>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Yeikel <email@yeikel.com>
|
||||
Yoichi Nakayama <yoichi.nakayama@gmail.com>
|
||||
Zhaohui Mei <mzh.whut@gmail.com>
|
||||
Zhiming Wang <zmwangx@gmail.com>
|
||||
calpeconsulting <61429736+calpeconsulting@users.noreply.github.com>
|
||||
cdnbacon <mike@busbud.com>
|
||||
dak180 <dak180@users.sf.net>
|
||||
davkor <david@adalogics.com>
|
||||
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
|
||||
eitsupi <50911393+eitsupi@users.noreply.github.com>
|
||||
fletcher gornick <fletcher@gornick.dev>
|
||||
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
||||
goodactive <167312449+goodactive@users.noreply.github.com>
|
||||
i <isomorphisms@sdf.org>
|
||||
jkleint <jkleint@gmail.com>
|
||||
lectrical <14344693+lectrical@users.noreply.github.com>
|
||||
liviubobocu <liviu.bobocu@uipath.com>
|
||||
maflcko <6399679+maflcko@users.noreply.github.com>
|
||||
mail6543210 <mail6543210@yahoo.com.tw>
|
||||
mjarosie <mjarosie@users.noreply.github.com>
|
||||
myaaaaaaaaa <103326468+myaaaaaaaaa@users.noreply.github.com>
|
||||
nmulcahey <nmulcahey@gmail.com>
|
||||
orbea <orbea@riseup.net>
|
||||
polyester <paul@cleanclothes.org>
|
||||
rain1 <rain1@airmail.cc>
|
||||
riastradh <campbell+github@mumble.net>
|
||||
sachint <32639496+sachintu47@users.noreply.github.com>
|
||||
sheepster <omer531998@gmail.com>
|
||||
tal@whatexit.org <tal@whatexit.org>
|
||||
taoky <taoky99@outlook.com>
|
||||
trantor <trantorvega@gmail.com>
|
||||
wellweek <148746285+wellweek@users.noreply.github.com>
|
||||
wllm-rbnt <william.robinet@conostix.com>
|
||||
zstadler <zeev.stadler@gmail.com>
|
||||
наб <nabijaczleweli@nabijaczleweli.xyz>
|
||||
Contributions by
|
||||
Anthony Shortland <anthony.shortland@me.com> - rpmbuild target
|
||||
Lee Thompson <stagr.lee@gmail.com> - autoconf stuff
|
||||
@@ -25,14 +25,14 @@ jq's documentation (everything found under the docs/ subdirectory in
|
||||
the source tree) is licensed under the Creative Commons CC BY 3.0
|
||||
license, which can be found at:
|
||||
|
||||
https://creativecommons.org/licenses/by/3.0/
|
||||
http://creativecommons.org/licenses/by/3.0/
|
||||
|
||||
The documentation website includes a copy of Twitter's Bootstrap and
|
||||
The documentation website includes a copy of Twitter's Boostrap and
|
||||
relies on Bonsai, Liquid templates and various other projects, look
|
||||
them up for detailed licensing conditions.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
jq incorporates David M. Gay's dtoa.c and g_fmt.c, which bear the
|
||||
following notices:
|
||||
|
||||
@@ -68,77 +68,3 @@ WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
|
||||
REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
|
||||
jq uses parts of the open source C library "decNumber", which is distributed
|
||||
under the following license:
|
||||
|
||||
|
||||
ICU License - ICU 1.8.1 and later
|
||||
|
||||
COPYRIGHT AND PERMISSION NOTICE
|
||||
|
||||
Copyright (c) 1995-2005 International Business Machines Corporation and others
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, and/or sell copies of the Software, and to permit persons
|
||||
to whom the Software is furnished to do so, provided that the above
|
||||
copyright notice(s) and this permission notice appear in all copies of
|
||||
the Software and that both the above copyright notice(s) and this
|
||||
permission notice appear in supporting documentation.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
|
||||
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of a copyright holder
|
||||
shall not be used in advertising or otherwise to promote the sale, use
|
||||
or other dealings in this Software without prior written authorization
|
||||
of the copyright holder.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
|
||||
|
||||
|
||||
|
||||
jv_thread.h is copied from Heimdal's lib/base/heimbase.h and some code
|
||||
in jv.c is copied from Heimdal's lib/base/dll.c:
|
||||
|
||||
|
||||
Portions Copyright (c) 2016 Kungliga Tekniska Högskolan
|
||||
(Royal Institute of Technology, Stockholm, Sweden).
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
FROM debian:12-slim AS builder
|
||||
|
||||
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 \
|
||||
--with-oniguruma=builtin \
|
||||
--enable-static \
|
||||
--enable-all-static \
|
||||
--prefix=/usr/local \
|
||||
&& make -j$(nproc) \
|
||||
&& make check VERBOSE=yes \
|
||||
&& make install-strip
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=builder /app/AUTHORS /app/COPYING /usr/local/bin/jq /
|
||||
RUN ["/jq", "--version"]
|
||||
ENTRYPOINT ["/jq"]
|
||||
@@ -1,8 +0,0 @@
|
||||
pub 4096R/71523402 2015-10-11
|
||||
Key fingerprint = 4FD7 01D6 FA9B 3D2D F5AC 935D AF19 040C 7152 3402
|
||||
uid jq Release Signing Key <jq@stedolan.github.io>
|
||||
|
||||
pub 2048R/D15684DB 2015-10-12 [expires: 2017-10-11]
|
||||
Key fingerprint = 7F6C 7BD3 0412 AFD5 8C1A 5007 EB26 A4F8 D156 84DB
|
||||
uid Nicolas Williams <nico@cryptonector.com>
|
||||
sub 2048R/9C9CCD6A 2015-10-12 [expires: 2017-10-11]
|
||||
+74
-203
@@ -1,252 +1,123 @@
|
||||
|
||||
### C source files to be built and distributed.
|
||||
|
||||
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 \
|
||||
vendor/decNumber/decContext.h vendor/decNumber/decNumber.h \
|
||||
vendor/decNumber/decNumberLocal.h
|
||||
JQ_INCS = jq_parser.h builtin.h bytecode.h compile.h execute.h \
|
||||
forkable_stack.h frame_layout.h jv.h jv_alloc.h jv_aux.h jv_dtoa.h \
|
||||
jv_parse.h jv_unicode.h locfile.h opcode.h opcode_list.h parser.y \
|
||||
jv_utf8_tables.h lexer.l
|
||||
|
||||
JQ_SRC = opcode.c bytecode.c compile.c execute.c builtin.c jv.c \
|
||||
jv_parse.c jv_print.c jv_dtoa.c jv_unicode.c jv_aux.c jv_alloc.c \
|
||||
jq_test.c ${JQ_INCS}
|
||||
|
||||
LIBJQ_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 \
|
||||
vendor/decNumber/decContext.c vendor/decNumber/decNumber.c \
|
||||
${LIBJQ_INCS}
|
||||
|
||||
### C build options
|
||||
|
||||
AM_CFLAGS = -Wextra -Wall -Wno-unused-parameter -Wno-unused-function \
|
||||
-Woverlength-strings -Wstrict-prototypes
|
||||
AM_CFLAGS = -Wextra -Wall -Wno-missing-field-initializers \
|
||||
-Wno-unused-parameter -Wno-unused-function
|
||||
|
||||
if WIN32
|
||||
AM_CFLAGS += -municode
|
||||
endif
|
||||
|
||||
ACLOCAL_AMFLAGS = -I config/m4
|
||||
|
||||
### Generating the lexer and parser
|
||||
|
||||
# While there is some autoconf macro support for lex/flex, it doesn't support
|
||||
# header file creation so we'll use good old make
|
||||
if MAINTAINER_MODE
|
||||
BUILT_SOURCES = src/lexer.h src/lexer.c src/parser.h src/parser.c \
|
||||
src/builtin.inc src/config_opts.inc src/version.h
|
||||
src/lexer.c: src/lexer.l
|
||||
$(AM_V_LEX) flex -o src/lexer.c --header-file=src/lexer.h $<
|
||||
src/lexer.h: src/lexer.c
|
||||
else
|
||||
BUILT_SOURCES = src/builtin.inc src/config_opts.inc src/version.h
|
||||
.y.c:
|
||||
$(AM_V_YACC) echo "NOT building parser.c!"
|
||||
.l.c:
|
||||
$(AM_V_LEX) echo "NOT building lexer.c!"
|
||||
endif
|
||||
BUILT_SOURCES = lexer.h lexer.c parser.h parser.c
|
||||
lexer.c: lexer.l
|
||||
flex -o lexer.c --header-file=lexer.h $<
|
||||
lexer.h: lexer.c
|
||||
|
||||
# Tell YACC (Bison) autoconf macros that you want a header file created.
|
||||
# If the --warnings=all fails, you probably have an old version of Bison
|
||||
# macOS ships an old Bison, so update with Homebrew or MacPorts.
|
||||
AM_YFLAGS = --warnings=all -Wno-yacc -d
|
||||
# Tell YACC (bison) autoconf macros that you want a header file created.
|
||||
# If the --warnings=all fails, you probably have an old version of bison
|
||||
# OSX ships an old bison, so update with homebrew or macports
|
||||
AM_YFLAGS = --warnings=all -d
|
||||
|
||||
### libjq
|
||||
|
||||
lib_LTLIBRARIES = libjq.la
|
||||
libjq_la_SOURCES = ${LIBJQ_SRC}
|
||||
libjq_la_LIBADD = -lm
|
||||
libjq_la_LDFLAGS = $(onig_LDFLAGS) -export-symbols-regex '^j[qv]_' -version-info 1:4:0
|
||||
|
||||
if WIN32
|
||||
libjq_la_LIBADD += -lshlwapi
|
||||
libjq_la_LDFLAGS += -no-undefined
|
||||
endif
|
||||
|
||||
include_HEADERS = src/jv.h src/jq.h
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir)/src -I$(srcdir)/vendor
|
||||
|
||||
### Address sanitizer (ASan)
|
||||
|
||||
if ENABLE_ASAN
|
||||
AM_CFLAGS += -fsanitize=address
|
||||
endif
|
||||
|
||||
### Undefined Behavior Sanitizer
|
||||
|
||||
if ENABLE_UBSAN
|
||||
AM_CFLAGS += -fsanitize=undefined
|
||||
endif
|
||||
|
||||
### Code coverage with gcov
|
||||
|
||||
if ENABLE_GCOV
|
||||
AM_CFLAGS += --coverage --no-inline
|
||||
endif
|
||||
|
||||
### Error injection for testing
|
||||
|
||||
if ENABLE_ERROR_INJECTION
|
||||
lib_LTLIBRARIES += libinject_errors.la
|
||||
libinject_errors_la_SOURCES = src/inject_errors.c
|
||||
libinject_errors_la_LIBADD = -ldl
|
||||
libinject_errors_la_LDFLAGS = -module
|
||||
endif
|
||||
|
||||
### Building the jq binary
|
||||
|
||||
# Remake the version.h header file if, and only if, the git ID has changed
|
||||
.PHONY: .FORCE
|
||||
.FORCE:
|
||||
generate_ver = ver="`{ $(srcdir)/scripts/version || echo '$(VERSION)' ; } | sed 's/.*/\x23define JQ_VERSION \"&\"/'`"
|
||||
.remake-version-h: .FORCE
|
||||
@ $(generate_ver); test "x`cat src/version.h 2>/dev/null`" = "x$$ver" || touch .remake-version-h
|
||||
src/version.h: .remake-version-h
|
||||
mkdir -p src
|
||||
$(AM_V_GEN) $(generate_ver); echo "$$ver" > $@
|
||||
src/config_opts.inc:
|
||||
mkdir -p src
|
||||
$(AM_V_GEN) if test -x ./config.status; then \
|
||||
./config.status --config; \
|
||||
else echo "(unknown)"; \
|
||||
fi | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' -e 's/^/#define JQ_CONFIG /' > $@
|
||||
src/main.c: src/version.h src/config_opts.inc
|
||||
|
||||
src/builtin.inc: $(srcdir)/src/builtin.jq
|
||||
mkdir -p src
|
||||
$(AM_V_GEN) od -v -A n -t o1 -- $< | \
|
||||
sed -e 's/$$/ /' \
|
||||
-e 's/\([0123456789]\) /\1, /g' \
|
||||
-e 's/ $$//' \
|
||||
-e 's/ 0/ 0/g' \
|
||||
-e 's/ \([123456789]\)/ 0\1/g' > $@
|
||||
src/builtin.o: src/builtin.inc
|
||||
|
||||
CLEANFILES = src/version.h .remake-version-h src/builtin.inc src/config_opts.inc
|
||||
main.c: config.h
|
||||
|
||||
bin_PROGRAMS = jq
|
||||
jq_SOURCES = src/main.c
|
||||
jq_LDADD = libjq.la -lm
|
||||
jq_SOURCES = ${JQ_SRC} main.c
|
||||
|
||||
if ENABLE_ALL_STATIC
|
||||
jq_LDFLAGS = -all-static
|
||||
endif
|
||||
|
||||
### Tests (make check)
|
||||
|
||||
TESTS = tests/mantest tests/jqtest tests/shtest tests/utf8test tests/base64test tests/uritest
|
||||
if !WIN32
|
||||
TESTS += tests/optionaltest
|
||||
endif
|
||||
TESTS = tests/all.test
|
||||
TEST_LOG_COMPILER = ${srcdir}/tests/run
|
||||
|
||||
AM_TESTS_ENVIRONMENT = JQ=$(abs_builddir)/jq
|
||||
if ENABLE_VALGRIND
|
||||
AM_TESTS_ENVIRONMENT += ENABLE_VALGRIND=1
|
||||
endif
|
||||
|
||||
# This is a magic make variable that causes it to treat tests/man.test as a
|
||||
# DATA-type dependency for the check target. As a result, it will attempt to
|
||||
# run any defined targets for tests/man.test as a dependency for check. This
|
||||
# allows us to ensure that the tests are up-to-date if the manual has been updated
|
||||
check_DATA = tests/man.test
|
||||
|
||||
### Building the man tests
|
||||
|
||||
# We use the examples in the manual as additional tests, to ensure they always work.
|
||||
# As a result, we need to rebuild the tests if the manual has been updated.
|
||||
# Making changes to the manpage without having the python deps means your
|
||||
# tests won't run. If you aren't making changes to the examples, you probably
|
||||
# don't care. But if you are, then you need to run the tests anyway.
|
||||
tests/man.test tests/manonig.test: $(srcdir)/docs/content/manual/dev/manual.yml
|
||||
if ENABLE_DOCS
|
||||
$(AM_V_GEN) ( cd ${abs_srcdir}/docs && \
|
||||
$(PIPENV) run python validate_manual_schema.py content/manual/dev/manual.yml && \
|
||||
$(PIPENV) run python build_mantests.py )
|
||||
else
|
||||
@echo Changes to the manual.yml require docs to be enabled to update the manual test.
|
||||
@echo As a result, the manual test is out of date.
|
||||
endif
|
||||
|
||||
### Building the manpage
|
||||
|
||||
# We build the docs from the manpage yml. If no changes have been made to the
|
||||
# manpage, then we'll end up using the cached version. Otherwise, we need to
|
||||
# rebuild it.
|
||||
# If ENABLE_DOCS is not set, just copy jq.1.default to jq.1
|
||||
# The real_docs target succeeds (possibly after building jq.1) only if ENABLE_DOCS is set
|
||||
# Thus, making "dist" depend on "real_docs" ensures that we never build a tarball with
|
||||
# a stub manpage.
|
||||
|
||||
man_MANS = jq.1
|
||||
jq.1.prebuilt: $(srcdir)/docs/content/manual/dev/manual.yml
|
||||
.PHONY: real_docs
|
||||
if ENABLE_DOCS
|
||||
$(AM_V_GEN) ( cd ${abs_srcdir}/docs && \
|
||||
$(PIPENV) run python validate_manual_schema.py content/manual/dev/manual.yml && \
|
||||
$(PIPENV) run python build_manpage.py ) > $@
|
||||
jq.1: $(srcdir)/docs/content/3.manual/manual.yml
|
||||
( cd ${abs_srcdir}/docs; '$(BUNDLER)' exec rake manpage ) > $@ || { rm -f $@; false; }
|
||||
jq.1.default: $(srcdir)/docs/default_manpage.md
|
||||
( cd ${abs_srcdir}/docs; '$(BUNDLER)' exec rake manpage_default ) > $@ || { rm -f $@; false; }
|
||||
real_docs: jq.1
|
||||
if cmp jq.1 $(srcdir)/jq.1.default > /dev/null; then\
|
||||
rm -f jq.1; $(MAKE) $(AM_MAKEFLAGS) jq.1;\
|
||||
fi
|
||||
else
|
||||
@echo Changes to the manual.yml require docs to be enabled to update the manpage.
|
||||
@echo As a result, the manpage is out of date.
|
||||
jq.1: $(srcdir)/jq.1.default
|
||||
cp $^ $@
|
||||
real_docs:
|
||||
@echo "Ruby dependencies not found, cannot build manpage." > /dev/stderr
|
||||
@echo "Follow the instructions in docs/README.md to install them" > /dev/stderr
|
||||
@echo "and then rerun ./configure" > /dev/stderr
|
||||
false
|
||||
endif
|
||||
|
||||
jq.1: jq.1.prebuilt
|
||||
$(AM_V_GEN) cp $(srcdir)/jq.1.prebuilt $@
|
||||
|
||||
CLEANFILES += jq.1
|
||||
|
||||
### Build oniguruma
|
||||
|
||||
if BUILD_ONIGURUMA
|
||||
libjq_la_LIBADD += vendor/oniguruma/src/.libs/libonig.la
|
||||
SUBDIRS = vendor/oniguruma
|
||||
endif
|
||||
|
||||
AM_CFLAGS += $(onig_CFLAGS)
|
||||
|
||||
if WITH_ONIGURUMA
|
||||
TESTS += tests/onigtest tests/manonigtest
|
||||
endif
|
||||
|
||||
### Packaging
|
||||
|
||||
docs/site.yml: configure.ac
|
||||
sed 's/^jq_version: .*/jq_version: "$(VERSION)"/' $@ > $@.new
|
||||
mv $@.new $@
|
||||
|
||||
install-binaries: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) install-exec
|
||||
|
||||
DOC_FILES = docs/content docs/public docs/templates \
|
||||
docs/Pipfile docs/Pipfile.lock docs/build_manpage.py \
|
||||
docs/build_mantests.py docs/build_website.py docs/README.md \
|
||||
docs/validate_manual_schema.py docs/manual_schema.yml
|
||||
# Ensure "make dist" fails when we can't build the real manpage
|
||||
dist-hook: real_docs
|
||||
|
||||
EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \
|
||||
jq.1.prebuilt jq.spec src/lexer.c src/lexer.h src/parser.c \
|
||||
src/parser.h src/version.h src/builtin.jq scripts/version \
|
||||
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/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 \
|
||||
tests/modules/syntaxerror/syntaxerror.jq \
|
||||
tests/modules/test_bind_order.jq \
|
||||
tests/modules/test_bind_order0.jq \
|
||||
tests/modules/test_bind_order1.jq \
|
||||
tests/modules/test_bind_order2.jq \
|
||||
tests/onig.supp tests/local.supp \
|
||||
tests/setup tests/torture/input0.json \
|
||||
tests/optional.test tests/man.test tests/manonig.test \
|
||||
tests/jq.test tests/onig.test tests/base64.test tests/uri.test \
|
||||
tests/utf8-truncate.jq tests/jq-f-test.sh \
|
||||
tests/no-main-program.jq tests/yes-main-program.jq
|
||||
DOC_FILES = docs/content docs/public docs/templates docs/site.yml \
|
||||
docs/Gemfile docs/Gemfile.lock docs/Rakefile docs/README.md \
|
||||
docs/default_manpage.md jq.1.default
|
||||
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS=--with-oniguruma=builtin
|
||||
# setup is only used by distribution developers, not package developers.
|
||||
# Still, as a matter of allowing patching, its not a bad idea to distribute
|
||||
# the developer setup script in the tarball.
|
||||
EXTRA_DIST = config.h.in $(BUILT_SOURCES) $(man_MANS) $(TESTS) \
|
||||
$(TEST_LOG_COMPILER) gen_utf8_tables.py jq.spec \
|
||||
$(DOC_FILES)
|
||||
|
||||
# README.md is expected in GitHub projects, good stuff in it, so we'll
|
||||
# README.md is expected in Github projects, good stuff in it, so we'll
|
||||
# distribute it and install it with the package in the doc directory.
|
||||
dist_doc_DATA = README.md NEWS.md COPYING AUTHORS
|
||||
docdir = ${datadir}/doc/${PACKAGE}
|
||||
dist_doc_DATA = README.md COPYING AUTHORS README
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libjq.pc
|
||||
releasetag:
|
||||
git tag -s "jq-$$(cat VERSION)" -m "jq release $$(cat VERSION)"
|
||||
|
||||
RELEASE ?= 1
|
||||
rpm: dist jq.spec
|
||||
rpm: jq
|
||||
@echo "Packaging jq as an RPM ..."
|
||||
mkdir -p rpm/SOURCES rpm/BUILD rpm/BUILDROOT rpm/RPMS rpm/SPECS
|
||||
cp jq-$(VERSION).tar.gz rpm/SOURCES/
|
||||
rpmbuild -tb --define "_topdir ${PWD}/rpm" --define "_prefix /usr" --define "myver $(VERSION)" --define "myrel ${RELEASE}" rpm/SOURCES/jq-$(VERSION).tar.gz
|
||||
cp jq-$$(cat VERSION).tar.gz rpm/SOURCES/
|
||||
rpmbuild -tb --define "_topdir ${PWD}/rpm" --define "_prefix /usr" --define "myver $$(cat VERSION)" --define "myrel ${RELEASE}" rpm/SOURCES/jq-$$(cat VERSION).tar.gz
|
||||
find rpm/RPMS/ -name "*.rpm" -exec mv {} ./ \;
|
||||
rm -rf rpm
|
||||
|
||||
dist-clean-local:
|
||||
rm -f ${BUILT_SOURCES}
|
||||
|
||||
# Not sure why this doesn't get cleaned up automatically, guess
|
||||
# automake used to man pages which are hand coded?
|
||||
clean-local:
|
||||
rm -f jq.1
|
||||
@@ -1,633 +0,0 @@
|
||||
# 1.8.0
|
||||
|
||||
We are pleased to announce the release of version 1.8.0.
|
||||
This release includes a number of improvements since the last version.
|
||||
Note that some changes may introduce breaking changes to existing scripts,
|
||||
so be sure to read the following information carefully.
|
||||
Full commit log can be found at <https://github.com/jqlang/jq/compare/jq-1.7.1...jq-1.8.0>.
|
||||
|
||||
## Releasing
|
||||
|
||||
- Change the version number pattern to `1.X.Y` (`1.8.0` instead of `1.8`). @itchyny #2999
|
||||
- Generate provenance attestations for release artifacts and docker image. @lectrical #3225
|
||||
|
||||
```sh
|
||||
gh attestation verify --repo jqlang/jq jq-linux-amd64
|
||||
gh attestation verify --repo jqlang/jq oci://ghcr.io/jqlang/jq:1.8.0
|
||||
```
|
||||
|
||||
## Security fixes
|
||||
|
||||
- CVE-2024-23337: Fix signed integer overflow in `jvp_array_write` and `jvp_object_rehash`.
|
||||
@itchyny de21386681c0df0104a99d9d09db23a9b2a78b1e
|
||||
- The fix for this issue now limits the maximum size of arrays and objects to 536870912 (`2^29`) elements.
|
||||
- CVE-2024-53427: Reject NaN with payload while parsing JSON.
|
||||
@itchyny a09a4dfd55e6c24d04b35062ccfe4509748b1dd3
|
||||
- The fix for this issue now drops support for NaN with payload in JSON (like `NaN123`).
|
||||
Other JSON extensions like `NaN` and `Infinity` are still supported.
|
||||
- CVE-2025-48060: Fix heap buffer overflow in `jv_string_vfmt`.
|
||||
@itchyny c6e041699d8cd31b97375a2596217aff2cfca85b
|
||||
- Fix use of uninitialized value in `check_literal`. @itchyny #3324
|
||||
- Fix segmentation fault on `strftime/1`, `strflocaltime/1`. @itchyny #3271
|
||||
- Fix unhandled overflow in `@base64d`. @emanuele6 #3080
|
||||
|
||||
## CLI changes
|
||||
|
||||
- Fix `--indent 0` implicitly enabling `--compact-output`. @amarshall @gbrlmarn @itchyny #3232
|
||||
|
||||
```sh
|
||||
$ jq --indent 0 . <<< '{ "foo": ["hello", "world"] }'
|
||||
{
|
||||
"foo": [
|
||||
"hello",
|
||||
"world"
|
||||
]
|
||||
}
|
||||
# Previously, this implied --compact-output, but now outputs with new lines.
|
||||
```
|
||||
|
||||
- Improve error messages to show problematic position in the filter. @itchyny #3292
|
||||
|
||||
```sh
|
||||
$ jq -n '1 + $foo + 2'
|
||||
jq: error: $foo is not defined at <top-level>, line 1, column 5:
|
||||
1 + $foo + 2
|
||||
^^^^
|
||||
jq: 1 compile error
|
||||
```
|
||||
|
||||
- Include column number in parser and compiler error messages. @liviubobocu #3257
|
||||
- Fix error message for string literal beginning with single quote. @mattmeyers #2964
|
||||
|
||||
```sh
|
||||
$ jq .foo <<< "{'foo':'bar'}"
|
||||
jq: parse error: Invalid string literal; expected ", but got ' at line 1, column 7
|
||||
# Previously, the error message was Invalid numeric literal at line 1, column 7.
|
||||
```
|
||||
|
||||
- Improve `JQ_COLORS` environment variable to support larger escapes like truecolor. @SArpnt #3282
|
||||
|
||||
```sh
|
||||
JQ_COLORS="38;2;255;173;173:38;2;255;214;165:38;2;253;255;182:38;2;202;255;191:38;2;155;246;255:38;2;160;196;255:38;2;189;178;255:38;2;255;198;255" jq -nc '[null,false,true,42,{"a":"bc"}]'
|
||||
```
|
||||
|
||||
- Add `--library-path` long option for `-L`. @thaliaarchi #3194
|
||||
- Fix `--slurp --stream` when input has no trailing newline character. @itchyny #3279
|
||||
- Fix `--indent` option to error for malformed values. @thaliaarchi #3195
|
||||
- Fix option parsing of `--binary` on non-Windows platforms. @calestyo #3131
|
||||
- Fix issue with `~/.jq` on Windows where `$HOME` is not set. @kirkoman #3114
|
||||
- Fix broken non-Latin output in the command help on Windows. @itchyny #3299
|
||||
- Increase the maximum parsing depth for JSON to 10000. @itchyny #3328
|
||||
- Parse short options in order given. @thaliaarchi #3194
|
||||
- Consistently reset color formatting. @thaliaarchi #3034
|
||||
|
||||
## New functions
|
||||
|
||||
- Add `trim/0`, `ltrim/0` and `rtrim/0` to trim leading and trailing white spaces. @wader #3056
|
||||
|
||||
```sh
|
||||
$ jq -n '" hello " | trim, ltrim, rtrim'
|
||||
"hello"
|
||||
"hello "
|
||||
" hello"
|
||||
```
|
||||
|
||||
- Add `trimstr/1` to trim string from both ends. @gbrlmarn #3319
|
||||
|
||||
```sh
|
||||
$ jq -n '"foobarfoo" | trimstr("foo")'
|
||||
"bar"
|
||||
```
|
||||
|
||||
- Add `add/1`. Generator variant of `add/0`. @myaaaaaaaaa #3144
|
||||
|
||||
```sh
|
||||
$ jq -c '.sum = add(.xs[])' <<< '{"xs":[1,2,3]}'
|
||||
{"xs":[1,2,3],"sum":6}
|
||||
```
|
||||
|
||||
- Add `skip/2` as the counterpart to `limit/2`. @itchyny #3181
|
||||
|
||||
```sh
|
||||
$ jq -nc '[1,2,3,4,5] | [skip(2; .[])]'
|
||||
[3,4,5]
|
||||
```
|
||||
|
||||
- Add `toboolean/0` to convert strings to booleans. @brahmlower @itchyny #2098
|
||||
|
||||
```sh
|
||||
$ jq -n '"true", "false" | toboolean'
|
||||
true
|
||||
false
|
||||
```
|
||||
|
||||
- Add `@urid` format. Reverse of `@uri`. @fmgornick #3161
|
||||
|
||||
```sh
|
||||
$ jq -Rr '@urid' <<< '%6a%71'
|
||||
jq
|
||||
```
|
||||
|
||||
## Changes to existing functions
|
||||
|
||||
- Use code point index for `indices/1`, `index/1` and `rindex/1`. @wader #3065
|
||||
- This is a breaking change. Use `utf8bytelength/0` to get byte index.
|
||||
- Improve `tonumber/0` performance and rejects numbers with leading or trailing
|
||||
white spaces. @itchyny @thaliaarchi #3055 #3195
|
||||
- This is a breaking change. Use `trim/0` to remove leading and trailing white spaces.
|
||||
- Populate timezone data when formatting time. This fixes timezone name in
|
||||
`strftime/1`, `strflocaltime/1` for DST. @marcin-serwin @sihde #3203 #3264 #3323
|
||||
- Preserve numerical precision on unary negation, `abs/0`, `length/0`. @itchyny #3242 #3275
|
||||
- Make `last(empty)` yield no output values like `first(empty)`. @itchyny #3179
|
||||
- Make `ltrimstr/1` and `rtrimstr/1` error for non-string inputs. @emanuele6 #2969
|
||||
- Make `limit/2` error for negative count. @itchyny #3181
|
||||
- Fix `mktime/0` overflow and allow fewer elements in date-time representation array. @emanuele6 #3070 #3162
|
||||
- Fix non-matched optional capture group. @wader #3238
|
||||
- Provide `strptime/1` on all systems. @george-hopkins @fdellwing #3008 #3094
|
||||
- Fix `_WIN32` port of `strptime`. @emanuele6 #3071
|
||||
- Improve `bsearch/1` performance by implementing in C. @eloycoto #2945
|
||||
- Improve `unique/0` and `unique_by/1` performance. @itchyny @emanuele6 #3254 #3304
|
||||
- Fix error messages including long string literal not to break Unicode characters. @itchyny #3249
|
||||
- Remove `pow10/0` as it has been deprecated in glibc 2.27. Use `exp10/0` instead. @itchyny #3059
|
||||
- Remove private (and undocumented) `_nwise` filter. @itchyny #3260
|
||||
|
||||
## Language changes
|
||||
|
||||
- Fix precedence of binding syntax against unary and binary operators.
|
||||
Also, allow some expressions as object values. @itchyny #3053 #3326
|
||||
- This is a breaking change that may change the output of filters with binding syntax as follows.
|
||||
|
||||
```sh
|
||||
$ jq -nc '[-1 as $x | 1,$x]'
|
||||
[1,-1] # previously, [-1,-1]
|
||||
$ jq -nc '1 | . + 2 as $x | -$x'
|
||||
-3 # previously, -1
|
||||
$ jq -nc '{x: 1 + 2, y: false or true, z: null // 3}'
|
||||
{"x":3,"y":true,"z":3} # previously, syntax error
|
||||
```
|
||||
|
||||
- Support Tcl-style multiline comments. @emanuele6 #2989
|
||||
|
||||
```sh
|
||||
#!/bin/sh --
|
||||
# Can be use to do shebang scripts.
|
||||
# Next line will be seen as a comment be of the trailing backslash. \
|
||||
exec jq ...
|
||||
# this jq expression will result in [1]
|
||||
[
|
||||
1,
|
||||
# \
|
||||
2
|
||||
]
|
||||
```
|
||||
|
||||
- Fix `foreach` not to break init backtracking with `DUPN`. @kanwren #3266
|
||||
|
||||
```sh
|
||||
$ jq -n '[1, 2] | foreach .[] as $x (0, 1; . + $x)'
|
||||
1
|
||||
3
|
||||
2
|
||||
4
|
||||
```
|
||||
|
||||
- Fix `reduce`/`foreach` state variable should not be reset each iteration. @itchyny #3205
|
||||
|
||||
```sh
|
||||
$ jq -n 'reduce range(5) as $x (0; .+$x | select($x!=2))'
|
||||
8
|
||||
$ jq -nc '[foreach range(5) as $x (0; .+$x | select($x!=2); [$x,.])]'
|
||||
[[0,0],[1,1],[3,4],[4,8]]
|
||||
```
|
||||
|
||||
- Support CRLF line breaks in filters. @itchyny #3274
|
||||
- Improve performance of repeating strings. @itchyny #3272
|
||||
|
||||
## Documentation changes
|
||||
|
||||
- Switch the homepage to custom domain [jqlang.org](https://jqlang.org). @itchyny @owenthereal #3243
|
||||
- Make latest release instead of development version the default manual. @wader #3130
|
||||
- Add opengraph meta tags. @wader #3247
|
||||
- Replace jqplay.org with play.jqlang.org @owenthereal #3265
|
||||
- Add missing line from decNumber's licence to `COPYING`. @emanuele6 #3106
|
||||
- Various document improvements. @tsibley #3322, @itchyny #3240, @jhcarl0814 #3239,
|
||||
@01mf02 #3184, @thaliaarchi #3199, @NathanBaulch #3173, @cjlarose #3164,
|
||||
@sheepster1 #3105, #3103, @kishoreinvits #3042, @jbrains #3035, @thalman #3033,
|
||||
@SOF3 #3017, @wader #3015, @wllm-rbnt #3002
|
||||
|
||||
## Build improvements
|
||||
|
||||
- Fix build with GCC 15 (C23). @emanuele6 #3209
|
||||
- Fix build with `-Woverlength-strings` @emanuele6 #3019
|
||||
- Fix compiler warning `type-limits` in `found_string`. @itchyny #3263
|
||||
- Fix compiler error in `jv_dtoa.c` and `builtin.c`. @UlrichEckhardt #3036
|
||||
- Fix warning: a function definition without a prototype is deprecated. @itchyny #3259
|
||||
- Define `_BSD_SOURCE` in `builtin.c` for OpenBSD support. @itchyny #3278
|
||||
- Define empty `JV_{,V}PRINTF_LIKE` macros if `__GNUC__` is not defined. @emanuele6 #3160
|
||||
- Avoid `ctype.h` abuse: cast `char` to `unsigned char` first. @riastradh #3152
|
||||
- Remove multiple calls to free when successively calling `jq_reset`. @Sameesunkaria #3134
|
||||
- Enable IBM z/OS support. @sachintu47 #3277
|
||||
- Fix insecure `RUNPATH`. @orbea #3212
|
||||
- Avoid zero-length `calloc`. @itchyny #3280
|
||||
- Move oniguruma and decNumber to vendor directory. @itchyny #3234
|
||||
|
||||
## Test improvements
|
||||
|
||||
- Run tests in C locale. @emanuele6 #3039
|
||||
- Improve reliability of `NO_COLOR` tests. @dag-erling #3188
|
||||
- Improve `shtest` not to fail if `JQ_COLORS` and `NO_COLOR` are already set. @SArpnt #3283
|
||||
- Refactor constant folding tests. @itchyny #3233
|
||||
- Make tests pass when `--disable-decnum`. @nicowilliams 6d02d53f515bf1314d644eee93ba30b0d11c7d2b
|
||||
- Disable Valgrind by default during testing. @itchyny #3269
|
||||
|
||||
# 1.7.1
|
||||
|
||||
## Security
|
||||
|
||||
- CVE-2023-50246: Fix heap buffer overflow in jvp\_literal\_number\_literal
|
||||
- CVE-2023-50268: fix stack-buffer-overflow if comparing nan with payload
|
||||
|
||||
## CLI changes
|
||||
|
||||
- Make the default background color more suitable for bright backgrounds. @mjarosie @taoky @nicowilliams @itchyny #2904
|
||||
- Allow passing the inline jq script after `--`. @emanuele6 #2919
|
||||
- Restrict systems operations on OpenBSD and remove unused `mkstemp`. @klemensn #2934
|
||||
- Fix possible uninitialised value dereference if `jq_init()` fails. @emanuele6 @nicowilliams #2935
|
||||
|
||||
## Language changes
|
||||
|
||||
- Simplify `paths/0` and `paths/1`. @asheiduk @emanuele6 #2946
|
||||
- Reject `U+001F` in string literals. @torsten-schenk @itchyny @wader #2911
|
||||
- Remove unused nref accumulator in `block_bind_library`. @emanuele6 #2914
|
||||
- Remove a bunch of unused variables, and useless assignments. @emanuele6 #2914
|
||||
- main.c: Remove unused EXIT\_STATUS\_EXACT option. @emanuele6 #2915
|
||||
- Actually use the number correctly casted from double to int as index. @emanuele6 #2916
|
||||
- src/builtin.c: remove unnecessary jv\_copy-s in type\_error/type\_error2. @emanuele6 #2937
|
||||
- Remove undefined behavior caught by LLVM 10 UBSAN. @Gaelan @emanuele6 #2926
|
||||
- Convert decnum to binary64 (double) instead of decimal64. This makes jq behave like the JSON specification suggests and more similar to other languages. @wader @leonid-s-usov #2949
|
||||
- Fix memory leaks on invalid input for `ltrimstr/1` and `rtrimstr/1`. @emanuele6 #2977
|
||||
- Fix memory leak on failed get for `setpath/2`. @emanuele6 #2970
|
||||
- Fix nan from json parsing also for nans with payload that start with 'n'. @emanuele6 #2985
|
||||
- Allow carriage return characters in comments. @emanuele6 #2942 #2984
|
||||
|
||||
## Documentation changes
|
||||
|
||||
- Generate links in the man page. @emanuele6 #2931
|
||||
- Standardize arch types to AMD64 & ARM64 from index page download dropdown. @owenthereal #2884
|
||||
|
||||
## libjq
|
||||
|
||||
- Add extern C for C++. @rockwotj #2953
|
||||
|
||||
## Build and test changes
|
||||
|
||||
- Fix incorrect syntax for checksum file. @kamontat @wader #2899
|
||||
- Remove `-dirty` version suffix for windows release build. @itchyny #2888
|
||||
- Make use of `od` in tests more compatible. @nabijaczleweli @emanuele6 @nicowilliams #2922
|
||||
- Add dependabot. @yeikel #2889
|
||||
- Extend fuzzing setup to fuzz parser and JSON serializer. @DavidKorczynski @emanuele6 #2952
|
||||
- Keep releasing executables with legacy names. @itchyny #2951
|
||||
|
||||
# 1.7
|
||||
|
||||
After a five year hiatus we're back with a GitHub organization, with new admins and new maintainers who have brought a great deal of energy to make a long-awaited and long-needed new release. We're very grateful for all the new owners, admins, and maintainers. Special thanks go to Owen Ou (@owenthereal) for pushing to set up a new GitHub organization for jq, Stephen Dolan (@stedolan) for transferring the jq repository to the new organization, @itchyny for doing a great deal of work to get the release done, Mattias Wadman (@wader) and Emanuele Torre (@emanuele6) for many PRs and code reviews. Many others also contributed PRs, issues, and code reviews as well, and you can find their contributions in the Git log and on the [closed issues and PRs page](https://github.com/jqlang/jq/issues?q=is%3Aclosed+sort%3Aupdated-desc).
|
||||
|
||||
Since the last stable release many things have happened:
|
||||
|
||||
- jq now lives at <https://github.com/jqlang>
|
||||
- New maintainers, admins, and owners have been recruited.
|
||||
- A list of [current maintainers](https://github.com/jqlang/jq/blob/jq-1.7/AUTHORS#L4-L14)
|
||||
- NEWS file is replaced by NEWS.md with Markdown format. @wader #2599
|
||||
- CI, scan builds, release, website builds etc now use GitHub actions. @owenthereal @wader @itchyny #2596 #2603 #2620 #2723
|
||||
- Lots of documentation improvements and fixes.
|
||||
- Website updated with new section search box, better section ids for linking, dark mode, etc. @itchyny #2628
|
||||
- Release builds for:
|
||||
- Linux `amd64`, `arm64`, `armel`, `armhf`, `i386`, `mips`, `mips64`, `mips64el`, `mips64r6`, `mips64r6el`, `mipsel`, `mipsr6`, `mipsr6el`, `powerpc`, `ppc64el`, `riscv64` and `s390x`
|
||||
- macOS `amd64` and `arm64`
|
||||
- Windows `i386` and `amd64`
|
||||
- Docker `linux/386`, `linux/amd64`, `linux/arm64`, `linux/mips64le`, `linux/ppc64le`, `linux/riscv64` and `linux/s390x`
|
||||
- More details see @owenthereal #2665
|
||||
- Docker images are now available from `ghcr.io/jqlang/jq` instead of Docker Hub. @itchyny #2652 #2686
|
||||
- OSS-fuzz. @DavidKorczynski #2760 #2762
|
||||
|
||||
Full commit log can be found at <https://github.com/jqlang/jq/compare/jq-1.6...jq-1.7> but here are some highlights:
|
||||
|
||||
## CLI changes
|
||||
|
||||
- Make object key color configurable using `JQ_COLORS` environment variable. @itchyny @haguenau @ericpruitt #2703
|
||||
|
||||
```sh
|
||||
# this would make "field" bold yellow (`1;33`, the last value)
|
||||
$ JQ_COLORS="0;90:0;37:0;37:0;37:0;32:1;37:1;37:1;33" ./jq -n '{field: 123}'
|
||||
{
|
||||
"field": 123
|
||||
}
|
||||
```
|
||||
|
||||
- Change the default color of null to Bright Black. @itchyny #2824
|
||||
- Respect `NO_COLOR` environment variable to disable color output. See <https://no-color.org> for details. @itchyny #2728
|
||||
- Improved `--help` output. Now mentions all options and nicer order. @itchyny @wader #2747 #2766 #2799
|
||||
- Fix multiple issues of exit code using `--exit-code`/`-e` option. @ryo1kato #1697
|
||||
|
||||
```sh
|
||||
# true-ish last output value exits with zero
|
||||
$ jq -ne true ; echo $?
|
||||
true
|
||||
0
|
||||
# false-ish last output value (false and null) exits with 1
|
||||
$ jq -ne false ; echo $?
|
||||
false
|
||||
1
|
||||
# no output value exists with 4
|
||||
$ jq -ne empty ; echo $?
|
||||
4
|
||||
```
|
||||
|
||||
- Add `--binary`/`-b` on Windows for binary output. To get `\n` instead of `\r\n` line endings. @nicowilliams 0dab2b1
|
||||
- Add `--raw-output0` for NUL (zero byte) separated output. @asottile @pabs3 @itchyny #1990 #2235 #2684
|
||||
|
||||
```sh
|
||||
# will output a zero byte after each output
|
||||
$ jq -n --raw-output0 '1,2,3' | xxd
|
||||
00000000: 3100 3200 3300 1.2.3.
|
||||
# can be used with xargs -0
|
||||
$ jq -n --raw-output0 '"a","b","c"' | xargs -0 -n1
|
||||
a
|
||||
b
|
||||
c
|
||||
$ jq -n --raw-output0 '"a b c", "d\ne\nf"' | xargs -0 printf '[%s]\n'
|
||||
[a b c]
|
||||
[d
|
||||
e
|
||||
f]
|
||||
# can be used with read -d ''
|
||||
$ while IFS= read -r -d '' json; do
|
||||
> jq '.name' <<< "$json"
|
||||
> done < <(jq -n --raw-output0 '{name:"a b c"},{name:"d\ne\nf"}')
|
||||
"a b c"
|
||||
"d\ne\nf"
|
||||
# also it's an error to output a string containing a NUL when using NUL separator
|
||||
$ jq -n --raw-output0 '"\u0000"'
|
||||
jq: error (at <unknown>): Cannot dump a string containing NUL with --raw-output0 option
|
||||
```
|
||||
|
||||
- Fix assert crash and validate JSON for `--jsonarg`. @wader #2658
|
||||
- Remove deprecated `--argfile` option. @itchyny #2768
|
||||
- Enable stack protection. @nicowilliams #2801
|
||||
|
||||
## Language changes
|
||||
|
||||
- Use decimal number literals to preserve precision. Comparison operations respects precision but arithmetic operations might truncate. @leonid-s-usov #1752
|
||||
|
||||
```sh
|
||||
# precision is preserved
|
||||
$ echo '100000000000000000' | jq .
|
||||
100000000000000000
|
||||
# comparison respects precision (this is false in JavaScript)
|
||||
$ jq -n '100000000000000000 < 100000000000000001'
|
||||
true
|
||||
# sort/0 works
|
||||
$ jq -n -c '[100000000000000001, 100000000000000003, 100000000000000004, 100000000000000002] | sort'
|
||||
[100000000000000001,100000000000000002,100000000000000003,100000000000000004]
|
||||
# arithmetic operations might truncate (same as JavaScript)
|
||||
$ jq -n '100000000000000000 + 10'
|
||||
100000000000000020
|
||||
```
|
||||
|
||||
- Adds new builtin `pick(stream)` to emit a projection of the input object or array. @pkoppstein #2656 #2779
|
||||
|
||||
```sh
|
||||
$ jq -n '{"a": 1, "b": {"c": 2, "d": 3}, "e": 4} | pick(.a, .b.c, .x)'
|
||||
{
|
||||
"a": 1,
|
||||
"b": {
|
||||
"c": 2
|
||||
},
|
||||
"x": null
|
||||
}
|
||||
```
|
||||
|
||||
- Adds new builtin `debug(msgs)` that works like `debug` but applies a filter on the input before writing to stderr. @pkoppstein #2710
|
||||
|
||||
```sh
|
||||
$ jq -n '1 as $x | 2 | debug("Entering function foo with $x == \($x)", .) | (.+1)'
|
||||
["DEBUG:","Entering function foo with $x == 1"]
|
||||
["DEBUG:",2]
|
||||
3
|
||||
$ jq -n '{a: 1, b: 2, c: 3} | debug({a, b, sum: (.a+.b)})'
|
||||
["DEBUG:",{"a":1,"b":2,"sum":3}]
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3
|
||||
}
|
||||
```
|
||||
|
||||
- Adds new builtin `scan($re; $flags)`. Was documented but not implemented. @itchyny #1961
|
||||
|
||||
```sh
|
||||
# look for pattern "ab" in "abAB" ignoring casing
|
||||
$ jq -n '"abAB" | scan("ab"; "i")'
|
||||
"ab"
|
||||
"AB"
|
||||
```
|
||||
|
||||
- Adds new builtin `abs` to get absolute value. This potentially allows the literal value of numbers to be preserved as `length` and `fabs` convert to float. @pkoppstein #2767
|
||||
- Allow `if` without `else`-branch. When skipped the `else`-branch will be `.` (identity). @chancez @wader #1825 #2481
|
||||
|
||||
```sh
|
||||
# convert 1 to "one" otherwise keep as is
|
||||
$ jq -n '1,2 | if . == 1 then "one" end'
|
||||
"one"
|
||||
2
|
||||
# behaves the same as
|
||||
$ jq -n '1,2 | if . == 1 then "one" else . end'
|
||||
"one"
|
||||
2
|
||||
# also works with elif
|
||||
$ jq -n '1,2,3 | if . == 1 then "one" elif . == 2 then "two" end
|
||||
"one"
|
||||
"two"
|
||||
3
|
||||
```
|
||||
|
||||
- Allow use of `$binding` as key in object literals. @nicowilliams 8ea4a55
|
||||
|
||||
```sh
|
||||
$ jq -n '"a" as $key | {$key: 123}'
|
||||
{
|
||||
"a": 123
|
||||
}
|
||||
# previously parentheses were needed
|
||||
$ jq -n '"a" as $key | {($key): 123}'
|
||||
{
|
||||
"a": 123
|
||||
}
|
||||
```
|
||||
|
||||
- Allow dot between chained indexes when using `.["index"]` @nicowilliams #1168
|
||||
|
||||
```sh
|
||||
$ jq -n '{"a": {"b": 123}} | .a["b"]'
|
||||
123
|
||||
# now this also works
|
||||
$ jq -n '{"a": {"b": 123}} | .a.["b"]'
|
||||
123
|
||||
```
|
||||
|
||||
- Allow dot for chained value iterator `.[]`, `.[]?` @wader #2650
|
||||
|
||||
```sh
|
||||
$ jq -n '{"a": [123]} | .a[]'
|
||||
123
|
||||
# now this also works
|
||||
$ jq -n '{"a": [123]} | .a.[]'
|
||||
123
|
||||
```
|
||||
|
||||
- Fix try/catch catches more than it should. @nicowilliams #2750
|
||||
- Speed up and refactor some builtins, also remove `scalars_or_empty/0`. @muhmuhten #1845
|
||||
- Now `halt` and `halt_error` exit immediately instead of continuing to the next input. @emanuele6 #2667
|
||||
- Fix issue converting string to number after previous convert error. @thalman #2400
|
||||
- Fix issue representing large numbers on some platforms causing invalid JSON output. @itchyny #2661
|
||||
- Fix deletion using assigning empty against arrays. @itchyny #2133
|
||||
|
||||
```sh
|
||||
# now this works as expected, filter out all values over 2 by assigning empty
|
||||
$ jq -c '(.[] | select(. >= 2)) |= empty' <<< '[1,5,3,0,7]'
|
||||
[1,0]
|
||||
```
|
||||
|
||||
- Allow keywords to be used as binding name in more places. @emanuele6 #2681
|
||||
- Allow using `nan` as NaN in JSON. @emanuele6 #2712
|
||||
- Expose a module's function names in `modulemeta`. @mrwilson #2837
|
||||
- Fix `contains/1` to handle strings with NUL. @nicowilliams 61cd6db
|
||||
- Fix `stderr/0` to output raw text without any decoration. @itchyny #2751
|
||||
- Fix `nth/2` to emit empty on index out of range. @itchyny #2674
|
||||
- Fix `implode` to not assert and instead replace invalid Unicode codepoints. @wader #2646
|
||||
- Fix `indices/1` and `rindex/1` in case of overlapping matches in strings. @emanuele6 #2718
|
||||
- Fix `sub/3` to resolve issues involving global search-and-replace (gsub) operations. @pkoppstein #2641
|
||||
- Fix `significand/0`, `gamma/0` and `drem/2` to be available on macOS. @itchyny #2756 #2775
|
||||
- Fix empty regular expression matches. @itchyny #2677
|
||||
- Fix overflow exception of the modulo operator. @itchyny #2629
|
||||
- Fix string multiplication by 0 (and less than 1) to emit empty string. @itchyny #2142
|
||||
- Fix segfault when using libjq and threads. @thalman #2546
|
||||
- Fix constant folding of division and reminder with zero divisor. @itchyny #2797
|
||||
- Fix `error/0`, `error/1` to throw null error. @emanuele6 #2823
|
||||
- Simpler and faster `transpose`. @pkoppstein #2758
|
||||
- Simple and efficient implementation of `walk/1`. @pkoppstein #2795
|
||||
- Remove deprecated filters `leaf_paths`, `recurse_down`. @itchyny #2666
|
||||
|
||||
# Previous releases
|
||||
|
||||
Release history
|
||||
|
||||
- jq version 1.6 was released on Fri Nov 2 2018
|
||||
- jq version 1.5 was released on Sat Aug 15 2015
|
||||
- jq version 1.4 was released on Mon Jun 9 2014
|
||||
- jq version 1.3 was released on Sun May 19 2013
|
||||
- jq version 1.2 was released on Thu Dec 20 2012
|
||||
- jq version 1.1 was released on Sun Oct 21 2012
|
||||
- jq version 1.0 was released on Sun Oct 21 2012
|
||||
|
||||
New features in 1.6 since 1.5:
|
||||
|
||||
- Destructuring Alternation
|
||||
|
||||
- New Builtins:
|
||||
- builtins/0
|
||||
- stderr/0
|
||||
- halt/0, halt_error/1
|
||||
- isempty/1
|
||||
- walk/1
|
||||
- utf8bytelength/1
|
||||
- localtime/0, strflocaltime/1
|
||||
- SQL-style builtins
|
||||
- and more!
|
||||
|
||||
- Add support for ASAN and UBSAN
|
||||
|
||||
- Make it easier to use jq with shebangs (8f6f28c)
|
||||
|
||||
- Add $ENV builtin variable to access environment
|
||||
|
||||
- Add JQ_COLORS env var for configuring the output colors
|
||||
|
||||
New features in 1.5 since 1.4:
|
||||
|
||||
- regular expressions (with Oniguruma)
|
||||
|
||||
- a library/module system
|
||||
|
||||
- many new builtins
|
||||
|
||||
- datetime builtins
|
||||
- math builtins
|
||||
- regexp-related builtins
|
||||
- stream-related builtins (e.g., all/1, any/1)
|
||||
- minimal I/O builtins (`inputs`, `debug`)
|
||||
|
||||
- new syntactic features, including:
|
||||
|
||||
- destructuring (`. as [$first, $second] | ...`)
|
||||
- try/catch, generalized `?` operator, and label/break
|
||||
- `foreach`
|
||||
- multiple definitions of a function with different numbers of
|
||||
arguments
|
||||
|
||||
- command-line arguments
|
||||
|
||||
- --join-lines / -j for raw output
|
||||
- --argjson and --slurpfile
|
||||
- --tab and --indent
|
||||
- --stream (streaming JSON parser)
|
||||
- --seq (RFC7464 JSON text sequence)
|
||||
- --run-tests improvements
|
||||
|
||||
- optimizations:
|
||||
|
||||
- tail-call optimization
|
||||
- reduce and foreach no longer leak a reference to .
|
||||
|
||||
New features in 1.4 since 1.3:
|
||||
|
||||
- command-line arguments
|
||||
|
||||
- jq --arg-file variable file
|
||||
- jq --unbuffered
|
||||
- jq -e / --exit-status (set exit status based on outputs)
|
||||
- jq -S / --sort-keys (now jq no longer sorts object keys by
|
||||
default
|
||||
|
||||
- syntax
|
||||
|
||||
- .. -> like // in XPath (recursive traversal)
|
||||
- question mark (e.g., .a?) to suppress errors
|
||||
- ."foo" syntax (equivalent to .["foo"])
|
||||
- better error handling for .foo
|
||||
- added % operator (modulo)
|
||||
- allow negation without requiring extra parenthesis
|
||||
- more function arguments (up to six)
|
||||
|
||||
- filters:
|
||||
|
||||
- any, all
|
||||
- iterables, arrays, objects, scalars, nulls, booleans, numbers,
|
||||
strings, values
|
||||
|
||||
- string built-ins:
|
||||
|
||||
- split
|
||||
- join (join an array of strings with a given separator string)
|
||||
- ltrimstr, rtrimstr
|
||||
- startswith, endswith
|
||||
- explode, implode
|
||||
- fromjson, tojson
|
||||
- index, rindex, indices
|
||||
|
||||
- math functions
|
||||
|
||||
- floor, sqrt, cbrt, etcetera (depends on what's available from libm)
|
||||
|
||||
- libjq -- a C API interface to jq's JSON representation and for
|
||||
running jq programs from C applications
|
||||
@@ -1,78 +1,23 @@
|
||||
# jq
|
||||
jq
|
||||
==
|
||||
|
||||
`jq` is a lightweight and flexible command-line JSON processor akin to `sed`,`awk`,`grep`, and friends for JSON data. It's written in portable C and has zero runtime dependencies, allowing you to easily slice, filter, map, and transform structured data.
|
||||
jq is a command-line JSON processor.
|
||||
|
||||
## Documentation
|
||||
If you want to learn to use jq, read the documentation at
|
||||
[http://stedolan.github.io/jq](http://stedolan.github.io/jq). This
|
||||
documentation is generated from the docs/ folder of this repository.
|
||||
|
||||
- **Official Documentation**: [jqlang.org](https://jqlang.org)
|
||||
- **Try jq Online**: [play.jqlang.org](https://play.jqlang.org)
|
||||
If you want to hack on jq, feel free, but be warned that its internals
|
||||
are not well-documented at the moment. Bring a hard hat and a
|
||||
shovel. Also, read the wiki: https://github.com/stedolan/jq/wiki
|
||||
|
||||
## Installation
|
||||
To build jq, run
|
||||
|
||||
### Prebuilt Binaries
|
||||
./configure
|
||||
make
|
||||
sudo make install (optionally)
|
||||
|
||||
Download the latest releases from the [GitHub release page](https://github.com/jqlang/jq/releases).
|
||||
If you've just checked out the latest version from git (rather than
|
||||
using a released source tarball) then you'll need to run this first:
|
||||
|
||||
### Docker Image
|
||||
|
||||
Pull the [jq image](https://github.com/jqlang/jq/pkgs/container/jq) to start quickly with Docker.
|
||||
|
||||
#### Run with Docker
|
||||
|
||||
##### Example: Extracting the version from a `package.json` file
|
||||
|
||||
```bash
|
||||
docker run --rm -i ghcr.io/jqlang/jq:latest < package.json '.version'
|
||||
```
|
||||
|
||||
##### Example: Extracting the version from a `package.json` file with a mounted volume
|
||||
|
||||
```bash
|
||||
docker run --rm -i -v "$PWD:$PWD" -w "$PWD" ghcr.io/jqlang/jq:latest '.version' package.json
|
||||
```
|
||||
|
||||
### Building from source
|
||||
|
||||
#### Dependencies
|
||||
|
||||
- libtool
|
||||
- make
|
||||
- automake
|
||||
- autoconf
|
||||
|
||||
#### Instructions
|
||||
|
||||
```console
|
||||
git submodule update --init # if building from git to get oniguruma
|
||||
autoreconf -i # if building from git
|
||||
./configure --with-oniguruma=builtin
|
||||
make clean # if upgrading from a version previously built from source
|
||||
make -j8
|
||||
make check
|
||||
sudo make install
|
||||
```
|
||||
|
||||
Build a statically linked version:
|
||||
|
||||
```console
|
||||
make LDFLAGS=-all-static
|
||||
```
|
||||
|
||||
If you're not using the latest git version but instead building a released tarball (available on the release page), skip the `autoreconf` step, and flex or bison won't be needed.
|
||||
|
||||
##### Cross-Compilation
|
||||
|
||||
For details on cross-compilation, check out the [GitHub Actions file](.github/workflows/ci.yml) and the [cross-compilation wiki page](https://github.com/jqlang/jq/wiki/Cross-compilation).
|
||||
|
||||
## Community & Support
|
||||
|
||||
- Questions & Help: [Stack Overflow (jq tag)](https://stackoverflow.com/questions/tagged/jq)
|
||||
- Chat & Community: [Join us on Discord](https://discord.gg/yg6yjNmgAC)
|
||||
- Wiki & Advanced Topics: [Explore the Wiki](https://github.com/jqlang/jq/wiki)
|
||||
|
||||
## License
|
||||
|
||||
`jq` is released under the [MIT License](COPYING). `jq`'s documentation is
|
||||
licensed under the [Creative Commons CC BY 3.0](COPYING).
|
||||
`jq` uses parts of the open source C library "decNumber", which is distributed
|
||||
under [ICU License](COPYING)
|
||||
autoreconf
|
||||
@@ -1,7 +0,0 @@
|
||||
# How to report security vulnerabilities in `jq`
|
||||
|
||||
GitHub has a [mechanism for private disclosure of vulnerabilities](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability) to repository owners and authorized persons such as maintainers. The `jqlang/jq` repository now has this feature enabled.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
See [Privately Reporting a Security Vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability). Click on [`jqlang/jq`](https://github.com/jqlang/jq)'s [Security page](https://github.com/jqlang/jq/security) and click on [Report a vulnerability](https://github.com/jqlang/jq/security/advisories/new). This will notify the owners and maintainers. After submitting you'll get an option to start a private clone of `jqlang/jq` for collaboration with the maintainers.
|
||||
@@ -0,0 +1,581 @@
|
||||
#include <string.h>
|
||||
#include "builtin.h"
|
||||
#include "compile.h"
|
||||
#include "jq_parser.h"
|
||||
#include "locfile.h"
|
||||
#include "jv_aux.h"
|
||||
#include "jv_unicode.h"
|
||||
|
||||
|
||||
|
||||
typedef jv (*func_1)(jv);
|
||||
typedef jv (*func_2)(jv,jv);
|
||||
typedef jv (*func_3)(jv,jv,jv);
|
||||
typedef jv (*func_4)(jv,jv,jv,jv);
|
||||
typedef jv (*func_5)(jv,jv,jv,jv,jv);
|
||||
jv cfunction_invoke(struct cfunction* function, jv input[]) {
|
||||
switch (function->nargs) {
|
||||
case 1: return ((func_1)function->fptr)(input[0]);
|
||||
case 2: return ((func_2)function->fptr)(input[0], input[1]);
|
||||
case 3: return ((func_3)function->fptr)(input[0], input[1], input[2]);
|
||||
case 4: return ((func_4)function->fptr)(input[0], input[1], input[2], input[3]);
|
||||
case 5: return ((func_5)function->fptr)(input[0], input[1], input[2], input[3], input[4]);
|
||||
default: return jv_invalid_with_msg(jv_string("Function takes too many arguments"));
|
||||
}
|
||||
}
|
||||
|
||||
static jv type_error(jv bad, const char* msg) {
|
||||
jv err = jv_invalid_with_msg(jv_string_fmt("%s %s",
|
||||
jv_kind_name(jv_get_kind(bad)),
|
||||
msg));
|
||||
jv_free(bad);
|
||||
return err;
|
||||
}
|
||||
|
||||
static jv type_error2(jv bad1, jv bad2, const char* msg) {
|
||||
jv err = jv_invalid_with_msg(jv_string_fmt("%s and %s %s",
|
||||
jv_kind_name(jv_get_kind(bad1)),
|
||||
jv_kind_name(jv_get_kind(bad2)),
|
||||
msg));
|
||||
jv_free(bad1);
|
||||
jv_free(bad2);
|
||||
return err;
|
||||
}
|
||||
|
||||
static jv f_plus(jv input, jv a, jv b) {
|
||||
jv_free(input);
|
||||
if (jv_get_kind(a) == JV_KIND_NULL) {
|
||||
jv_free(a);
|
||||
return b;
|
||||
} else if (jv_get_kind(b) == JV_KIND_NULL) {
|
||||
jv_free(b);
|
||||
return a;
|
||||
} else if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
|
||||
return jv_number(jv_number_value(a) +
|
||||
jv_number_value(b));
|
||||
} else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) {
|
||||
return jv_string_concat(a, b);
|
||||
} else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
|
||||
return jv_array_concat(a, b);
|
||||
} else if (jv_get_kind(a) == JV_KIND_OBJECT && jv_get_kind(b) == JV_KIND_OBJECT) {
|
||||
return jv_object_merge(a, b);
|
||||
} else {
|
||||
return type_error2(a, b, "cannot be added");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_negate(jv input) {
|
||||
if (jv_get_kind(input) != JV_KIND_NUMBER) {
|
||||
return type_error(input, "cannot be negated");
|
||||
}
|
||||
jv ret = jv_number(-jv_number_value(input));
|
||||
jv_free(input);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jv f_minus(jv input, jv a, jv b) {
|
||||
jv_free(input);
|
||||
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
|
||||
return jv_number(jv_number_value(a) - jv_number_value(b));
|
||||
} else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
|
||||
jv out = jv_array();
|
||||
jv_array_foreach(a, i, x) {
|
||||
int include = 1;
|
||||
jv_array_foreach(b, j, y) {
|
||||
if (jv_equal(jv_copy(x), y)) {
|
||||
include = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (include)
|
||||
out = jv_array_append(out, jv_copy(x));
|
||||
jv_free(x);
|
||||
}
|
||||
jv_free(a);
|
||||
jv_free(b);
|
||||
return out;
|
||||
} else {
|
||||
return type_error2(a, b, "cannot be subtracted");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_multiply(jv input, jv a, jv b) {
|
||||
jv_free(input);
|
||||
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
|
||||
return jv_number(jv_number_value(a) * jv_number_value(b));
|
||||
} else {
|
||||
return type_error2(a, b, "cannot be multiplied");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_divide(jv input, jv a, jv b) {
|
||||
jv_free(input);
|
||||
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
|
||||
return jv_number(jv_number_value(a) / jv_number_value(b));
|
||||
} else {
|
||||
return type_error2(a, b, "cannot be divided");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_equal(jv input, jv a, jv b) {
|
||||
jv_free(input);
|
||||
return jv_bool(jv_equal(a, b));
|
||||
}
|
||||
|
||||
static jv f_notequal(jv input, jv a, jv b) {
|
||||
jv_free(input);
|
||||
return jv_bool(!jv_equal(a, b));
|
||||
}
|
||||
|
||||
enum cmp_op {
|
||||
CMP_OP_LESS,
|
||||
CMP_OP_GREATER,
|
||||
CMP_OP_LESSEQ,
|
||||
CMP_OP_GREATEREQ
|
||||
};
|
||||
|
||||
static jv order_cmp(jv input, jv a, jv b, enum cmp_op op) {
|
||||
jv_free(input);
|
||||
int r = jv_cmp(a, b);
|
||||
return jv_bool((op == CMP_OP_LESS && r < 0) ||
|
||||
(op == CMP_OP_LESSEQ && r <= 0) ||
|
||||
(op == CMP_OP_GREATEREQ && r >= 0) ||
|
||||
(op == CMP_OP_GREATER && r > 0));
|
||||
}
|
||||
|
||||
static jv f_less(jv input, jv a, jv b) {
|
||||
return order_cmp(input, a, b, CMP_OP_LESS);
|
||||
}
|
||||
|
||||
static jv f_greater(jv input, jv a, jv b) {
|
||||
return order_cmp(input, a, b, CMP_OP_GREATER);
|
||||
}
|
||||
|
||||
static jv f_lesseq(jv input, jv a, jv b) {
|
||||
return order_cmp(input, a, b, CMP_OP_LESSEQ);
|
||||
}
|
||||
|
||||
static jv f_greatereq(jv input, jv a, jv b) {
|
||||
return order_cmp(input, a, b, CMP_OP_GREATEREQ);
|
||||
}
|
||||
|
||||
static jv f_contains(jv a, jv b) {
|
||||
if (jv_get_kind(a) == jv_get_kind(b)) {
|
||||
return jv_bool(jv_contains(a, b));
|
||||
} else {
|
||||
return type_error2(a, b, "cannot have their containment checked");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_tonumber(jv input) {
|
||||
if (jv_get_kind(input) == JV_KIND_NUMBER) {
|
||||
return input;
|
||||
}
|
||||
if (jv_get_kind(input) == JV_KIND_STRING) {
|
||||
jv parsed = jv_parse(jv_string_value(input));
|
||||
if (!jv_is_valid(parsed) || jv_get_kind(parsed) == JV_KIND_NUMBER) {
|
||||
jv_free(input);
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
return type_error(input, "cannot be parsed as a number");
|
||||
}
|
||||
|
||||
static jv f_length(jv input) {
|
||||
if (jv_get_kind(input) == JV_KIND_ARRAY) {
|
||||
return jv_number(jv_array_length(input));
|
||||
} else if (jv_get_kind(input) == JV_KIND_OBJECT) {
|
||||
return jv_number(jv_object_length(input));
|
||||
} else if (jv_get_kind(input) == JV_KIND_STRING) {
|
||||
return jv_number(jv_string_length_codepoints(input));
|
||||
} else if (jv_get_kind(input) == JV_KIND_NULL) {
|
||||
jv_free(input);
|
||||
return jv_number(0);
|
||||
} else {
|
||||
return type_error(input, "has no length");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_tostring(jv input) {
|
||||
if (jv_get_kind(input) == JV_KIND_STRING) {
|
||||
return input;
|
||||
} else {
|
||||
return jv_dump_string(input, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#define CHARS_ALPHANUM "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
static jv escape_string(jv input, const char* escapings) {
|
||||
|
||||
assert(jv_get_kind(input) == JV_KIND_STRING);
|
||||
const char* lookup[128] = {0};
|
||||
const char* p = escapings;
|
||||
while (*p) {
|
||||
lookup[(int)*p] = p+1;
|
||||
p++;
|
||||
p += strlen(p);
|
||||
p++;
|
||||
}
|
||||
|
||||
jv ret = jv_string("");
|
||||
const char* i = jv_string_value(input);
|
||||
const char* end = i + jv_string_length_bytes(jv_copy(input));
|
||||
const char* cstart;
|
||||
int c = 0;
|
||||
while ((i = jvp_utf8_next((cstart = i), end, &c))) {
|
||||
assert(c != -1);
|
||||
if (c < 128 && lookup[c]) {
|
||||
ret = jv_string_append_str(ret, lookup[c]);
|
||||
} else {
|
||||
ret = jv_string_append_buf(ret, cstart, i - cstart);
|
||||
}
|
||||
}
|
||||
jv_free(input);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static jv f_format(jv input, jv fmt) {
|
||||
if (jv_get_kind(fmt) != JV_KIND_STRING) {
|
||||
jv_free(input);
|
||||
return type_error(fmt, "is not a valid format");
|
||||
}
|
||||
const char* fmt_s = jv_string_value(fmt);
|
||||
if (!strcmp(fmt_s, "json")) {
|
||||
jv_free(fmt);
|
||||
return jv_dump_string(input, 0);
|
||||
} else if (!strcmp(fmt_s, "text")) {
|
||||
jv_free(fmt);
|
||||
return f_tostring(input);
|
||||
} else if (!strcmp(fmt_s, "csv")) {
|
||||
jv_free(fmt);
|
||||
if (jv_get_kind(input) != JV_KIND_ARRAY)
|
||||
return type_error(input, "cannot be csv-formatted, only array");
|
||||
jv line = jv_string("");
|
||||
jv_array_foreach(input, i, x) {
|
||||
if (i) line = jv_string_append_str(line, ",");
|
||||
switch (jv_get_kind(x)) {
|
||||
case JV_KIND_NULL:
|
||||
/* null rendered as empty string */
|
||||
jv_free(x);
|
||||
break;
|
||||
case JV_KIND_TRUE:
|
||||
case JV_KIND_FALSE:
|
||||
line = jv_string_concat(line, jv_dump_string(x, 0));
|
||||
break;
|
||||
case JV_KIND_NUMBER:
|
||||
if (jv_number_value(x) != jv_number_value(x)) {
|
||||
/* NaN, render as empty string */
|
||||
jv_free(x);
|
||||
} else {
|
||||
line = jv_string_concat(line, jv_dump_string(x, 0));
|
||||
}
|
||||
break;
|
||||
case JV_KIND_STRING: {
|
||||
line = jv_string_append_str(line, "\"");
|
||||
line = jv_string_concat(line, escape_string(x, "\"\"\"\0"));
|
||||
line = jv_string_append_str(line, "\"");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
jv_free(input);
|
||||
jv_free(line);
|
||||
return type_error(x, "is not valid in a csv row");
|
||||
}
|
||||
}
|
||||
jv_free(input);
|
||||
return line;
|
||||
} else if (!strcmp(fmt_s, "html")) {
|
||||
jv_free(fmt);
|
||||
return escape_string(f_tostring(input), "&&\0<<\0>>\0''\0\""\0");
|
||||
} else if (!strcmp(fmt_s, "uri")) {
|
||||
jv_free(fmt);
|
||||
input = f_tostring(input);
|
||||
|
||||
int unreserved[128] = {0};
|
||||
const char* p = CHARS_ALPHANUM "-_.!~*'()";
|
||||
while (*p) unreserved[(int)*p++] = 1;
|
||||
|
||||
jv line = jv_string("");
|
||||
const char* s = jv_string_value(input);
|
||||
for (int i=0; i<jv_string_length_bytes(jv_copy(input)); i++) {
|
||||
unsigned ch = (unsigned)(unsigned char)*s;
|
||||
if (ch < 128 && unreserved[ch]) {
|
||||
line = jv_string_append_buf(line, s, 1);
|
||||
} else {
|
||||
line = jv_string_concat(line, jv_string_fmt("%%%02x", ch));
|
||||
}
|
||||
s++;
|
||||
}
|
||||
jv_free(input);
|
||||
return line;
|
||||
} else if (!strcmp(fmt_s, "sh")) {
|
||||
jv_free(fmt);
|
||||
if (jv_get_kind(input) != JV_KIND_ARRAY)
|
||||
input = jv_array_set(jv_array(), 0, input);
|
||||
jv line = jv_string("");
|
||||
jv_array_foreach(input, i, x) {
|
||||
if (i) line = jv_string_append_str(line, " ");
|
||||
switch (jv_get_kind(x)) {
|
||||
case JV_KIND_NULL:
|
||||
case JV_KIND_TRUE:
|
||||
case JV_KIND_FALSE:
|
||||
case JV_KIND_NUMBER:
|
||||
line = jv_string_concat(line, jv_dump_string(x, 0));
|
||||
break;
|
||||
|
||||
case JV_KIND_STRING: {
|
||||
line = jv_string_append_str(line, "'");
|
||||
line = jv_string_concat(line, escape_string(x, "''\\''\0"));
|
||||
line = jv_string_append_str(line, "'");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
jv_free(input);
|
||||
jv_free(line);
|
||||
return type_error(x, "can not be escaped for shell");
|
||||
}
|
||||
}
|
||||
jv_free(input);
|
||||
return line;
|
||||
} else if (!strcmp(fmt_s, "base64")) {
|
||||
jv_free(fmt);
|
||||
input = f_tostring(input);
|
||||
jv line = jv_string("");
|
||||
const char b64[64 + 1] = CHARS_ALPHANUM "+/";
|
||||
const char* data = jv_string_value(input);
|
||||
int len = jv_string_length_bytes(jv_copy(input));
|
||||
for (int i=0; i<len; i+=3) {
|
||||
uint32_t code = 0;
|
||||
int n = len - i >= 3 ? 3 : len-i;
|
||||
for (int j=0; j<3; j++) {
|
||||
code <<= 8;
|
||||
code |= j < n ? (unsigned)data[i+j] : 0;
|
||||
}
|
||||
char buf[4];
|
||||
for (int j=0; j<4; j++) {
|
||||
buf[j] = b64[(code >> (18 - j*6)) & 0x3f];
|
||||
}
|
||||
if (n < 3) buf[3] = '=';
|
||||
if (n < 2) buf[2] = '=';
|
||||
line = jv_string_append_buf(line, buf, sizeof(buf));
|
||||
}
|
||||
jv_free(input);
|
||||
return line;
|
||||
} else {
|
||||
jv_free(input);
|
||||
return jv_invalid_with_msg(jv_string_concat(fmt, jv_string(" is not a valid format")));
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_keys(jv input) {
|
||||
if (jv_get_kind(input) == JV_KIND_OBJECT || jv_get_kind(input) == JV_KIND_ARRAY) {
|
||||
return jv_keys(input);
|
||||
} else {
|
||||
return type_error(input, "has no keys");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_sort(jv input){
|
||||
if (jv_get_kind(input) == JV_KIND_ARRAY) {
|
||||
return jv_sort(input, jv_copy(input));
|
||||
} else {
|
||||
return type_error(input, "cannot be sorted, as it is not an array");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_sort_by_impl(jv input, jv keys) {
|
||||
if (jv_get_kind(input) == JV_KIND_ARRAY &&
|
||||
jv_get_kind(keys) == JV_KIND_ARRAY &&
|
||||
jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
|
||||
return jv_sort(input, keys);
|
||||
} else {
|
||||
return type_error2(input, keys, "cannot be sorted, as they are not both arrays");
|
||||
}
|
||||
}
|
||||
|
||||
static jv f_group_by_impl(jv input, jv keys) {
|
||||
if (jv_get_kind(input) == JV_KIND_ARRAY &&
|
||||
jv_get_kind(keys) == JV_KIND_ARRAY &&
|
||||
jv_array_length(jv_copy(input)) == jv_array_length(jv_copy(keys))) {
|
||||
return jv_group(input, keys);
|
||||
} else {
|
||||
return type_error2(input, keys, "cannot be sorted, as they are not both arrays");
|
||||
}
|
||||
}
|
||||
|
||||
static jv minmax_by(jv values, jv keys, int is_min) {
|
||||
if (jv_get_kind(values) != JV_KIND_ARRAY)
|
||||
return type_error2(values, keys, "cannot be iterated over");
|
||||
if (jv_get_kind(keys) != JV_KIND_ARRAY)
|
||||
return type_error2(values, keys, "cannot be iterated over");
|
||||
if (jv_array_length(jv_copy(values)) != jv_array_length(jv_copy(keys)))
|
||||
return type_error2(values, keys, "have wrong length");
|
||||
|
||||
if (jv_array_length(jv_copy(values)) == 0) {
|
||||
jv_free(values);
|
||||
jv_free(keys);
|
||||
return jv_null();
|
||||
}
|
||||
jv ret = jv_array_get(jv_copy(values), 0);
|
||||
jv retkey = jv_array_get(jv_copy(keys), 0);
|
||||
for (int i=1; i<jv_array_length(jv_copy(values)); i++) {
|
||||
jv item = jv_array_get(jv_copy(keys), i);
|
||||
int cmp = jv_cmp(jv_copy(item), jv_copy(retkey));
|
||||
if ((cmp < 0) == (is_min == 1)) {
|
||||
jv_free(retkey);
|
||||
retkey = item;
|
||||
jv_free(ret);
|
||||
ret = jv_array_get(jv_copy(values), i);
|
||||
} else {
|
||||
jv_free(item);
|
||||
}
|
||||
}
|
||||
jv_free(values);
|
||||
jv_free(keys);
|
||||
jv_free(retkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static jv f_min(jv x) {
|
||||
return minmax_by(x, jv_copy(x), 1);
|
||||
}
|
||||
|
||||
static jv f_max(jv x) {
|
||||
return minmax_by(x, jv_copy(x), 0);
|
||||
}
|
||||
|
||||
static jv f_min_by_impl(jv x, jv y) {
|
||||
return minmax_by(x, y, 1);
|
||||
}
|
||||
|
||||
static jv f_max_by_impl(jv x, jv y) {
|
||||
return minmax_by(x, y, 0);
|
||||
}
|
||||
|
||||
|
||||
static jv f_type(jv input) {
|
||||
jv out = jv_string(jv_kind_name(jv_get_kind(input)));
|
||||
jv_free(input);
|
||||
return out;
|
||||
}
|
||||
|
||||
static jv f_error(jv input, jv msg) {
|
||||
jv_free(input);
|
||||
msg = f_tostring(msg);
|
||||
return jv_invalid_with_msg(msg);
|
||||
}
|
||||
|
||||
static const struct cfunction function_list[] = {
|
||||
{(cfunction_ptr)f_plus, "_plus", 3},
|
||||
{(cfunction_ptr)f_negate, "_negate", 1},
|
||||
{(cfunction_ptr)f_minus, "_minus", 3},
|
||||
{(cfunction_ptr)f_multiply, "_multiply", 3},
|
||||
{(cfunction_ptr)f_divide, "_divide", 3},
|
||||
{(cfunction_ptr)f_tonumber, "tonumber", 1},
|
||||
{(cfunction_ptr)f_tostring, "tostring", 1},
|
||||
{(cfunction_ptr)f_keys, "keys", 1},
|
||||
{(cfunction_ptr)jv_setpath, "setpath", 3}, // FIXME typechecking
|
||||
{(cfunction_ptr)jv_getpath, "getpath", 2},
|
||||
{(cfunction_ptr)jv_delpaths, "delpaths", 2},
|
||||
{(cfunction_ptr)jv_has, "has", 2},
|
||||
{(cfunction_ptr)f_equal, "_equal", 3},
|
||||
{(cfunction_ptr)f_notequal, "_notequal", 3},
|
||||
{(cfunction_ptr)f_less, "_less", 3},
|
||||
{(cfunction_ptr)f_greater, "_greater", 3},
|
||||
{(cfunction_ptr)f_lesseq, "_lesseq", 3},
|
||||
{(cfunction_ptr)f_greatereq, "_greatereq", 3},
|
||||
{(cfunction_ptr)f_contains, "contains", 2},
|
||||
{(cfunction_ptr)f_length, "length", 1},
|
||||
{(cfunction_ptr)f_type, "type", 1},
|
||||
{(cfunction_ptr)f_sort, "sort", 1},
|
||||
{(cfunction_ptr)f_sort_by_impl, "_sort_by_impl", 2},
|
||||
{(cfunction_ptr)f_group_by_impl, "_group_by_impl", 2},
|
||||
{(cfunction_ptr)f_min, "min", 1},
|
||||
{(cfunction_ptr)f_max, "max", 1},
|
||||
{(cfunction_ptr)f_min_by_impl, "_min_by_impl", 2},
|
||||
{(cfunction_ptr)f_max_by_impl, "_max_by_impl", 2},
|
||||
{(cfunction_ptr)f_error, "error", 2},
|
||||
{(cfunction_ptr)f_format, "format", 2},
|
||||
};
|
||||
|
||||
struct bytecoded_builtin { const char* name; block code; };
|
||||
static block bind_bytecoded_builtins(block b) {
|
||||
block builtins = gen_noop();
|
||||
{
|
||||
struct bytecoded_builtin builtin_defs[] = {
|
||||
{"empty", gen_op_simple(BACKTRACK)},
|
||||
{"false", gen_const(jv_false())},
|
||||
{"true", gen_const(jv_true())},
|
||||
{"null", gen_const(jv_null())},
|
||||
{"not", gen_condbranch(gen_const(jv_false()),
|
||||
gen_const(jv_true()))}
|
||||
};
|
||||
for (unsigned i=0; i<sizeof(builtin_defs)/sizeof(builtin_defs[0]); i++) {
|
||||
builtins = BLOCK(builtins, gen_function(builtin_defs[i].name, gen_noop(),
|
||||
builtin_defs[i].code));
|
||||
}
|
||||
}
|
||||
{
|
||||
struct bytecoded_builtin builtin_def_1arg[] = {
|
||||
{"path", BLOCK(gen_op_simple(PATH_BEGIN),
|
||||
gen_call("arg", gen_noop()),
|
||||
gen_op_simple(PATH_END))},
|
||||
};
|
||||
for (unsigned i=0; i<sizeof(builtin_def_1arg)/sizeof(builtin_def_1arg[0]); i++) {
|
||||
builtins = BLOCK(builtins, gen_function(builtin_def_1arg[i].name,
|
||||
gen_op_block_unbound(CLOSURE_PARAM, "arg"),
|
||||
builtin_def_1arg[i].code));
|
||||
}
|
||||
}
|
||||
{
|
||||
block rangevar = block_bind(gen_op_var_unbound(STOREV, "rangevar"),
|
||||
gen_noop(), OP_HAS_VARIABLE);
|
||||
block init = BLOCK(gen_op_simple(DUP), gen_call("start", gen_noop()), rangevar);
|
||||
block range = BLOCK(init,
|
||||
gen_call("end", gen_noop()),
|
||||
gen_op_var_bound(RANGE, rangevar));
|
||||
builtins = BLOCK(builtins, gen_function("range",
|
||||
BLOCK(gen_op_block_unbound(CLOSURE_PARAM, "start"),
|
||||
gen_op_block_unbound(CLOSURE_PARAM, "end")),
|
||||
range));
|
||||
}
|
||||
|
||||
return block_bind_referenced(builtins, b, OP_IS_CALL_PSEUDO);
|
||||
}
|
||||
|
||||
static const char* const jq_builtins[] = {
|
||||
"def map(f): [.[] | f];",
|
||||
"def select(f): if f then . else empty end;",
|
||||
"def sort_by(f): _sort_by_impl(map([f]));",
|
||||
"def group_by(f): _group_by_impl(map([f]));",
|
||||
"def unique: group_by(.) | map(.[0]);",
|
||||
"def max_by(f): _max_by_impl(map([f]));",
|
||||
"def min_by(f): _min_by_impl(map([f]));",
|
||||
"def add: reduce .[] as $x (null; . + $x);",
|
||||
"def del(f): delpaths([path(f)]);",
|
||||
"def _assign(paths; value): value as $v | reduce path(paths) as $p (.; setpath($p; $v));",
|
||||
"def _modify(paths; update): reduce path(paths) as $p (.; setpath($p; getpath($p) | update));",
|
||||
"def recurse(f): ., (f | select(. != null) | recurse(f));",
|
||||
"def to_entries: [keys[] as $k | {key: $k, value: .[$k]}];",
|
||||
"def from_entries: map({(.key): .value}) | add;",
|
||||
"def with_entries(f): to_entries | map(f) | from_entries;",
|
||||
"def reverse: [.[length - 1 - range(0;length)]];",
|
||||
};
|
||||
|
||||
|
||||
block builtins_bind(block b) {
|
||||
for (int i=(int)(sizeof(jq_builtins)/sizeof(jq_builtins[0]))-1; i>=0; i--) {
|
||||
struct locfile src;
|
||||
locfile_init(&src, jq_builtins[i], strlen(jq_builtins[i]));
|
||||
block funcs;
|
||||
int nerrors = jq_parse_library(&src, &funcs);
|
||||
assert(!nerrors);
|
||||
b = block_bind_referenced(funcs, b, OP_IS_CALL_PSEUDO);
|
||||
locfile_free(&src);
|
||||
}
|
||||
b = bind_bytecoded_builtins(b);
|
||||
return gen_cbinding(function_list, sizeof(function_list)/sizeof(function_list[0]), b);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef BUILTIN_H
|
||||
#define BUILTIN_H
|
||||
|
||||
#include "compile.h"
|
||||
|
||||
block builtins_bind(block);
|
||||
|
||||
|
||||
typedef void (*cfunction_ptr)(void);
|
||||
|
||||
struct cfunction {
|
||||
cfunction_ptr fptr;
|
||||
const char* name;
|
||||
int nargs;
|
||||
};
|
||||
|
||||
|
||||
jv cfunction_invoke(struct cfunction* function, jv input[]);
|
||||
|
||||
|
||||
#endif
|
||||
+25
-58
@@ -3,64 +3,17 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bytecode.h"
|
||||
#include "opcode.h"
|
||||
#include "jv_alloc.h"
|
||||
|
||||
// flags, length
|
||||
#define NONE 0, 1
|
||||
#define CONSTANT OP_HAS_CONSTANT, 2
|
||||
#define VARIABLE (OP_HAS_VARIABLE | OP_HAS_BINDING), 3
|
||||
#define GLOBAL (OP_HAS_CONSTANT | OP_HAS_VARIABLE | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4
|
||||
#define BRANCH OP_HAS_BRANCH, 2
|
||||
#define CFUNC (OP_HAS_CFUNC | OP_HAS_BINDING), 3
|
||||
#define UFUNC (OP_HAS_UFUNC | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4
|
||||
#define DEFINITION (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0
|
||||
#define CLOSURE_REF_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 2
|
||||
|
||||
#define OP(name, imm, in, out) \
|
||||
{name, #name, imm, in, out},
|
||||
|
||||
static const struct opcode_description opcode_descriptions[] = {
|
||||
#include "opcode_list.h"
|
||||
};
|
||||
|
||||
static const struct opcode_description invalid_opcode_description = {
|
||||
-1, "#INVALID", 0, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
const struct opcode_description* opcode_describe(opcode op) {
|
||||
if ((int)op >= 0 && (int)op < NUM_OPCODES) {
|
||||
return &opcode_descriptions[op];
|
||||
} else {
|
||||
return &invalid_opcode_description;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int bytecode_operation_length(uint16_t* codeptr) {
|
||||
static int bytecode_operation_length(uint16_t* codeptr) {
|
||||
int length = opcode_describe(*codeptr)->length;
|
||||
if (*codeptr == CALL_JQ || *codeptr == TAIL_CALL_JQ) {
|
||||
if (*codeptr == CALL_JQ) {
|
||||
length += codeptr[1] * 2;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
static void dump_code(int indent, struct bytecode* bc) {
|
||||
int pc = 0;
|
||||
while (pc < bc->codelen) {
|
||||
printf("%*s", indent, "");
|
||||
dump_operation(bc, bc->code + pc);
|
||||
printf("\n");
|
||||
pc += bytecode_operation_length(bc->code + pc);
|
||||
}
|
||||
}
|
||||
|
||||
static void symbol_table_free(struct symbol_table* syms) {
|
||||
jv_mem_free(syms->cfunctions);
|
||||
jv_free(syms->cfunc_names);
|
||||
jv_mem_free(syms);
|
||||
}
|
||||
|
||||
void dump_disassembly(int indent, struct bytecode* bc) {
|
||||
if (bc->nclosures > 0) {
|
||||
printf("%*s[params: ", indent, "");
|
||||
@@ -84,6 +37,16 @@ void dump_disassembly(int indent, struct bytecode* bc) {
|
||||
}
|
||||
}
|
||||
|
||||
void dump_code(int indent, struct bytecode* bc) {
|
||||
int pc = 0;
|
||||
while (pc < bc->codelen) {
|
||||
printf("%*s", indent, "");
|
||||
dump_operation(bc, bc->code + pc);
|
||||
printf("\n");
|
||||
pc += bytecode_operation_length(bc->code + pc);
|
||||
}
|
||||
}
|
||||
|
||||
static struct bytecode* getlevel(struct bytecode* bc, int level) {
|
||||
while (level > 0) {
|
||||
bc = bc->parent;
|
||||
@@ -99,17 +62,17 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
|
||||
printf("%s", op->name);
|
||||
if (op->length > 1) {
|
||||
uint16_t imm = bc->code[pc++];
|
||||
if (op->op == CALL_JQ || op->op == TAIL_CALL_JQ) {
|
||||
if (op->op == CALL_JQ) {
|
||||
for (int i=0; i<imm+1; i++) {
|
||||
uint16_t level = bc->code[pc++];
|
||||
uint16_t idx = bc->code[pc++];
|
||||
jv name;
|
||||
if (idx & ARG_NEWCLOSURE) {
|
||||
idx &= ~ARG_NEWCLOSURE;
|
||||
name = jv_object_get(jv_copy(getlevel(bc,level)->subfunctions[idx]->debuginfo),
|
||||
name = jv_object_get(jv_copy(getlevel(bc,level)->subfunctions[idx]->debuginfo),
|
||||
jv_string("name"));
|
||||
} else {
|
||||
name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,level)->debuginfo),
|
||||
name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,level)->debuginfo),
|
||||
jv_string("params")), idx);
|
||||
}
|
||||
printf(" %s:%d",
|
||||
@@ -133,8 +96,8 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
|
||||
} else if (op->flags & OP_HAS_VARIABLE) {
|
||||
uint16_t v = bc->code[pc++];
|
||||
jv name = jv_array_get(jv_object_get(jv_copy(getlevel(bc,imm)->debuginfo), jv_string("locals")), v);
|
||||
printf(" $%s:%d",
|
||||
jv_string_value(name),
|
||||
printf(" $%s:%d",
|
||||
jv_string_value(name),
|
||||
v);
|
||||
jv_free(name);
|
||||
if (imm) {
|
||||
@@ -143,12 +106,16 @@ void dump_operation(struct bytecode* bc, uint16_t* codeptr) {
|
||||
} else {
|
||||
printf(" %d", imm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void symbol_table_free(struct symbol_table* syms) {
|
||||
jv_mem_free(syms->cfunctions);
|
||||
jv_free(syms->cfunc_names);
|
||||
jv_mem_free(syms);
|
||||
}
|
||||
|
||||
void bytecode_free(struct bytecode* bc) {
|
||||
if (!bc)
|
||||
return;
|
||||
jv_mem_free(bc->code);
|
||||
jv_free(bc->constants);
|
||||
for (int i=0; i<bc->nsubfunctions; i++)
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
#ifndef BYTECODE_H
|
||||
#define BYTECODE_H
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jv.h"
|
||||
#include "opcode.h"
|
||||
#include "builtin.h"
|
||||
|
||||
#define MAX_CFUNCTION_ARGS 10
|
||||
struct symbol_table {
|
||||
struct cfunction* cfunctions;
|
||||
int ncfunctions;
|
||||
jv cfunc_names;
|
||||
};
|
||||
|
||||
// The bytecode format matters in:
|
||||
// execute.c - interpreter
|
||||
// compile.c - compiler
|
||||
// bytecode.c - disassembler
|
||||
|
||||
#define ARG_NEWCLOSURE 0x1000
|
||||
|
||||
struct bytecode {
|
||||
uint16_t* code;
|
||||
int codelen;
|
||||
|
||||
int nlocals;
|
||||
int nclosures;
|
||||
|
||||
jv constants; // JSON array of constants
|
||||
struct symbol_table* globals;
|
||||
|
||||
struct bytecode** subfunctions;
|
||||
int nsubfunctions;
|
||||
|
||||
struct bytecode* parent;
|
||||
|
||||
jv debuginfo;
|
||||
};
|
||||
|
||||
void dump_disassembly(int, struct bytecode* code);
|
||||
void dump_code(int, struct bytecode* code);
|
||||
void dump_operation(struct bytecode* bc, uint16_t* op);
|
||||
|
||||
void symbol_table_free(struct symbol_table* syms);
|
||||
void bytecode_free(struct bytecode* bc);
|
||||
|
||||
#endif
|
||||
-106
@@ -1,106 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Mac C. compile-ios.sh for JQ.
|
||||
|
||||
# Defaults
|
||||
set -e
|
||||
oniguruma='6.9.10'
|
||||
|
||||
unset CFLAGS
|
||||
unset CXXFLAGS
|
||||
unset LDFLAGS
|
||||
|
||||
# Parse args.
|
||||
usage(){
|
||||
cat << EOF
|
||||
${0##*/}: usage
|
||||
|
||||
Description:
|
||||
This simple script builds oniguruma and jq for all *-apple-darwin devices.
|
||||
|
||||
Arguments:
|
||||
--extra-cflags <arg>: Pass defines or includes to clang.
|
||||
--extra-ldflags <arg>: Pass libs or includes to ld64.
|
||||
|
||||
--with-oniguruma <arg>: Change default version of onigurma from ${oniguruma}.
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
while (( $# )); do
|
||||
case "$1" in
|
||||
--with-oniguruma) shift; oniguruma="${1}" ;;
|
||||
|
||||
--extra-cflags) shift; export CFLAGS_="${1}" ;;
|
||||
--extra-ldflags) shift; export LDFLAGS_="${1}" ;;
|
||||
|
||||
--help) usage ;;
|
||||
*) echo -e "Unknown option: ${1}\n"; usage ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Start building.
|
||||
echo "Building..."
|
||||
MAKEJOBS="$(sysctl -n hw.ncpu || echo 1)"
|
||||
CC_="$(xcrun -f clang || echo clang)"
|
||||
|
||||
onig_url="https://github.com/kkos/oniguruma/releases/download/v${oniguruma}/onig-${oniguruma}.tar.gz"
|
||||
builddir="${TMPDIR:-/tmp}/${RANDOM:-'xxxxx'}-compile-ios-build"
|
||||
cwd="$(realpath ${PWD} 2>/dev/null || echo ${PWD})"
|
||||
|
||||
t_exit() {
|
||||
cat << EOF
|
||||
|
||||
A error as occurred.
|
||||
oniguruma location: ${builddir}/onig/onig-${oniguruma}
|
||||
jq location: ${cwd}
|
||||
|
||||
Provide config.log and console logs when posting a issue.
|
||||
|
||||
EOF
|
||||
}
|
||||
trap t_exit ERR
|
||||
|
||||
# Onig.
|
||||
mkdir -p "${builddir}/onig"
|
||||
cd "${builddir}/"
|
||||
curl -L ${onig_url} | tar xz
|
||||
for arch in i386 x86_64 armv7 armv7s arm64; do
|
||||
if [[ "$arch" = "i386" || "$arch" = "x86_64" ]]; then
|
||||
SYSROOT=$(xcrun -f --sdk iphonesimulator --show-sdk-path)
|
||||
else
|
||||
SYSROOT=$(xcrun -f --sdk iphoneos --show-sdk-path)
|
||||
fi
|
||||
HOST="${arch}-apple-darwin"
|
||||
[[ "${arch}" = "arm64" ]] && HOST="aarch64-apple-darwin"
|
||||
|
||||
CFLAGS="-arch ${arch} -miphoneos-version-min=9.0 -isysroot ${SYSROOT} ${CFLAGS_} -D_REENTRANT"
|
||||
LDFLAGS="-arch ${arch} -miphoneos-version-min=9.0 -isysroot ${SYSROOT} ${LDFLAGS_}"
|
||||
CC="${CC_} ${CFLAGS}"
|
||||
|
||||
# ./configure; make install
|
||||
cd "${builddir}/onig-${oniguruma}"
|
||||
CC=${CC} LDFLAGS=${LDFLAGS} \
|
||||
./configure --host=${HOST} --build=$(./config.guess) --enable-shared=no --enable-static=yes --prefix=/
|
||||
make -j${MAKEJOBS} install DESTDIR="${cwd}/ios/onig/${arch}"
|
||||
make clean
|
||||
|
||||
# Jump back to JQ.
|
||||
cd ${cwd}
|
||||
[[ ! -f ./configure ]] && autoreconf -ivf
|
||||
CC=${CC} LDFLAGS=${LDFLAGS} \
|
||||
./configure --host=${HOST} --build=$(./config/config.guess) --enable-docs=no --enable-shared=no --enable-static=yes --prefix=/ --with-oniguruma=${cwd}/ios/onig/${arch} $(test -z ${BISON+x} || echo '--enable-maintainer-mode')
|
||||
make -j${MAKEJOBS} install DESTDIR="${cwd}/ios/jq/${arch}"
|
||||
make clean
|
||||
done
|
||||
|
||||
mkdir -p "${cwd}/ios/dest/lib"
|
||||
# lipo, make a static lib.
|
||||
lipo -create -output ${cwd}/ios/dest/lib/libonig.a ${cwd}/ios/onig/{i386,x86_64,armv7,armv7s,arm64}/lib/libonig.a
|
||||
lipo -create -output ${cwd}/ios/dest/lib/libjq.a ${cwd}/ios/jq/{i386,x86_64,armv7,armv7s,arm64}/lib/libjq.a
|
||||
|
||||
# Take the arm64 headers- the most common target.
|
||||
cp -r ${cwd}/ios/jq/arm64/include ${cwd}/ios/dest/
|
||||
rm -rf ${cwd}/build/ios/{i386,x86_64,armv7,armv7s,arm64}
|
||||
|
||||
echo "Output to ${cwd}/ios/dest"
|
||||
@@ -0,0 +1,678 @@
|
||||
#define _GNU_SOURCE // for strdup
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "opcode.h"
|
||||
#include "compile.h"
|
||||
#include "bytecode.h"
|
||||
#include "locfile.h"
|
||||
#include "jv_alloc.h"
|
||||
|
||||
/*
|
||||
The intermediate representation for jq filters is as a sequence of
|
||||
struct inst, which form a doubly-linked list via the next and prev
|
||||
pointers.
|
||||
|
||||
A "block" represents a sequence of "struct inst", which may be
|
||||
empty.
|
||||
|
||||
Blocks are generated by the parser bottom-up, so may have free
|
||||
variables (refer to things not defined). See inst.bound_by and
|
||||
inst.symbol.
|
||||
*/
|
||||
struct inst {
|
||||
struct inst* next;
|
||||
struct inst* prev;
|
||||
|
||||
opcode op;
|
||||
|
||||
struct {
|
||||
uint16_t intval;
|
||||
struct inst* target;
|
||||
jv constant;
|
||||
const struct cfunction* cfunc;
|
||||
} imm;
|
||||
|
||||
location source;
|
||||
|
||||
// Binding
|
||||
// An instruction requiring binding (for parameters/variables/functions)
|
||||
// is in one of three states:
|
||||
// inst->bound_by = NULL - Unbound free variable
|
||||
// inst->bound_by = inst - This instruction binds a variable
|
||||
// inst->bound_by = other - Uses variable bound by other instruction
|
||||
// Unbound instructions (references to other things that may or may not
|
||||
// exist) are created by "gen_foo_unbound", and bindings are created by
|
||||
// block_bind(definition, body), which binds all instructions in
|
||||
// body which are unboudn and refer to "definition" by name.
|
||||
struct inst* bound_by;
|
||||
char* symbol;
|
||||
|
||||
block subfn; // used by CLOSURE_CREATE (body of function)
|
||||
block arglist; // used by CLOSURE_CREATE (formals) and CALL_JQ (arguments)
|
||||
|
||||
// This instruction is compiled as part of which function?
|
||||
// (only used during block_compile)
|
||||
struct bytecode* compiled;
|
||||
|
||||
int bytecode_pos; // position just after this insn
|
||||
};
|
||||
|
||||
static inst* inst_new(opcode op) {
|
||||
inst* i = jv_mem_alloc(sizeof(inst));
|
||||
i->next = i->prev = 0;
|
||||
i->op = op;
|
||||
i->bytecode_pos = -1;
|
||||
i->bound_by = 0;
|
||||
i->symbol = 0;
|
||||
i->subfn = gen_noop();
|
||||
i->arglist = gen_noop();
|
||||
i->source = UNKNOWN_LOCATION;
|
||||
return i;
|
||||
}
|
||||
|
||||
static void inst_free(struct inst* i) {
|
||||
jv_mem_free(i->symbol);
|
||||
block_free(i->subfn);
|
||||
block_free(i->arglist);
|
||||
if (opcode_describe(i->op)->flags & OP_HAS_CONSTANT) {
|
||||
jv_free(i->imm.constant);
|
||||
}
|
||||
jv_mem_free(i);
|
||||
}
|
||||
|
||||
static block inst_block(inst* i) {
|
||||
block b = {i,i};
|
||||
return b;
|
||||
}
|
||||
|
||||
static int block_is_single(block b) {
|
||||
return b.first && b.first == b.last;
|
||||
}
|
||||
|
||||
static inst* block_take(block* b) {
|
||||
if (b->first == 0) return 0;
|
||||
inst* i = b->first;
|
||||
if (i->next) {
|
||||
i->next->prev = 0;
|
||||
b->first = i->next;
|
||||
i->next = 0;
|
||||
} else {
|
||||
b->first = 0;
|
||||
b->last = 0;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
block gen_location(location loc, block b) {
|
||||
for (inst* i = b.first; i; i = i->next) {
|
||||
if (i->source.start == UNKNOWN_LOCATION.start &&
|
||||
i->source.end == UNKNOWN_LOCATION.end) {
|
||||
i->source = loc;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
block gen_noop() {
|
||||
block b = {0,0};
|
||||
return b;
|
||||
}
|
||||
|
||||
block gen_op_simple(opcode op) {
|
||||
assert(opcode_describe(op)->length == 1);
|
||||
return inst_block(inst_new(op));
|
||||
}
|
||||
|
||||
|
||||
block gen_const(jv constant) {
|
||||
assert(opcode_describe(LOADK)->flags & OP_HAS_CONSTANT);
|
||||
inst* i = inst_new(LOADK);
|
||||
i->imm.constant = constant;
|
||||
return inst_block(i);
|
||||
}
|
||||
|
||||
block gen_op_target(opcode op, block target) {
|
||||
assert(opcode_describe(op)->flags & OP_HAS_BRANCH);
|
||||
assert(target.last);
|
||||
inst* i = inst_new(op);
|
||||
i->imm.target = target.last;
|
||||
return inst_block(i);
|
||||
}
|
||||
|
||||
block gen_op_targetlater(opcode op) {
|
||||
assert(opcode_describe(op)->flags & OP_HAS_BRANCH);
|
||||
inst* i = inst_new(op);
|
||||
i->imm.target = 0;
|
||||
return inst_block(i);
|
||||
}
|
||||
void inst_set_target(block b, block target) {
|
||||
assert(block_is_single(b));
|
||||
assert(opcode_describe(b.first->op)->flags & OP_HAS_BRANCH);
|
||||
assert(target.last);
|
||||
b.first->imm.target = target.last;
|
||||
}
|
||||
|
||||
block gen_op_var_unbound(opcode op, const char* name) {
|
||||
assert(opcode_describe(op)->flags & OP_HAS_VARIABLE);
|
||||
inst* i = inst_new(op);
|
||||
i->symbol = strdup(name);
|
||||
return inst_block(i);
|
||||
}
|
||||
|
||||
block gen_op_var_bound(opcode op, block binder) {
|
||||
assert(block_is_single(binder));
|
||||
block b = gen_op_var_unbound(op, binder.first->symbol);
|
||||
b.first->bound_by = binder.first;
|
||||
return b;
|
||||
}
|
||||
|
||||
block gen_op_block_unbound(opcode op, const char* name) {
|
||||
assert(opcode_describe(op)->flags & OP_IS_CALL_PSEUDO);
|
||||
inst* i = inst_new(op);
|
||||
i->symbol = strdup(name);
|
||||
return inst_block(i);
|
||||
}
|
||||
|
||||
block gen_op_block_bound(opcode op, block binder) {
|
||||
assert(block_is_single(binder));
|
||||
block b = gen_op_block_unbound(op, binder.first->symbol);
|
||||
b.first->bound_by = binder.first;
|
||||
return b;
|
||||
}
|
||||
|
||||
static void inst_join(inst* a, inst* b) {
|
||||
assert(a && b);
|
||||
assert(!a->next);
|
||||
assert(!b->prev);
|
||||
a->next = b;
|
||||
b->prev = a;
|
||||
}
|
||||
|
||||
void block_append(block* b, block b2) {
|
||||
if (b2.first) {
|
||||
if (b->last) {
|
||||
inst_join(b->last, b2.first);
|
||||
} else {
|
||||
b->first = b2.first;
|
||||
}
|
||||
b->last = b2.last;
|
||||
}
|
||||
}
|
||||
|
||||
block block_join(block a, block b) {
|
||||
block c = a;
|
||||
block_append(&c, b);
|
||||
return c;
|
||||
}
|
||||
|
||||
int block_has_only_binders(block binders, int bindflags) {
|
||||
bindflags |= OP_HAS_BINDING;
|
||||
for (inst* curr = binders.first; curr; curr = curr->next) {
|
||||
if ((opcode_describe(curr->op)->flags & bindflags) != bindflags) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int block_bind_subblock(block binder, block body, int bindflags) {
|
||||
assert(block_is_single(binder));
|
||||
assert((opcode_describe(binder.first->op)->flags & bindflags) == bindflags);
|
||||
assert(binder.first->symbol);
|
||||
assert(binder.first->bound_by == 0 || binder.first->bound_by == binder.first);
|
||||
|
||||
binder.first->bound_by = binder.first;
|
||||
int nrefs = 0;
|
||||
for (inst* i = body.first; i; i = i->next) {
|
||||
int flags = opcode_describe(i->op)->flags;
|
||||
if ((flags & bindflags) == bindflags &&
|
||||
i->bound_by == 0 &&
|
||||
!strcmp(i->symbol, binder.first->symbol)) {
|
||||
// bind this instruction
|
||||
i->bound_by = binder.first;
|
||||
nrefs++;
|
||||
}
|
||||
// binding recurses into closures
|
||||
nrefs += block_bind_subblock(binder, i->subfn, bindflags);
|
||||
// binding recurses into argument list
|
||||
nrefs += block_bind_subblock(binder, i->arglist, bindflags);
|
||||
}
|
||||
return nrefs;
|
||||
}
|
||||
|
||||
static void block_bind_each(block binder, block body, int bindflags) {
|
||||
assert(block_has_only_binders(binder, bindflags));
|
||||
bindflags |= OP_HAS_BINDING;
|
||||
for (inst* curr = binder.first; curr; curr = curr->next) {
|
||||
block_bind_subblock(inst_block(curr), body, bindflags);
|
||||
}
|
||||
}
|
||||
|
||||
block block_bind(block binder, block body, int bindflags) {
|
||||
block_bind_each(binder, body, bindflags);
|
||||
return block_join(binder, body);
|
||||
}
|
||||
|
||||
block block_bind_referenced(block binder, block body, int bindflags) {
|
||||
assert(block_has_only_binders(binder, bindflags));
|
||||
bindflags |= OP_HAS_BINDING;
|
||||
block refd = gen_noop();
|
||||
for (inst* curr; (curr = block_take(&binder));) {
|
||||
block b = inst_block(curr);
|
||||
if (block_bind_subblock(b, body, bindflags)) {
|
||||
refd = BLOCK(refd, b);
|
||||
} else {
|
||||
block_free(b);
|
||||
}
|
||||
}
|
||||
return block_join(refd, body);
|
||||
}
|
||||
|
||||
block gen_function(const char* name, block formals, block body) {
|
||||
block_bind_each(formals, body, OP_IS_CALL_PSEUDO);
|
||||
inst* i = inst_new(CLOSURE_CREATE);
|
||||
i->subfn = body;
|
||||
i->symbol = strdup(name);
|
||||
i->arglist = formals;
|
||||
block b = inst_block(i);
|
||||
block_bind_subblock(b, b, OP_IS_CALL_PSEUDO | OP_HAS_BINDING);
|
||||
return b;
|
||||
}
|
||||
|
||||
block gen_lambda(block body) {
|
||||
return gen_function("@lambda", gen_noop(), body);
|
||||
}
|
||||
|
||||
block gen_call(const char* name, block args) {
|
||||
block b = gen_op_block_unbound(CALL_JQ, name);
|
||||
b.first->arglist = args;
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
block gen_subexp(block a) {
|
||||
return BLOCK(gen_op_simple(SUBEXP_BEGIN), a, gen_op_simple(SUBEXP_END));
|
||||
}
|
||||
|
||||
block gen_both(block a, block b) {
|
||||
block jump = gen_op_targetlater(JUMP);
|
||||
block fork = gen_op_target(FORK, jump);
|
||||
block c = BLOCK(fork, a, jump, b);
|
||||
inst_set_target(jump, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
block gen_collect(block expr) {
|
||||
block array_var = block_bind(gen_op_var_unbound(STOREV, "collect"),
|
||||
gen_noop(), OP_HAS_VARIABLE);
|
||||
block c = BLOCK(gen_op_simple(DUP), gen_const(jv_array()), array_var);
|
||||
|
||||
block tail = BLOCK(gen_op_var_bound(APPEND, array_var),
|
||||
gen_op_simple(BACKTRACK));
|
||||
|
||||
return BLOCK(c,
|
||||
gen_op_target(FORK, tail),
|
||||
expr,
|
||||
tail,
|
||||
gen_op_var_bound(LOADVN, array_var));
|
||||
}
|
||||
|
||||
block gen_reduce(const char* varname, block source, block init, block body) {
|
||||
block res_var = block_bind(gen_op_var_unbound(STOREV, "reduce"),
|
||||
gen_noop(), OP_HAS_VARIABLE);
|
||||
|
||||
block loop = BLOCK(gen_op_simple(DUP),
|
||||
source,
|
||||
block_bind(gen_op_var_unbound(STOREV, varname),
|
||||
BLOCK(gen_op_var_bound(LOADVN, res_var),
|
||||
body,
|
||||
gen_op_var_bound(STOREV, res_var)),
|
||||
OP_HAS_VARIABLE),
|
||||
gen_op_simple(BACKTRACK));
|
||||
return BLOCK(gen_op_simple(DUP),
|
||||
init,
|
||||
res_var,
|
||||
gen_op_target(FORK, loop),
|
||||
loop,
|
||||
gen_op_var_bound(LOADVN, res_var));
|
||||
}
|
||||
|
||||
block gen_definedor(block a, block b) {
|
||||
// var found := false
|
||||
block found_var = block_bind(gen_op_var_unbound(STOREV, "found"),
|
||||
gen_noop(), OP_HAS_VARIABLE);
|
||||
block init = BLOCK(gen_op_simple(DUP), gen_const(jv_false()), found_var);
|
||||
|
||||
// if found, backtrack. Otherwise execute b
|
||||
block backtrack = gen_op_simple(BACKTRACK);
|
||||
block tail = BLOCK(gen_op_simple(DUP),
|
||||
gen_op_var_bound(LOADV, found_var),
|
||||
gen_op_target(JUMP_F, backtrack),
|
||||
backtrack,
|
||||
gen_op_simple(POP),
|
||||
b);
|
||||
|
||||
// try again
|
||||
block if_notfound = gen_op_simple(BACKTRACK);
|
||||
|
||||
// found := true, produce result
|
||||
block if_found = BLOCK(gen_op_simple(DUP),
|
||||
gen_const(jv_true()),
|
||||
gen_op_var_bound(STOREV, found_var),
|
||||
gen_op_target(JUMP, tail));
|
||||
|
||||
return BLOCK(init,
|
||||
gen_op_target(FORK, if_notfound),
|
||||
a,
|
||||
gen_op_target(JUMP_F, if_found),
|
||||
if_found,
|
||||
if_notfound,
|
||||
tail);
|
||||
}
|
||||
|
||||
block gen_condbranch(block iftrue, block iffalse) {
|
||||
iftrue = BLOCK(iftrue, gen_op_target(JUMP, iffalse));
|
||||
return BLOCK(gen_op_target(JUMP_F, iftrue), iftrue, iffalse);
|
||||
}
|
||||
|
||||
block gen_and(block a, block b) {
|
||||
// a and b = if a then (if b then true else false) else false
|
||||
return BLOCK(gen_op_simple(DUP), a,
|
||||
gen_condbranch(BLOCK(gen_op_simple(POP),
|
||||
b,
|
||||
gen_condbranch(gen_const(jv_true()),
|
||||
gen_const(jv_false()))),
|
||||
BLOCK(gen_op_simple(POP), gen_const(jv_false()))));
|
||||
}
|
||||
|
||||
block gen_or(block a, block b) {
|
||||
// a or b = if a then true else (if b then true else false)
|
||||
return BLOCK(gen_op_simple(DUP), a,
|
||||
gen_condbranch(BLOCK(gen_op_simple(POP), gen_const(jv_true())),
|
||||
BLOCK(gen_op_simple(POP),
|
||||
b,
|
||||
gen_condbranch(gen_const(jv_true()),
|
||||
gen_const(jv_false())))));
|
||||
}
|
||||
|
||||
block gen_var_binding(block var, const char* name, block body) {
|
||||
return BLOCK(gen_op_simple(DUP), var,
|
||||
block_bind(gen_op_var_unbound(STOREV, name),
|
||||
body, OP_HAS_VARIABLE));
|
||||
}
|
||||
|
||||
block gen_cond(block cond, block iftrue, block iffalse) {
|
||||
return BLOCK(gen_op_simple(DUP), cond,
|
||||
gen_condbranch(BLOCK(gen_op_simple(POP), iftrue),
|
||||
BLOCK(gen_op_simple(POP), iffalse)));
|
||||
}
|
||||
|
||||
block gen_cbinding(const struct cfunction* cfunctions, int ncfunctions, block code) {
|
||||
for (int cfunc=0; cfunc<ncfunctions; cfunc++) {
|
||||
inst* i = inst_new(CLOSURE_CREATE_C);
|
||||
i->imm.cfunc = &cfunctions[cfunc];
|
||||
i->symbol = strdup(i->imm.cfunc->name);
|
||||
code = block_bind(inst_block(i), code, OP_IS_CALL_PSEUDO);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static uint16_t nesting_level(struct bytecode* bc, inst* target) {
|
||||
uint16_t level = 0;
|
||||
assert(bc && target->compiled);
|
||||
while (bc && target->compiled != bc) {
|
||||
level++;
|
||||
bc = bc->parent;
|
||||
}
|
||||
assert(bc && bc == target->compiled);
|
||||
return level;
|
||||
}
|
||||
|
||||
static int count_cfunctions(block b) {
|
||||
int n = 0;
|
||||
for (inst* i = b.first; i; i = i->next) {
|
||||
if (i->op == CLOSURE_CREATE_C) n++;
|
||||
n += count_cfunctions(i->subfn);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
// Expands call instructions into a calling sequence
|
||||
static int expand_call_arglist(struct locfile* locations, block* b) {
|
||||
int errors = 0;
|
||||
block ret = gen_noop();
|
||||
for (inst* curr; (curr = block_take(b));) {
|
||||
if (opcode_describe(curr->op)->flags & OP_HAS_BINDING) {
|
||||
if (!curr->bound_by) {
|
||||
locfile_locate(locations, curr->source, "error: %s is not defined", curr->symbol);
|
||||
errors++;
|
||||
// don't process this instruction if it's not well-defined
|
||||
ret = BLOCK(ret, inst_block(curr));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
block prelude = gen_noop();
|
||||
if (curr->op == CALL_JQ) {
|
||||
int actual_args = 0, desired_args = 0;
|
||||
// We expand the argument list as a series of instructions
|
||||
switch (curr->bound_by->op) {
|
||||
default: assert(0 && "Unknown function type"); break;
|
||||
case CLOSURE_CREATE:
|
||||
case CLOSURE_PARAM: {
|
||||
block callargs = gen_noop();
|
||||
for (inst* i; (i = block_take(&curr->arglist));) {
|
||||
assert(opcode_describe(i->op)->flags & OP_IS_CALL_PSEUDO);
|
||||
block b = inst_block(i);
|
||||
switch (i->op) {
|
||||
default: assert(0 && "Unknown type of parameter"); break;
|
||||
case CLOSURE_REF:
|
||||
block_append(&callargs, b);
|
||||
break;
|
||||
case CLOSURE_CREATE:
|
||||
block_append(&prelude, b);
|
||||
block_append(&callargs, gen_op_block_bound(CLOSURE_REF, b));
|
||||
break;
|
||||
}
|
||||
actual_args++;
|
||||
}
|
||||
curr->imm.intval = actual_args;
|
||||
curr->arglist = callargs;
|
||||
|
||||
if (curr->bound_by->op == CLOSURE_CREATE) {
|
||||
for (inst* i = curr->bound_by->arglist.first; i; i = i->next) {
|
||||
assert(i->op == CLOSURE_PARAM);
|
||||
desired_args++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CLOSURE_CREATE_C: {
|
||||
for (inst* i; (i = block_take(&curr->arglist)); ) {
|
||||
assert(i->op == CLOSURE_CREATE); // FIXME
|
||||
block body = i->subfn;
|
||||
i->subfn = gen_noop();
|
||||
inst_free(i);
|
||||
// arguments should be pushed in reverse order, prepend them to prelude
|
||||
errors += expand_call_arglist(locations, &body);
|
||||
prelude = BLOCK(gen_subexp(body), prelude);
|
||||
actual_args++;
|
||||
}
|
||||
assert(curr->op == CALL_JQ);
|
||||
curr->op = CALL_BUILTIN;
|
||||
curr->imm.intval = actual_args + 1 /* include the implicit input in arg count */;
|
||||
assert(curr->bound_by->op == CLOSURE_CREATE_C);
|
||||
desired_args = curr->bound_by->imm.cfunc->nargs - 1;
|
||||
assert(!curr->arglist.first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (actual_args != desired_args) {
|
||||
locfile_locate(locations, curr->source,
|
||||
"error: %s arguments to %s (expected %d but got %d)",
|
||||
actual_args > desired_args ? "too many" : "too few",
|
||||
curr->symbol, desired_args, actual_args);
|
||||
errors++;
|
||||
}
|
||||
|
||||
}
|
||||
ret = BLOCK(ret, prelude, inst_block(curr));
|
||||
}
|
||||
*b = ret;
|
||||
return errors;
|
||||
}
|
||||
|
||||
static int compile(struct locfile* locations, struct bytecode* bc, block b) {
|
||||
int errors = 0;
|
||||
int pos = 0;
|
||||
int var_frame_idx = 0;
|
||||
bc->nsubfunctions = 0;
|
||||
errors += expand_call_arglist(locations, &b);
|
||||
b = BLOCK(b, gen_op_simple(RET));
|
||||
jv localnames = jv_array();
|
||||
for (inst* curr = b.first; curr; curr = curr->next) {
|
||||
if (!curr->next) assert(curr == b.last);
|
||||
int length = opcode_describe(curr->op)->length;
|
||||
if (curr->op == CALL_JQ) {
|
||||
for (inst* arg = curr->arglist.first; arg; arg = arg->next) {
|
||||
length += 2;
|
||||
}
|
||||
}
|
||||
pos += length;
|
||||
curr->bytecode_pos = pos;
|
||||
curr->compiled = bc;
|
||||
|
||||
assert(curr->op != CLOSURE_REF && curr->op != CLOSURE_PARAM);
|
||||
|
||||
if ((opcode_describe(curr->op)->flags & OP_HAS_VARIABLE) &&
|
||||
curr->bound_by == curr) {
|
||||
curr->imm.intval = var_frame_idx++;
|
||||
localnames = jv_array_append(localnames, jv_string(curr->symbol));
|
||||
}
|
||||
|
||||
if (curr->op == CLOSURE_CREATE) {
|
||||
assert(curr->bound_by == curr);
|
||||
curr->imm.intval = bc->nsubfunctions++;
|
||||
}
|
||||
if (curr->op == CLOSURE_CREATE_C) {
|
||||
assert(curr->bound_by == curr);
|
||||
int idx = bc->globals->ncfunctions++;
|
||||
bc->globals->cfunc_names = jv_array_append(bc->globals->cfunc_names,
|
||||
jv_string(curr->symbol));
|
||||
bc->globals->cfunctions[idx] = *curr->imm.cfunc;
|
||||
curr->imm.intval = idx;
|
||||
}
|
||||
}
|
||||
bc->debuginfo = jv_object_set(bc->debuginfo, jv_string("locals"), localnames);
|
||||
if (bc->nsubfunctions) {
|
||||
bc->subfunctions = jv_mem_alloc(sizeof(struct bytecode*) * bc->nsubfunctions);
|
||||
for (inst* curr = b.first; curr; curr = curr->next) {
|
||||
if (curr->op == CLOSURE_CREATE) {
|
||||
struct bytecode* subfn = jv_mem_alloc(sizeof(struct bytecode));
|
||||
bc->subfunctions[curr->imm.intval] = subfn;
|
||||
subfn->globals = bc->globals;
|
||||
subfn->parent = bc;
|
||||
subfn->nclosures = 0;
|
||||
subfn->debuginfo = jv_object_set(jv_object(), jv_string("name"), jv_string(curr->symbol));
|
||||
jv params = jv_array();
|
||||
for (inst* param = curr->arglist.first; param; param = param->next) {
|
||||
assert(param->op == CLOSURE_PARAM);
|
||||
assert(param->bound_by == param);
|
||||
param->imm.intval = subfn->nclosures++;
|
||||
param->compiled = subfn;
|
||||
params = jv_array_append(params, jv_string(param->symbol));
|
||||
}
|
||||
subfn->debuginfo = jv_object_set(subfn->debuginfo, jv_string("params"), params);
|
||||
errors += compile(locations, subfn, curr->subfn);
|
||||
curr->subfn = gen_noop();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bc->subfunctions = 0;
|
||||
}
|
||||
bc->codelen = pos;
|
||||
uint16_t* code = jv_mem_alloc(sizeof(uint16_t) * bc->codelen);
|
||||
bc->code = code;
|
||||
pos = 0;
|
||||
jv constant_pool = jv_array();
|
||||
int maxvar = -1;
|
||||
if (!errors) for (inst* curr = b.first; curr; curr = curr->next) {
|
||||
const struct opcode_description* op = opcode_describe(curr->op);
|
||||
if (op->length == 0)
|
||||
continue;
|
||||
code[pos++] = curr->op;
|
||||
assert(curr->op != CLOSURE_REF && curr->op != CLOSURE_PARAM);
|
||||
if (curr->op == CALL_BUILTIN) {
|
||||
assert(curr->bound_by->op == CLOSURE_CREATE_C);
|
||||
assert(!curr->arglist.first);
|
||||
code[pos++] = (uint16_t)curr->imm.intval;
|
||||
code[pos++] = curr->bound_by->imm.intval;
|
||||
} else if (curr->op == CALL_JQ) {
|
||||
assert(curr->bound_by->op == CLOSURE_CREATE ||
|
||||
curr->bound_by->op == CLOSURE_PARAM);
|
||||
code[pos++] = (uint16_t)curr->imm.intval;
|
||||
code[pos++] = nesting_level(bc, curr->bound_by);
|
||||
code[pos++] = curr->bound_by->imm.intval |
|
||||
(curr->bound_by->op == CLOSURE_CREATE ? ARG_NEWCLOSURE : 0);
|
||||
for (inst* arg = curr->arglist.first; arg; arg = arg->next) {
|
||||
assert(arg->op == CLOSURE_REF && arg->bound_by->op == CLOSURE_CREATE);
|
||||
code[pos++] = nesting_level(bc, arg->bound_by);
|
||||
code[pos++] = arg->bound_by->imm.intval | ARG_NEWCLOSURE;
|
||||
}
|
||||
} else if (op->flags & OP_HAS_CONSTANT) {
|
||||
code[pos++] = jv_array_length(jv_copy(constant_pool));
|
||||
constant_pool = jv_array_append(constant_pool, jv_copy(curr->imm.constant));
|
||||
} else if (op->flags & OP_HAS_VARIABLE) {
|
||||
code[pos++] = nesting_level(bc, curr->bound_by);
|
||||
uint16_t var = (uint16_t)curr->bound_by->imm.intval;
|
||||
code[pos++] = var;
|
||||
if (var > maxvar) maxvar = var;
|
||||
} else if (op->flags & OP_HAS_BRANCH) {
|
||||
assert(curr->imm.target->bytecode_pos != -1);
|
||||
assert(curr->imm.target->bytecode_pos > pos); // only forward branches
|
||||
code[pos] = curr->imm.target->bytecode_pos - (pos + 1);
|
||||
pos++;
|
||||
} else if (op->length > 1) {
|
||||
assert(0 && "codegen not implemented for this operation");
|
||||
}
|
||||
}
|
||||
bc->constants = constant_pool;
|
||||
bc->nlocals = maxvar + 2; // FIXME: frames of size zero?
|
||||
block_free(b);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int block_compile(block b, struct locfile* locations, struct bytecode** out) {
|
||||
struct bytecode* bc = jv_mem_alloc(sizeof(struct bytecode));
|
||||
bc->parent = 0;
|
||||
bc->nclosures = 0;
|
||||
bc->globals = jv_mem_alloc(sizeof(struct symbol_table));
|
||||
int ncfunc = count_cfunctions(b);
|
||||
bc->globals->ncfunctions = 0;
|
||||
bc->globals->cfunctions = jv_mem_alloc(sizeof(struct cfunction) * ncfunc);
|
||||
bc->globals->cfunc_names = jv_array();
|
||||
bc->debuginfo = jv_object_set(jv_object(), jv_string("name"), jv_null());
|
||||
int nerrors = compile(locations, bc, b);
|
||||
assert(bc->globals->ncfunctions == ncfunc);
|
||||
if (nerrors > 0) {
|
||||
bytecode_free(bc);
|
||||
*out = 0;
|
||||
} else {
|
||||
*out = bc;
|
||||
}
|
||||
return nerrors;
|
||||
}
|
||||
|
||||
void block_free(block b) {
|
||||
struct inst* next;
|
||||
for (struct inst* curr = b.first; curr; curr = next) {
|
||||
next = curr->next;
|
||||
inst_free(curr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#ifndef COMPILE_H
|
||||
#define COMPILE_H
|
||||
#include <stdint.h>
|
||||
#include "jv.h"
|
||||
#include "opcode.h"
|
||||
#include "locfile.h"
|
||||
|
||||
struct bytecode;
|
||||
struct symbol_table;
|
||||
struct cfunction;
|
||||
|
||||
struct inst;
|
||||
typedef struct inst inst;
|
||||
|
||||
|
||||
typedef struct block {
|
||||
inst* first;
|
||||
inst* last;
|
||||
} block;
|
||||
|
||||
block gen_location(location, block);
|
||||
|
||||
block gen_noop();
|
||||
block gen_op_simple(opcode op);
|
||||
block gen_const(jv constant);
|
||||
block gen_op_target(opcode op, block target);
|
||||
block gen_op_var_unbound(opcode op, const char* name);
|
||||
block gen_op_var_bound(opcode op, block binder);
|
||||
block gen_op_block_unbound(opcode op, const char* name);
|
||||
|
||||
block gen_function(const char* name, block formals, block body);
|
||||
block gen_lambda(block body);
|
||||
block gen_call(const char* name, block body);
|
||||
block gen_subexp(block a);
|
||||
block gen_both(block a, block b);
|
||||
block gen_collect(block expr);
|
||||
block gen_reduce(const char* varname, block source, block init, block body);
|
||||
block gen_definedor(block a, block b);
|
||||
block gen_condbranch(block iftrue, block iffalse);
|
||||
block gen_and(block a, block b);
|
||||
block gen_or(block a, block b);
|
||||
|
||||
block gen_var_binding(block var, const char* name, block body);
|
||||
|
||||
block gen_cond(block cond, block iftrue, block iffalse);
|
||||
|
||||
block gen_cbinding(const struct cfunction* functions, int nfunctions, block b);
|
||||
|
||||
void block_append(block* b, block b2);
|
||||
block block_join(block a, block b);
|
||||
int block_has_only_binders(block, int bindflags);
|
||||
block block_bind(block binder, block body, int bindflags);
|
||||
block block_bind_referenced(block binder, block body, int bindflags);
|
||||
|
||||
int block_compile(block, struct locfile*, struct bytecode**);
|
||||
|
||||
void block_free(block);
|
||||
|
||||
|
||||
|
||||
// Here's some horrible preprocessor gunk so that code
|
||||
// sequences can be contructed as BLOCK(block1, block2, block3)
|
||||
|
||||
#define BLOCK_1(b1) (b1)
|
||||
#define BLOCK_2(b1,b2) (block_join((b1),(b2)))
|
||||
#define BLOCK_3(b1,b2,b3) (block_join(BLOCK_2(b1,b2),(b3)))
|
||||
#define BLOCK_4(b1,b2,b3,b4) (block_join(BLOCK_3(b1,b2,b3),(b4)))
|
||||
#define BLOCK_5(b1,b2,b3,b4,b5) (block_join(BLOCK_4(b1,b2,b3,b4),(b5)))
|
||||
#define BLOCK_6(b1,b2,b3,b4,b5,b6) (block_join(BLOCK_5(b1,b2,b3,b4,b5),(b6)))
|
||||
#define BLOCK_7(b1,b2,b3,b4,b5,b6,b7) (block_join(BLOCK_6(b1,b2,b3,b4,b5,b6),(b7)))
|
||||
|
||||
#define BLOCK_IDX(_1,_2,_3,_4,_5,_6,_7,NAME,...) NAME
|
||||
#define BLOCK(...) \
|
||||
BLOCK_IDX(__VA_ARGS__, BLOCK_7, BLOCK_6, BLOCK_5, BLOCK_4, BLOCK_3, BLOCK_2, BLOCK_1)(__VA_ARGS__)
|
||||
|
||||
|
||||
#endif
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
|
||||
`char[]'. */
|
||||
#undef YYTEXT_POINTER
|
||||
@@ -1,10 +0,0 @@
|
||||
config.guess
|
||||
config.sub
|
||||
compile
|
||||
depcomp
|
||||
install-sh
|
||||
ltmain.sh
|
||||
missing
|
||||
ylwrap
|
||||
test-driver
|
||||
ar-lib
|
||||
Executable
+343
@@ -0,0 +1,343 @@
|
||||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-03-05.13; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
|
||||
# Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
Executable
+708
@@ -0,0 +1,708 @@
|
||||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2012-03-27.16; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
|
||||
# 2011, 2012 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' "$nl" < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# '$object: dependent.h' and one to simply 'dependent.h:'.
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
|
||||
# However on
|
||||
# $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\':
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
# tcc 0.9.26 (FIXME still under development at the moment of writing)
|
||||
# will emit a similar output, but also prepend the continuation lines
|
||||
# with horizontal tabulation characters.
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form 'foo.o: dependent.h',
|
||||
# or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# '$object: dependent.h' and one to simply 'dependent.h:'.
|
||||
sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \
|
||||
< "$tmpdepfile" > "$depfile"
|
||||
sed '
|
||||
s/[ '"$tab"'][ '"$tab"']*/ /g
|
||||
s/^ *//
|
||||
s/ *\\*$//
|
||||
s/^[^:]*: *//
|
||||
/^$/d
|
||||
/:$/d
|
||||
s/$/ :/
|
||||
' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mechanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test "$stat" = 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' "$nl" < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
Executable
+527
@@ -0,0 +1,527 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2011-01-19.21; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for `test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@@ -1,2 +0,0 @@
|
||||
libtool.m4
|
||||
lt*.m4
|
||||
@@ -1,9 +0,0 @@
|
||||
dnl AC_CHECK_MATH_FUNC(func)
|
||||
AC_DEFUN([AC_CHECK_MATH_FUNC], [
|
||||
AC_LANG(C)
|
||||
AC_CHECK_LIB([m],[$1],[
|
||||
m4_define([ac_tr_func], [HAVE_]m4_toupper($1))
|
||||
AC_DEFINE(ac_tr_func, 1, [Define if you have the $1 math function.])
|
||||
],[
|
||||
])
|
||||
])
|
||||
@@ -1,8 +0,0 @@
|
||||
dnl Shamelessly stolen from Heimdal
|
||||
dnl
|
||||
dnl Look for function in any of the specified libraries
|
||||
dnl
|
||||
|
||||
dnl AC_FIND_FUNC_NO_LIBS(func, libraries, includes, arguments, extra libs, extra args)
|
||||
AC_DEFUN([AC_FIND_FUNC_NO_LIBS], [
|
||||
AC_FIND_FUNC_NO_LIBS2([$1], ["" $2], [$3], [$4], [$5], [$6])])
|
||||
@@ -1,62 +0,0 @@
|
||||
dnl Shamelessly stolen from Heimdal
|
||||
dnl
|
||||
dnl Look for function in any of the specified libraries
|
||||
dnl
|
||||
|
||||
dnl AC_FIND_FUNC_NO_LIBS2(func, libraries, includes, arguments, extra libs, extra args)
|
||||
AC_DEFUN([AC_FIND_FUNC_NO_LIBS2], [
|
||||
|
||||
AC_MSG_CHECKING([for $1])
|
||||
AC_CACHE_VAL(ac_cv_funclib_$1,
|
||||
[
|
||||
if eval "test \"\$ac_cv_func_$1\" != yes" ; then
|
||||
ac_save_LIBS="$LIBS"
|
||||
for ac_lib in $2; do
|
||||
case "$ac_lib" in
|
||||
"") ;;
|
||||
yes) ac_lib="" ;;
|
||||
no) continue ;;
|
||||
-l*) ;;
|
||||
*) ac_lib="-l$ac_lib" ;;
|
||||
esac
|
||||
LIBS="$6 $ac_lib $5 $ac_save_LIBS"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[$3]],[[$1($4)]])],[eval "if test -n \"$ac_lib\";then ac_cv_funclib_$1=$ac_lib; else ac_cv_funclib_$1=yes; fi";break])
|
||||
done
|
||||
eval "ac_cv_funclib_$1=\${ac_cv_funclib_$1-no}"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
])
|
||||
|
||||
eval "ac_res=\$ac_cv_funclib_$1"
|
||||
|
||||
if false; then
|
||||
AC_CHECK_FUNCS($1)
|
||||
dnl AC_CHECK_LIBS($2, foo)
|
||||
fi
|
||||
# $1
|
||||
eval "ac_tr_func=HAVE_[]upcase($1)"
|
||||
eval "ac_tr_lib=HAVE_LIB[]upcase($ac_res | sed -e 's/-l//')"
|
||||
eval "LIB_$1=$ac_res"
|
||||
|
||||
case "$ac_res" in
|
||||
yes)
|
||||
eval "ac_cv_func_$1=yes"
|
||||
eval "LIB_$1="
|
||||
AC_DEFINE_UNQUOTED($ac_tr_func, 1, [Define if the $1 function is available.])
|
||||
AC_MSG_RESULT([yes])
|
||||
;;
|
||||
no)
|
||||
eval "ac_cv_func_$1=no"
|
||||
eval "LIB_$1="
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
*)
|
||||
eval "ac_cv_func_$1=yes"
|
||||
eval "ac_cv_lib_`echo "$ac_res" | sed 's/-l//'`=yes"
|
||||
AC_DEFINE_UNQUOTED($ac_tr_func, 1, [Define if you have the $1 function.])
|
||||
AC_DEFINE_UNQUOTED($ac_tr_lib, 1, [Define if you have the $2 library.])
|
||||
AC_MSG_RESULT([yes, in $ac_res])
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(LIB_$1)
|
||||
])
|
||||
@@ -1,9 +0,0 @@
|
||||
dnl Shamelessly stolen from Heimdal
|
||||
dnl
|
||||
dnl AC_FIND_FUNC(func, libraries, includes, arguments)
|
||||
AC_DEFUN([AC_FIND_FUNC], [
|
||||
AC_FIND_FUNC_NO_LIBS([$1], [$2], [$3], [$4])
|
||||
if test -n "$LIB_$1"; then
|
||||
LIBS="$LIB_$1 $LIBS"
|
||||
fi
|
||||
])
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
dnl Shamelessly stolen from Heimdal
|
||||
AC_DEFUN([upcase],[`echo $1 | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`])dnl
|
||||
Executable
+331
@@ -0,0 +1,331 @@
|
||||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2012-01-06.13; # UTC
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
|
||||
# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
|
||||
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case $1 in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
autom4te touch the output file, or create a stub one
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
|
||||
\`g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# normalize program name to check for.
|
||||
program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program). This is about non-GNU programs, so use $1 not
|
||||
# $program.
|
||||
case $1 in
|
||||
lex*|yacc*)
|
||||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case $program in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case $f in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison*|yacc*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG=\${$#}
|
||||
case $LASTARG in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f y.tab.h; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if test ! -f y.tab.c; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex*|flex*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG=\${$#}
|
||||
case $LASTARG in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f lex.yy.c; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit $?
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# The file to touch is that specified with -o ...
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -z "$file"; then
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '
|
||||
/^@setfilename/{
|
||||
s/.* \([^ ]*\) *$/\1/
|
||||
p
|
||||
q
|
||||
}' $infile`
|
||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
fi
|
||||
# If the file does not exist, the user really needs makeinfo;
|
||||
# let's fail without touching anything.
|
||||
test -f $file || exit 1
|
||||
touch $file
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
Executable
+226
@@ -0,0 +1,226 @@
|
||||
#! /bin/sh
|
||||
# ylwrap - wrapper for lex/yacc invocations.
|
||||
|
||||
scriptversion=2011-08-25.18; # UTC
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005,
|
||||
# 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
#
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
case "$1" in
|
||||
'')
|
||||
echo "$0: No files given. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
--basedir)
|
||||
basedir=$2
|
||||
shift 2
|
||||
;;
|
||||
-h|--h*)
|
||||
cat <<\EOF
|
||||
Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
|
||||
|
||||
Wrapper for lex/yacc invocations, renaming files as desired.
|
||||
|
||||
INPUT is the input file
|
||||
OUTPUT is one file PROG generates
|
||||
DESIRED is the file we actually want instead of OUTPUT
|
||||
PROGRAM is program to run
|
||||
ARGS are passed to PROG
|
||||
|
||||
Any number of OUTPUT,DESIRED pairs may be used.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v|--v*)
|
||||
echo "ylwrap $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# The input.
|
||||
input="$1"
|
||||
shift
|
||||
case "$input" in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
# Absolute path; do nothing.
|
||||
;;
|
||||
*)
|
||||
# Relative path. Make it absolute.
|
||||
input="`pwd`/$input"
|
||||
;;
|
||||
esac
|
||||
|
||||
pairlist=
|
||||
while test "$#" -ne 0; do
|
||||
if test "$1" = "--"; then
|
||||
shift
|
||||
break
|
||||
fi
|
||||
pairlist="$pairlist $1"
|
||||
shift
|
||||
done
|
||||
|
||||
# The program to run.
|
||||
prog="$1"
|
||||
shift
|
||||
# Make any relative path in $prog absolute.
|
||||
case "$prog" in
|
||||
[\\/]* | ?:[\\/]*) ;;
|
||||
*[\\/]*) prog="`pwd`/$prog" ;;
|
||||
esac
|
||||
|
||||
# FIXME: add hostname here for parallel makes that run commands on
|
||||
# other machines. But that might take us over the 14-char limit.
|
||||
dirname=ylwrap$$
|
||||
do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
mkdir $dirname || exit 1
|
||||
|
||||
cd $dirname
|
||||
|
||||
case $# in
|
||||
0) "$prog" "$input" ;;
|
||||
*) "$prog" "$@" "$input" ;;
|
||||
esac
|
||||
ret=$?
|
||||
|
||||
if test $ret -eq 0; then
|
||||
set X $pairlist
|
||||
shift
|
||||
first=yes
|
||||
# Since DOS filename conventions don't allow two dots,
|
||||
# the DOS version of Bison writes out y_tab.c instead of y.tab.c
|
||||
# and y_tab.h instead of y.tab.h. Test to see if this is the case.
|
||||
y_tab_nodot="no"
|
||||
if test -f y_tab.c || test -f y_tab.h; then
|
||||
y_tab_nodot="yes"
|
||||
fi
|
||||
|
||||
# The directory holding the input.
|
||||
input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
|
||||
# Quote $INPUT_DIR so we can use it in a regexp.
|
||||
# FIXME: really we should care about more than `.' and `\'.
|
||||
input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
|
||||
|
||||
while test "$#" -ne 0; do
|
||||
from="$1"
|
||||
# Handle y_tab.c and y_tab.h output by DOS
|
||||
if test $y_tab_nodot = "yes"; then
|
||||
if test $from = "y.tab.c"; then
|
||||
from="y_tab.c"
|
||||
else
|
||||
if test $from = "y.tab.h"; then
|
||||
from="y_tab.h"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test -f "$from"; then
|
||||
# If $2 is an absolute path name, then just use that,
|
||||
# otherwise prepend `../'.
|
||||
case "$2" in
|
||||
[\\/]* | ?:[\\/]*) target="$2";;
|
||||
*) target="../$2";;
|
||||
esac
|
||||
|
||||
# We do not want to overwrite a header file if it hasn't
|
||||
# changed. This avoid useless recompilations. However the
|
||||
# parser itself (the first file) should always be updated,
|
||||
# because it is the destination of the .y.c rule in the
|
||||
# Makefile. Divert the output of all other files to a temporary
|
||||
# file so we can compare them to existing versions.
|
||||
if test $first = no; then
|
||||
realtarget="$target"
|
||||
target="tmp-`echo $target | sed s/.*[\\/]//g`"
|
||||
fi
|
||||
# Edit out `#line' or `#' directives.
|
||||
#
|
||||
# We don't want the resulting debug information to point at
|
||||
# an absolute srcdir; it is better for it to just mention the
|
||||
# .y file with no path.
|
||||
#
|
||||
# We want to use the real output file name, not yy.lex.c for
|
||||
# instance.
|
||||
#
|
||||
# We want the include guards to be adjusted too.
|
||||
FROM=`echo "$from" | sed \
|
||||
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
|
||||
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
|
||||
TARGET=`echo "$2" | sed \
|
||||
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
|
||||
-e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
|
||||
|
||||
sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
|
||||
-e "s,$FROM,$TARGET," "$from" >"$target" || ret=$?
|
||||
|
||||
# Check whether header files must be updated.
|
||||
if test $first = no; then
|
||||
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
|
||||
echo "$2" is unchanged
|
||||
rm -f "$target"
|
||||
else
|
||||
echo updating "$2"
|
||||
mv -f "$target" "$realtarget"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# A missing file is only an error for the first file. This
|
||||
# is a blatant hack to let us support using "yacc -d". If -d
|
||||
# is not specified, we don't want an error when the header
|
||||
# file is "missing".
|
||||
if test $first = yes; then
|
||||
ret=1
|
||||
fi
|
||||
fi
|
||||
shift
|
||||
shift
|
||||
first=no
|
||||
done
|
||||
else
|
||||
ret=$?
|
||||
fi
|
||||
|
||||
# Remove the directory.
|
||||
cd ..
|
||||
rm -rf $dirname
|
||||
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
+35
-258
@@ -1,289 +1,66 @@
|
||||
m4_define([jq_version], m4_esyscmd_s([scripts/version])))
|
||||
|
||||
AC_INIT([jq],[jq_version],[https://github.com/jqlang/jq/issues],[jq],[https://jqlang.org])
|
||||
AC_INIT([jq], [1.3], [mu@netsoc.tcd.ie],
|
||||
[jq], [http://stedolan.github.com/jq/])
|
||||
|
||||
dnl Created autoconf implementation thompson@dtosolutions, 26NOV12
|
||||
AC_PREREQ([2.65])
|
||||
AC_PREREQ([2.61])
|
||||
AC_CONFIG_AUX_DIR([config])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AM_INIT_AUTOMAKE([1.11.2 subdir-objects parallel-tests foreign -Wall])
|
||||
AM_INIT_AUTOMAKE([parallel-tests foreign])
|
||||
AM_SILENT_RULES([yes])
|
||||
AM_PROG_AR
|
||||
AM_MAINTAINER_MODE([disable])
|
||||
AC_PROG_CC
|
||||
m4_version_prereq([2.70], [], [AC_PROG_CC_STDC])
|
||||
AC_PROG_CC_STDC
|
||||
AC_PROG_CPP_WERROR
|
||||
AC_PROG_YACC
|
||||
AC_OBJEXT
|
||||
AC_EXEEXT
|
||||
LT_INIT([shared static win32-dll])
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
AC_SYS_LARGEFILE # issue 2167
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
dnl couldn't use AM_PROG_LEX as it doesn't support header files like the
|
||||
dnl AC_PROG_YACC macros...
|
||||
|
||||
dnl check bison version
|
||||
dnl
|
||||
dnl these program checks should probably be deleted
|
||||
dnl
|
||||
|
||||
if test "$USE_MAINTAINER_MODE" = yes; then
|
||||
if test "$YACC" != "bison -y"; then
|
||||
AC_MSG_CHECKING([bison version])
|
||||
AC_MSG_RESULT([not bison])
|
||||
else
|
||||
AX_PROG_BISON_VERSION([3],
|
||||
[],
|
||||
[AC_MSG_ERROR([You need bison version 3.0 or greater])])
|
||||
fi
|
||||
|
||||
AC_CHECK_PROGS(LEX, flex lex)
|
||||
AC_PROG_LEX
|
||||
if test "x$LEX" != xflex; then
|
||||
LEX="$SHELL $missing_dir/missing flex"
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(memmem)
|
||||
|
||||
AC_CHECK_HEADER("sys/cygwin.h", [have_cygwin=1;])
|
||||
AC_CHECK_HEADER("shlwapi.h",[have_shlwapi=1;])
|
||||
AM_CONDITIONAL([WIN32], [test "x$have_shlwapi" = x1 && test ! "x$have_cygwin" = x1])
|
||||
dnl Check for valgrind
|
||||
AC_CHECK_PROGS(valgrind_cmd, valgrind)
|
||||
if test "x$valgrind_cmd" = "x" ; then
|
||||
AC_MSG_WARN([valgrind is required to test jq.])
|
||||
fi
|
||||
|
||||
dnl Running tests with Valgrind is slow. It is faster to iterate on
|
||||
dnl code without Valgrind until tests pass, then enable Valgrind and
|
||||
dnl fix leaks.
|
||||
AC_ARG_ENABLE([valgrind],
|
||||
AS_HELP_STRING([--enable-valgrind],[enable Valgrind during testing]))
|
||||
|
||||
dnl Address sanitizer (ASan)
|
||||
AC_ARG_ENABLE([asan],
|
||||
AS_HELP_STRING([--enable-asan],[enable address sanitizer]))
|
||||
|
||||
dnl Undefined Behavior Sanitizer
|
||||
AC_ARG_ENABLE([ubsan],
|
||||
AS_HELP_STRING([--enable-ubsan],[enable undefined behavior sanitizer]))
|
||||
|
||||
dnl Code coverage
|
||||
AC_ARG_ENABLE([gcov],
|
||||
AS_HELP_STRING([--enable-gcov],[enable gcov code coverage tool]))
|
||||
|
||||
dnl Don't attempt to build docs if python deps aren't installed
|
||||
dnl Don't attempt to build docs if there's no Ruby lying around
|
||||
AC_ARG_ENABLE([docs],
|
||||
AS_HELP_STRING([--disable-docs],[do not build docs]), [], [enable_docs=yes])
|
||||
|
||||
dnl Don't attempt to build the error injection object (if there is no LD_PRELOAD support)
|
||||
AC_ARG_ENABLE([error-injection],
|
||||
AS_HELP_STRING([--enable-error-injection],[build and test with error injection]))
|
||||
|
||||
dnl Enable building all static
|
||||
AC_ARG_ENABLE([all-static],
|
||||
AS_HELP_STRING([--enable-all-static],[link jq with static libraries only]))
|
||||
|
||||
dnl find pipenv
|
||||
AC_ARG_VAR([PIPENV], [pipenv command])
|
||||
AC_CHECK_PROGS([PIPENV], pipenv)
|
||||
AC_HELP_STRING([--disable-docs], [don't build docs]))
|
||||
|
||||
AS_IF([test "x$enable_docs" != "xno"],[
|
||||
AC_CACHE_CHECK([for Python dependencies], [jq_cv_python_deps],[
|
||||
jq_cv_python_deps=yes
|
||||
AS_IF([test "x$PIPENV" = "x" || \
|
||||
! bmsg="`cd ${srcdir}/docs; LC_ALL=$LANG "$PIPENV" --venv`"],[
|
||||
jq_cv_python_deps=no
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([test "x$jq_cv_python_deps" != "xyes"], [
|
||||
AC_MSG_WARN([Error checking python dependencies: $bmsg
|
||||
AC_CHECK_PROGS(bundle_cmd, bundle)
|
||||
AS_IF([test "x$bundle_cmd" = "x" || \
|
||||
! ( cd ${srcdir}/docs; "$bundle_cmd" check 2>/dev/null )],[
|
||||
AC_MSG_WARN([no bundler])
|
||||
cat <<EOF
|
||||
*****************************************************************
|
||||
* Python dependencies for building jq documentation not found. *
|
||||
* Ruby dependencies for building jq documentation not found. *
|
||||
* You can still build, install and hack on jq, but the manpage *
|
||||
* will not be rebuilt and new manpage tests will not be run. *
|
||||
* will not be rebuilt and some of the tests won't run. *
|
||||
* See docs/README.md for how to install the docs dependencies. *
|
||||
*****************************************************************])
|
||||
enable_docs=no
|
||||
*****************************************************************
|
||||
EOF
|
||||
enable_docs=no
|
||||
])
|
||||
])
|
||||
|
||||
dnl Disable decNumber support
|
||||
AC_ARG_ENABLE([decnum],
|
||||
AS_HELP_STRING([--disable-decnum],[disable decnum support]))
|
||||
|
||||
AS_IF([test "x$enable_decnum" != "xno"],[
|
||||
AC_DEFINE([USE_DECNUM], 1, [Define to enable decnum support.])
|
||||
])
|
||||
|
||||
AM_CONDITIONAL([ENABLE_VALGRIND], [test "x$enable_valgrind" = xyes])
|
||||
AM_CONDITIONAL([ENABLE_ASAN], [test "x$enable_asan" = xyes])
|
||||
AM_CONDITIONAL([ENABLE_UBSAN], [test "x$enable_ubsan" = xyes])
|
||||
AM_CONDITIONAL([ENABLE_GCOV], [test "x$enable_gcov" = xyes])
|
||||
AM_CONDITIONAL([ENABLE_DOCS], [test "x$enable_docs" != xno])
|
||||
AM_CONDITIONAL([ENABLE_ERROR_INJECTION], [test "x$enable_error_injection" = xyes])
|
||||
AM_CONDITIONAL([ENABLE_ALL_STATIC], [test "x$enable_all_static" = xyes])
|
||||
AC_SUBST([BUNDLER], ["$bundle_cmd"])
|
||||
|
||||
dnl Find pthread, if we have it. We do this first because we may set -pthread on CFLAGS
|
||||
dnl which can cause various macros to be defined (__REENTRANT on Darwin, for example)
|
||||
AX_PTHREAD([
|
||||
AC_DEFINE([HAVE_PTHREAD], [1], [Define to enable POSIX threads support.])
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
CC="$PTHREAD_CC"
|
||||
])
|
||||
|
||||
AC_FUNC_ALLOCA
|
||||
|
||||
AC_FIND_FUNC([isatty], [c], [#include <unistd.h>], [0])
|
||||
AC_FIND_FUNC([_isatty], [c], [#include <io.h>], [0])
|
||||
AC_FIND_FUNC([strptime], [c], [#include <time.h>], [0, 0, 0])
|
||||
AC_FIND_FUNC([strftime], [c], [#include <time.h>], [0, 0, 0, 0])
|
||||
AC_FIND_FUNC([setenv], [c], [#include <stdlib.h>], [0, 0, 0])
|
||||
AC_FIND_FUNC([timegm], [c], [#include <time.h>], [0])
|
||||
AC_FIND_FUNC([gmtime_r], [c], [#include <time.h>], [0, 0])
|
||||
AC_FIND_FUNC([gmtime], [c], [#include <time.h>], [0])
|
||||
AC_FIND_FUNC([localtime_r], [c], [#include <time.h>], [0, 0])
|
||||
AC_FIND_FUNC([localtime], [c], [#include <time.h>], [0])
|
||||
AC_FIND_FUNC([gettimeofday], [c], [#include <sys/time.h>], [0, 0])
|
||||
AC_CHECK_MEMBER([struct tm.tm_gmtoff], [AC_DEFINE([HAVE_TM_TM_GMT_OFF],1,[Define to 1 if the system has the tm_gmt_off field in struct tm])],
|
||||
[], [[#include <time.h>]])
|
||||
AC_CHECK_MEMBER([struct tm.__tm_gmtoff], [AC_DEFINE([HAVE_TM___TM_GMT_OFF],1,[Define to 1 if the system has the __tm_gmt_off field in struct tm])],
|
||||
[], [[#include <time.h>]])
|
||||
AC_FIND_FUNC([setlocale], [c], [#include <locale.h>], [0,0])
|
||||
|
||||
dnl Figure out if we have the pthread functions we actually need
|
||||
AC_FIND_FUNC_NO_LIBS([pthread_key_create], [], [#include <pthread.h>], [NULL, NULL])
|
||||
AC_FIND_FUNC_NO_LIBS([pthread_once], [], [#include <pthread.h>], [NULL, NULL])
|
||||
AC_FIND_FUNC_NO_LIBS([atexit], [], [#include <stdlib.h>], [NULL])
|
||||
|
||||
dnl libm math.h functions
|
||||
AC_CHECK_MATH_FUNC(acos)
|
||||
AC_CHECK_MATH_FUNC(acosh)
|
||||
AC_CHECK_MATH_FUNC(asin)
|
||||
AC_CHECK_MATH_FUNC(asinh)
|
||||
AC_CHECK_MATH_FUNC(atan2)
|
||||
AC_CHECK_MATH_FUNC(atan)
|
||||
AC_CHECK_MATH_FUNC(atanh)
|
||||
AC_CHECK_MATH_FUNC(cbrt)
|
||||
AC_CHECK_MATH_FUNC(ceil)
|
||||
AC_CHECK_MATH_FUNC(copysign)
|
||||
AC_CHECK_MATH_FUNC(cos)
|
||||
AC_CHECK_MATH_FUNC(cosh)
|
||||
AC_CHECK_MATH_FUNC(drem)
|
||||
AC_CHECK_MATH_FUNC(erf)
|
||||
AC_CHECK_MATH_FUNC(erfc)
|
||||
AC_CHECK_MATH_FUNC(exp10)
|
||||
AC_CHECK_MATH_FUNC(__exp10) dnl macOS has an __exp10
|
||||
AC_CHECK_MATH_FUNC(exp2)
|
||||
AC_CHECK_MATH_FUNC(exp)
|
||||
AC_CHECK_MATH_FUNC(expm1)
|
||||
AC_CHECK_MATH_FUNC(fabs)
|
||||
AC_CHECK_MATH_FUNC(fdim)
|
||||
AC_CHECK_MATH_FUNC(floor)
|
||||
AC_CHECK_MATH_FUNC(fma)
|
||||
AC_CHECK_MATH_FUNC(fmax)
|
||||
AC_CHECK_MATH_FUNC(fmin)
|
||||
AC_CHECK_MATH_FUNC(fmod)
|
||||
AC_CHECK_MATH_FUNC(frexp)
|
||||
AC_CHECK_MATH_FUNC(gamma)
|
||||
AC_CHECK_MATH_FUNC(hypot)
|
||||
AC_CHECK_MATH_FUNC(j0)
|
||||
AC_CHECK_MATH_FUNC(j1)
|
||||
AC_CHECK_MATH_FUNC(jn)
|
||||
AC_CHECK_MATH_FUNC(ldexp)
|
||||
AC_CHECK_MATH_FUNC(lgamma)
|
||||
AC_CHECK_MATH_FUNC(log10)
|
||||
AC_CHECK_MATH_FUNC(log1p)
|
||||
AC_CHECK_MATH_FUNC(log2)
|
||||
AC_CHECK_MATH_FUNC(log)
|
||||
AC_CHECK_MATH_FUNC(logb)
|
||||
AC_CHECK_MATH_FUNC(modf)
|
||||
AC_CHECK_MATH_FUNC(lgamma_r)
|
||||
AC_CHECK_MATH_FUNC(nearbyint)
|
||||
AC_CHECK_MATH_FUNC(nextafter)
|
||||
AC_CHECK_MATH_FUNC(nexttoward)
|
||||
AC_CHECK_MATH_FUNC(pow)
|
||||
AC_CHECK_MATH_FUNC(remainder)
|
||||
AC_CHECK_MATH_FUNC(rint)
|
||||
AC_CHECK_MATH_FUNC(round)
|
||||
AC_CHECK_MATH_FUNC(scalb)
|
||||
AC_CHECK_MATH_FUNC(scalbln)
|
||||
AC_CHECK_MATH_FUNC(significand)
|
||||
dnl scalbn and ilogb are used on macos to replace significand if we don't have frexp
|
||||
AC_CHECK_MATH_FUNC(scalbn)
|
||||
AC_CHECK_MATH_FUNC(ilogb)
|
||||
|
||||
AC_CHECK_MATH_FUNC(sin)
|
||||
AC_CHECK_MATH_FUNC(sinh)
|
||||
AC_CHECK_MATH_FUNC(sqrt)
|
||||
AC_CHECK_MATH_FUNC(tan)
|
||||
AC_CHECK_MATH_FUNC(tanh)
|
||||
AC_CHECK_MATH_FUNC(tgamma)
|
||||
AC_CHECK_MATH_FUNC(trunc)
|
||||
AC_CHECK_MATH_FUNC(y0)
|
||||
AC_CHECK_MATH_FUNC(y1)
|
||||
AC_CHECK_MATH_FUNC(yn)
|
||||
|
||||
dnl Thread local storage
|
||||
have___thread=no
|
||||
AC_MSG_CHECKING(for thread-local storage)
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
static __thread int x ;
|
||||
int main () { x = 123; return x; }
|
||||
])], have___thread=yes)
|
||||
if test $have___thread = yes; then
|
||||
AC_DEFINE([HAVE___THREAD],1,[Define to 1 if the system supports __thread])
|
||||
fi
|
||||
AC_MSG_RESULT($have___thread)
|
||||
|
||||
AC_C_BIGENDIAN(
|
||||
AC_DEFINE([IEEE_MC68k], 1, [machine is bigendian]),
|
||||
AC_DEFINE([IEEE_8087], 1, [machine is littleendian]),
|
||||
AC_MSG_ERROR(unknown endianness),
|
||||
AC_MSG_ERROR(universal endianness not supported)
|
||||
)
|
||||
|
||||
dnl Oniguruma
|
||||
AC_ARG_WITH([oniguruma],
|
||||
[AS_HELP_STRING([--with-oniguruma=prefix],
|
||||
[try this for a non-standard install prefix of the oniguruma library])], ,
|
||||
[with_oniguruma=yes])
|
||||
|
||||
onig_CFLAGS=
|
||||
onig_LDFLAGS=
|
||||
build_oniguruma=no
|
||||
AS_IF([test "x$with_oniguruma" != xno], [
|
||||
save_CFLAGS="$CFLAGS"
|
||||
save_LDFLAGS="$LDFLAGS"
|
||||
AS_IF([test "x$with_oniguruma" != xyes], [
|
||||
AS_IF([test "x$with_oniguruma" = xbuiltin], [
|
||||
build_oniguruma=yes
|
||||
], [
|
||||
onig_CFLAGS="-I${with_oniguruma}/include"
|
||||
onig_LDFLAGS="-L${with_oniguruma}/lib"
|
||||
])
|
||||
])
|
||||
AS_IF([test "x$build_oniguruma" = xno], [
|
||||
# check for ONIGURUMA library, either in /usr or where requested
|
||||
CFLAGS="$CFLAGS $onig_CFLAGS"
|
||||
LDFLAGS="$LDFLAGS $onig_LDFLAGS"
|
||||
AC_CHECK_HEADER("oniguruma.h",
|
||||
AC_CHECK_LIB([onig],[onig_version]))
|
||||
# handle check results
|
||||
AS_IF([test "x$ac_cv_lib_onig_onig_version" != "xyes"], [
|
||||
build_oniguruma=yes
|
||||
AC_MSG_NOTICE([Oniguruma was not found. Will use the packaged oniguruma.])
|
||||
])
|
||||
])
|
||||
AS_IF([test "x$build_oniguruma" = xyes && test -f "${srcdir}/vendor/oniguruma/configure.ac" ], [
|
||||
onig_CFLAGS="-I${srcdir}/vendor/oniguruma/src"
|
||||
onig_LDFLAGS="-L${srcdir}/vendor/oniguruma/src -Wl,-rpath,${libdir}"
|
||||
AC_CONFIG_SUBDIRS([vendor/oniguruma])
|
||||
AC_DEFINE([HAVE_LIBONIG],1,[Define to 1 if the system includes libonig])
|
||||
])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
LDFLAGS="$save_LDFLAGS"
|
||||
])
|
||||
AC_SUBST(onig_CFLAGS)
|
||||
AC_SUBST(onig_LDFLAGS)
|
||||
|
||||
AM_CONDITIONAL([BUILD_ONIGURUMA], [test "x$build_oniguruma" = xyes])
|
||||
AM_CONDITIONAL([WITH_ONIGURUMA], [test "x$with_oniguruma" != xno])
|
||||
|
||||
AC_CONFIG_MACRO_DIRS([config/m4 m4])
|
||||
AC_CONFIG_FILES([Makefile libjq.pc])
|
||||
dnl AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
AM_INIT_AUTOMAKE([-Wall])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
.DS_Store
|
||||
.sass-cache
|
||||
output/*
|
||||
|
||||
# Autogenerated from public/css/base.scss
|
||||
public/css/base.css
|
||||
@@ -0,0 +1,6 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "rake"
|
||||
gem "bonsai"
|
||||
gem "maruku"
|
||||
gem "ronn"
|
||||
@@ -0,0 +1,63 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
POpen4 (0.1.4)
|
||||
Platform (>= 0.4.0)
|
||||
open4
|
||||
Platform (0.4.0)
|
||||
activesupport (3.2.12)
|
||||
i18n (~> 0.6)
|
||||
multi_json (~> 1.0)
|
||||
addressable (2.3.4)
|
||||
bonsai (1.4.8)
|
||||
activesupport (>= 3.0.3)
|
||||
builder (>= 3.0.0)
|
||||
i18n (>= 0.5.0)
|
||||
launchy (>= 0.3.7)
|
||||
liquid (>= 2.2.2)
|
||||
maruku (>= 0.6.0)
|
||||
rack
|
||||
sass
|
||||
sinatra (>= 1.0)
|
||||
tilt (>= 1.3)
|
||||
watch (>= 0.1.0)
|
||||
yui-compressor
|
||||
builder (3.2.0)
|
||||
hpricot (0.8.6)
|
||||
i18n (0.6.4)
|
||||
launchy (2.3.0)
|
||||
addressable (~> 2.3)
|
||||
liquid (2.5.0)
|
||||
maruku (0.6.1)
|
||||
syntax (>= 1.0.0)
|
||||
multi_json (1.7.3)
|
||||
mustache (0.99.4)
|
||||
open4 (1.3.0)
|
||||
rack (1.5.2)
|
||||
rack-protection (1.5.0)
|
||||
rack
|
||||
rake (10.0.3)
|
||||
rdiscount (2.0.7.2)
|
||||
ronn (0.7.3)
|
||||
hpricot (>= 0.8.2)
|
||||
mustache (>= 0.7.0)
|
||||
rdiscount (>= 1.5.8)
|
||||
sass (3.2.8)
|
||||
sinatra (1.4.2)
|
||||
rack (~> 1.5, >= 1.5.2)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (~> 1.3, >= 1.3.4)
|
||||
syntax (1.0.0)
|
||||
tilt (1.4.0)
|
||||
watch (0.1.0)
|
||||
yui-compressor (0.9.6)
|
||||
POpen4 (>= 0.1.4)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
bonsai
|
||||
maruku
|
||||
rake
|
||||
ronn
|
||||
@@ -1,14 +0,0 @@
|
||||
[[source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[packages]
|
||||
jinja2 = "*"
|
||||
pyyaml = "*"
|
||||
markdown = "*"
|
||||
lxml = "*"
|
||||
jsonschema = "*"
|
||||
importlib_resources = "*"
|
||||
Generated
-482
@@ -1,482 +0,0 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "14036c3c9f103c52a0c5a53346ef33c2fbef409697f9eb314da51ccdd3aa9fb2"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3",
|
||||
"sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==25.3.0"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
"sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000",
|
||||
"sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==8.7.0"
|
||||
},
|
||||
"importlib-resources": {
|
||||
"hashes": [
|
||||
"sha256:4cf94875a8368bd89531a756df9a9ebe1f150e0f885030b461237bc7f2d905f2",
|
||||
"sha256:d952faee11004c045f785bb5636e8f885bed30dc3c940d5d42798a2a4541c185"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.0.0"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d",
|
||||
"sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.6"
|
||||
},
|
||||
"jsonschema": {
|
||||
"hashes": [
|
||||
"sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4",
|
||||
"sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.23.0"
|
||||
},
|
||||
"jsonschema-specifications": {
|
||||
"hashes": [
|
||||
"sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272",
|
||||
"sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==2024.10.1"
|
||||
},
|
||||
"lxml": {
|
||||
"hashes": [
|
||||
"sha256:00b8686694423ddae324cf614e1b9659c2edb754de617703c3d29ff568448df5",
|
||||
"sha256:073eb6dcdf1f587d9b88c8c93528b57eccda40209cf9be549d469b942b41d70b",
|
||||
"sha256:09846782b1ef650b321484ad429217f5154da4d6e786636c38e434fa32e94e49",
|
||||
"sha256:0a01ce7d8479dce84fc03324e3b0c9c90b1ece9a9bb6a1b6c9025e7e4520e78c",
|
||||
"sha256:0be91891bdb06ebe65122aa6bf3fc94489960cf7e03033c6f83a90863b23c58b",
|
||||
"sha256:0cef4feae82709eed352cd7e97ae062ef6ae9c7b5dbe3663f104cd2c0e8d94ba",
|
||||
"sha256:0e108352e203c7afd0eb91d782582f00a0b16a948d204d4dec8565024fafeea5",
|
||||
"sha256:0ea0252b51d296a75f6118ed0d8696888e7403408ad42345d7dfd0d1e93309a7",
|
||||
"sha256:0fce1294a0497edb034cb416ad3e77ecc89b313cff7adbee5334e4dc0d11f422",
|
||||
"sha256:1320091caa89805df7dcb9e908add28166113dcd062590668514dbd510798c88",
|
||||
"sha256:142accb3e4d1edae4b392bd165a9abdee8a3c432a2cca193df995bc3886249c8",
|
||||
"sha256:14479c2ad1cb08b62bb941ba8e0e05938524ee3c3114644df905d2331c76cd57",
|
||||
"sha256:151d6c40bc9db11e960619d2bf2ec5829f0aaffb10b41dcf6ad2ce0f3c0b2325",
|
||||
"sha256:15a665ad90054a3d4f397bc40f73948d48e36e4c09f9bcffc7d90c87410e478a",
|
||||
"sha256:1a42b3a19346e5601d1b8296ff6ef3d76038058f311902edd574461e9c036982",
|
||||
"sha256:1af80c6316ae68aded77e91cd9d80648f7dd40406cef73df841aa3c36f6907c8",
|
||||
"sha256:1b717b00a71b901b4667226bba282dd462c42ccf618ade12f9ba3674e1fabc55",
|
||||
"sha256:1dc4ca99e89c335a7ed47d38964abcb36c5910790f9bd106f2a8fa2ee0b909d2",
|
||||
"sha256:20e16c08254b9b6466526bc1828d9370ee6c0d60a4b64836bc3ac2917d1e16df",
|
||||
"sha256:226046e386556a45ebc787871d6d2467b32c37ce76c2680f5c608e25823ffc84",
|
||||
"sha256:24974f774f3a78ac12b95e3a20ef0931795ff04dbb16db81a90c37f589819551",
|
||||
"sha256:24f6df5f24fc3385f622c0c9d63fe34604893bc1a5bdbb2dbf5870f85f9a404a",
|
||||
"sha256:27a9ded0f0b52098ff89dd4c418325b987feed2ea5cc86e8860b0f844285d740",
|
||||
"sha256:29f451a4b614a7b5b6c2e043d7b64a15bd8304d7e767055e8ab68387a8cacf4e",
|
||||
"sha256:2b31a3a77501d86d8ade128abb01082724c0dfd9524f542f2f07d693c9f1175f",
|
||||
"sha256:2c62891b1ea3094bb12097822b3d44b93fc6c325f2043c4d2736a8ff09e65f60",
|
||||
"sha256:2dc191e60425ad70e75a68c9fd90ab284df64d9cd410ba8d2b641c0c45bc006e",
|
||||
"sha256:31e63621e073e04697c1b2d23fcb89991790eef370ec37ce4d5d469f40924ed6",
|
||||
"sha256:32697d2ea994e0db19c1df9e40275ffe84973e4232b5c274f47e7c1ec9763cdd",
|
||||
"sha256:3a3178b4873df8ef9457a4875703488eb1622632a9cee6d76464b60e90adbfcd",
|
||||
"sha256:3b9c2754cef6963f3408ab381ea55f47dabc6f78f4b8ebb0f0b25cf1ac1f7609",
|
||||
"sha256:3d3c30ba1c9b48c68489dc1829a6eede9873f52edca1dda900066542528d6b20",
|
||||
"sha256:3e6d5557989cdc3ebb5302bbdc42b439733a841891762ded9514e74f60319ad6",
|
||||
"sha256:4025bf2884ac4370a3243c5aa8d66d3cb9e15d3ddd0af2d796eccc5f0244390e",
|
||||
"sha256:4291d3c409a17febf817259cb37bc62cb7eb398bcc95c1356947e2871911ae61",
|
||||
"sha256:4329422de653cdb2b72afa39b0aa04252fca9071550044904b2e7036d9d97fe4",
|
||||
"sha256:43d549b876ce64aa18b2328faff70f5877f8c6dede415f80a2f799d31644d776",
|
||||
"sha256:460508a4b07364d6abf53acaa0a90b6d370fafde5693ef37602566613a9b0779",
|
||||
"sha256:47fb24cc0f052f0576ea382872b3fc7e1f7e3028e53299ea751839418ade92a6",
|
||||
"sha256:48b4afaf38bf79109bb060d9016fad014a9a48fb244e11b94f74ae366a64d252",
|
||||
"sha256:497cab4d8254c2a90bf988f162ace2ddbfdd806fce3bda3f581b9d24c852e03c",
|
||||
"sha256:4aa412a82e460571fad592d0f93ce9935a20090029ba08eca05c614f99b0cc92",
|
||||
"sha256:4b7ce10634113651d6f383aa712a194179dcd496bd8c41e191cec2099fa09de5",
|
||||
"sha256:4cd915c0fb1bed47b5e6d6edd424ac25856252f09120e3e8ba5154b6b921860e",
|
||||
"sha256:4d885698f5019abe0de3d352caf9466d5de2baded00a06ef3f1216c1a58ae78f",
|
||||
"sha256:4f5322cf38fe0e21c2d73901abf68e6329dc02a4994e483adbcf92b568a09a54",
|
||||
"sha256:50441c9de951a153c698b9b99992e806b71c1f36d14b154592580ff4a9d0d877",
|
||||
"sha256:529024ab3a505fed78fe3cc5ddc079464e709f6c892733e3f5842007cec8ac6e",
|
||||
"sha256:53370c26500d22b45182f98847243efb518d268374a9570409d2e2276232fd37",
|
||||
"sha256:53d9469ab5460402c19553b56c3648746774ecd0681b1b27ea74d5d8a3ef5590",
|
||||
"sha256:56dbdbab0551532bb26c19c914848d7251d73edb507c3079d6805fa8bba5b706",
|
||||
"sha256:5a99d86351f9c15e4a901fc56404b485b1462039db59288b203f8c629260a142",
|
||||
"sha256:5cca36a194a4eb4e2ed6be36923d3cffd03dcdf477515dea687185506583d4c9",
|
||||
"sha256:5f11a1526ebd0dee85e7b1e39e39a0cc0d9d03fb527f56d8457f6df48a10dc0c",
|
||||
"sha256:61c7bbf432f09ee44b1ccaa24896d21075e533cd01477966a5ff5a71d88b2f56",
|
||||
"sha256:639978bccb04c42677db43c79bdaa23785dc7f9b83bfd87570da8207872f1ce5",
|
||||
"sha256:63e7968ff83da2eb6fdda967483a7a023aa497d85ad8f05c3ad9b1f2e8c84987",
|
||||
"sha256:664cdc733bc87449fe781dbb1f309090966c11cc0c0cd7b84af956a02a8a4729",
|
||||
"sha256:67ed8a40665b84d161bae3181aa2763beea3747f748bca5874b4af4d75998f87",
|
||||
"sha256:67f779374c6b9753ae0a0195a892a1c234ce8416e4448fe1e9f34746482070a7",
|
||||
"sha256:6854f8bd8a1536f8a1d9a3655e6354faa6406621cf857dc27b681b69860645c7",
|
||||
"sha256:696ea9e87442467819ac22394ca36cb3d01848dad1be6fac3fb612d3bd5a12cf",
|
||||
"sha256:6ef80aeac414f33c24b3815ecd560cee272786c3adfa5f31316d8b349bfade28",
|
||||
"sha256:72ac9762a9f8ce74c9eed4a4e74306f2f18613a6b71fa065495a67ac227b3056",
|
||||
"sha256:75133890e40d229d6c5837b0312abbe5bac1c342452cf0e12523477cd3aa21e7",
|
||||
"sha256:7605c1c32c3d6e8c990dd28a0970a3cbbf1429d5b92279e37fda05fb0c92190e",
|
||||
"sha256:773e27b62920199c6197130632c18fb7ead3257fce1ffb7d286912e56ddb79e0",
|
||||
"sha256:795f61bcaf8770e1b37eec24edf9771b307df3af74d1d6f27d812e15a9ff3872",
|
||||
"sha256:79d5bfa9c1b455336f52343130b2067164040604e41f6dc4d8313867ed540079",
|
||||
"sha256:7a62cc23d754bb449d63ff35334acc9f5c02e6dae830d78dab4dd12b78a524f4",
|
||||
"sha256:7be701c24e7f843e6788353c055d806e8bd8466b52907bafe5d13ec6a6dbaecd",
|
||||
"sha256:7ca56ebc2c474e8f3d5761debfd9283b8b18c76c4fc0967b74aeafba1f5647f9",
|
||||
"sha256:7ce1a171ec325192c6a636b64c94418e71a1964f56d002cc28122fceff0b6121",
|
||||
"sha256:891f7f991a68d20c75cb13c5c9142b2a3f9eb161f1f12a9489c82172d1f133c0",
|
||||
"sha256:8f82125bc7203c5ae8633a7d5d20bcfdff0ba33e436e4ab0abc026a53a8960b7",
|
||||
"sha256:91505d3ddebf268bb1588eb0f63821f738d20e1e7f05d3c647a5ca900288760b",
|
||||
"sha256:942a5d73f739ad7c452bf739a62a0f83e2578afd6b8e5406308731f4ce78b16d",
|
||||
"sha256:9454b8d8200ec99a224df8854786262b1bd6461f4280064c807303c642c05e76",
|
||||
"sha256:9459e6892f59ecea2e2584ee1058f5d8f629446eab52ba2305ae13a32a059530",
|
||||
"sha256:9776af1aad5a4b4a1317242ee2bea51da54b2a7b7b48674be736d463c999f37d",
|
||||
"sha256:97dac543661e84a284502e0cf8a67b5c711b0ad5fb661d1bd505c02f8cf716d7",
|
||||
"sha256:98a3912194c079ef37e716ed228ae0dcb960992100461b704aea4e93af6b0bb9",
|
||||
"sha256:9b4a3bd174cc9cdaa1afbc4620c049038b441d6ba07629d89a83b408e54c35cd",
|
||||
"sha256:9c886b481aefdf818ad44846145f6eaf373a20d200b5ce1a5c8e1bc2d8745410",
|
||||
"sha256:9ceaf423b50ecfc23ca00b7f50b64baba85fb3fb91c53e2c9d00bc86150c7e40",
|
||||
"sha256:a11a96c3b3f7551c8a8109aa65e8594e551d5a84c76bf950da33d0fb6dfafab7",
|
||||
"sha256:a3bcdde35d82ff385f4ede021df801b5c4a5bcdfb61ea87caabcebfc4945dc1b",
|
||||
"sha256:a7fb111eef4d05909b82152721a59c1b14d0f365e2be4c742a473c5d7372f4f5",
|
||||
"sha256:a81e1196f0a5b4167a8dafe3a66aa67c4addac1b22dc47947abd5d5c7a3f24b5",
|
||||
"sha256:a8c9b7f16b63e65bbba889acb436a1034a82d34fa09752d754f88d708eca80e1",
|
||||
"sha256:a8ef956fce64c8551221f395ba21d0724fed6b9b6242ca4f2f7beb4ce2f41997",
|
||||
"sha256:ab339536aa798b1e17750733663d272038bf28069761d5be57cb4a9b0137b4f8",
|
||||
"sha256:ac7ba71f9561cd7d7b55e1ea5511543c0282e2b6450f122672a2694621d63b7e",
|
||||
"sha256:aea53d51859b6c64e7c51d522c03cc2c48b9b5d6172126854cc7f01aa11f52bc",
|
||||
"sha256:aea7c06667b987787c7d1f5e1dfcd70419b711cdb47d6b4bb4ad4b76777a0563",
|
||||
"sha256:aefe1a7cb852fa61150fcb21a8c8fcea7b58c4cb11fbe59c97a0a4b31cae3c8c",
|
||||
"sha256:b0989737a3ba6cf2a16efb857fb0dfa20bc5c542737fddb6d893fde48be45433",
|
||||
"sha256:b108134b9667bcd71236c5a02aad5ddd073e372fb5d48ea74853e009fe38acb6",
|
||||
"sha256:b12cb6527599808ada9eb2cd6e0e7d3d8f13fe7bbb01c6311255a15ded4c7ab4",
|
||||
"sha256:b5aff6f3e818e6bdbbb38e5967520f174b18f539c2b9de867b1e7fde6f8d95a4",
|
||||
"sha256:b67319b4aef1a6c56576ff544b67a2a6fbd7eaee485b241cabf53115e8908b8f",
|
||||
"sha256:b7c86884ad23d61b025989d99bfdd92a7351de956e01c61307cb87035960bcb1",
|
||||
"sha256:b92b69441d1bd39f4940f9eadfa417a25862242ca2c396b406f9272ef09cdcaa",
|
||||
"sha256:bcb7a1096b4b6b24ce1ac24d4942ad98f983cd3810f9711bcd0293f43a9d8b9f",
|
||||
"sha256:bda3ea44c39eb74e2488297bb39d47186ed01342f0022c8ff407c250ac3f498e",
|
||||
"sha256:be2ba4c3c5b7900246a8f866580700ef0d538f2ca32535e991027bdaba944063",
|
||||
"sha256:c5681160758d3f6ac5b4fea370495c48aac0989d6a0f01bb9a72ad8ef5ab75c4",
|
||||
"sha256:c5d32f5284012deaccd37da1e2cd42f081feaa76981f0eaa474351b68df813c5",
|
||||
"sha256:c6364038c519dffdbe07e3cf42e6a7f8b90c275d4d1617a69bb59734c1a2d571",
|
||||
"sha256:c70e93fba207106cb16bf852e421c37bbded92acd5964390aad07cb50d60f5cf",
|
||||
"sha256:ca755eebf0d9e62d6cb013f1261e510317a41bf4650f22963474a663fdfe02aa",
|
||||
"sha256:cccd007d5c95279e529c146d095f1d39ac05139de26c098166c4beb9374b0f4d",
|
||||
"sha256:ce31158630a6ac85bddd6b830cffd46085ff90498b397bd0a259f59d27a12188",
|
||||
"sha256:ce9c671845de9699904b1e9df95acfe8dfc183f2310f163cdaa91a3535af95de",
|
||||
"sha256:d12832e1dbea4be280b22fd0ea7c9b87f0d8fc51ba06e92dc62d52f804f78ebd",
|
||||
"sha256:d2ed1b3cb9ff1c10e6e8b00941bb2e5bb568b307bfc6b17dffbbe8be5eecba86",
|
||||
"sha256:d5663bc1b471c79f5c833cffbc9b87d7bf13f87e055a5c86c363ccd2348d7e82",
|
||||
"sha256:d90b729fd2732df28130c064aac9bb8aff14ba20baa4aee7bd0795ff1187545f",
|
||||
"sha256:dc0af80267edc68adf85f2a5d9be1cdf062f973db6790c1d065e45025fa26140",
|
||||
"sha256:de5b4e1088523e2b6f730d0509a9a813355b7f5659d70eb4f319c76beea2e250",
|
||||
"sha256:de6f6bb8a7840c7bf216fb83eec4e2f79f7325eca8858167b68708b929ab2172",
|
||||
"sha256:df53330a3bff250f10472ce96a9af28628ff1f4efc51ccba351a8820bca2a8ba",
|
||||
"sha256:e094ec83694b59d263802ed03a8384594fcce477ce484b0cbcd0008a211ca751",
|
||||
"sha256:e794f698ae4c5084414efea0f5cc9f4ac562ec02d66e1484ff822ef97c2cadff",
|
||||
"sha256:e7bc6df34d42322c5289e37e9971d6ed114e3776b45fa879f734bded9d1fea9c",
|
||||
"sha256:eaf24066ad0b30917186420d51e2e3edf4b0e2ea68d8cd885b14dc8afdcf6556",
|
||||
"sha256:ecf4c4b83f1ab3d5a7ace10bafcb6f11df6156857a3c418244cef41ca9fa3e44",
|
||||
"sha256:ef5a7178fcc73b7d8c07229e89f8eb45b2908a9238eb90dcfc46571ccf0383b8",
|
||||
"sha256:f5cb182f6396706dc6cc1896dd02b1c889d644c081b0cdec38747573db88a7d7",
|
||||
"sha256:fa0e294046de09acd6146be0ed6727d1f42ded4ce3ea1e9a19c11b6774eea27c",
|
||||
"sha256:fb54f7c6bafaa808f27166569b1511fc42701a7713858dddc08afdde9746849e",
|
||||
"sha256:fd3be6481ef54b8cfd0e1e953323b7aa9d9789b94842d0e5b142ef4bb7999539"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==5.4.0"
|
||||
},
|
||||
"markdown": {
|
||||
"hashes": [
|
||||
"sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc",
|
||||
"sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==3.8"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4",
|
||||
"sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30",
|
||||
"sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0",
|
||||
"sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9",
|
||||
"sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396",
|
||||
"sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13",
|
||||
"sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028",
|
||||
"sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca",
|
||||
"sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557",
|
||||
"sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832",
|
||||
"sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0",
|
||||
"sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b",
|
||||
"sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579",
|
||||
"sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a",
|
||||
"sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c",
|
||||
"sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff",
|
||||
"sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c",
|
||||
"sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22",
|
||||
"sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094",
|
||||
"sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb",
|
||||
"sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e",
|
||||
"sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5",
|
||||
"sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a",
|
||||
"sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d",
|
||||
"sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a",
|
||||
"sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b",
|
||||
"sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8",
|
||||
"sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225",
|
||||
"sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c",
|
||||
"sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144",
|
||||
"sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f",
|
||||
"sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87",
|
||||
"sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d",
|
||||
"sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93",
|
||||
"sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf",
|
||||
"sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158",
|
||||
"sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84",
|
||||
"sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb",
|
||||
"sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48",
|
||||
"sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171",
|
||||
"sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c",
|
||||
"sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6",
|
||||
"sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd",
|
||||
"sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d",
|
||||
"sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1",
|
||||
"sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d",
|
||||
"sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca",
|
||||
"sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a",
|
||||
"sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29",
|
||||
"sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe",
|
||||
"sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798",
|
||||
"sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c",
|
||||
"sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8",
|
||||
"sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f",
|
||||
"sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f",
|
||||
"sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a",
|
||||
"sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178",
|
||||
"sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0",
|
||||
"sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79",
|
||||
"sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430",
|
||||
"sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==3.0.2"
|
||||
},
|
||||
"pkgutil-resolve-name": {
|
||||
"hashes": [
|
||||
"sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174",
|
||||
"sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"
|
||||
],
|
||||
"markers": "python_version < '3.9'",
|
||||
"version": "==1.3.10"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc",
|
||||
"sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741",
|
||||
"sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206",
|
||||
"sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27",
|
||||
"sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595",
|
||||
"sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62",
|
||||
"sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98",
|
||||
"sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696",
|
||||
"sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d",
|
||||
"sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867",
|
||||
"sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47",
|
||||
"sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486",
|
||||
"sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6",
|
||||
"sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3",
|
||||
"sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007",
|
||||
"sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938",
|
||||
"sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c",
|
||||
"sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735",
|
||||
"sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d",
|
||||
"sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba",
|
||||
"sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8",
|
||||
"sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5",
|
||||
"sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd",
|
||||
"sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3",
|
||||
"sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0",
|
||||
"sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515",
|
||||
"sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c",
|
||||
"sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c",
|
||||
"sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924",
|
||||
"sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34",
|
||||
"sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43",
|
||||
"sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859",
|
||||
"sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673",
|
||||
"sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a",
|
||||
"sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab",
|
||||
"sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa",
|
||||
"sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c",
|
||||
"sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585",
|
||||
"sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d",
|
||||
"sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==6.0.1"
|
||||
},
|
||||
"referencing": {
|
||||
"hashes": [
|
||||
"sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa",
|
||||
"sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==0.36.2"
|
||||
},
|
||||
"rpds-py": {
|
||||
"hashes": [
|
||||
"sha256:0047638c3aa0dbcd0ab99ed1e549bbf0e142c9ecc173b6492868432d8989a046",
|
||||
"sha256:006f4342fe729a368c6df36578d7a348c7c716be1da0a1a0f86e3021f8e98724",
|
||||
"sha256:041f00419e1da7a03c46042453598479f45be3d787eb837af382bfc169c0db33",
|
||||
"sha256:04ecf5c1ff4d589987b4d9882872f80ba13da7d42427234fce8f22efb43133bc",
|
||||
"sha256:04f2b712a2206e13800a8136b07aaedc23af3facab84918e7aa89e4be0260032",
|
||||
"sha256:0aeb3329c1721c43c58cae274d7d2ca85c1690d89485d9c63a006cb79a85771a",
|
||||
"sha256:0e374c0ce0ca82e5b67cd61fb964077d40ec177dd2c4eda67dba130de09085c7",
|
||||
"sha256:0f00c16e089282ad68a3820fd0c831c35d3194b7cdc31d6e469511d9bffc535c",
|
||||
"sha256:174e46569968ddbbeb8a806d9922f17cd2b524aa753b468f35b97ff9c19cb718",
|
||||
"sha256:1b221c2457d92a1fb3c97bee9095c874144d196f47c038462ae6e4a14436f7bc",
|
||||
"sha256:208b3a70a98cf3710e97cabdc308a51cd4f28aa6e7bb11de3d56cd8b74bab98d",
|
||||
"sha256:20f2712bd1cc26a3cc16c5a1bfee9ed1abc33d4cdf1aabd297fe0eb724df4272",
|
||||
"sha256:24795c099453e3721fda5d8ddd45f5dfcc8e5a547ce7b8e9da06fecc3832e26f",
|
||||
"sha256:2a0f156e9509cee987283abd2296ec816225145a13ed0391df8f71bf1d789e2d",
|
||||
"sha256:2b2356688e5d958c4d5cb964af865bea84db29971d3e563fb78e46e20fe1848b",
|
||||
"sha256:2c13777ecdbbba2077670285dd1fe50828c8742f6a4119dbef6f83ea13ad10fb",
|
||||
"sha256:2d3ee4615df36ab8eb16c2507b11e764dcc11fd350bbf4da16d09cda11fcedef",
|
||||
"sha256:2d53747da70a4e4b17f559569d5f9506420966083a31c5fbd84e764461c4444b",
|
||||
"sha256:32bab0a56eac685828e00cc2f5d1200c548f8bc11f2e44abf311d6b548ce2e45",
|
||||
"sha256:34d90ad8c045df9a4259c47d2e16a3f21fdb396665c94520dbfe8766e62187a4",
|
||||
"sha256:369d9c6d4c714e36d4a03957b4783217a3ccd1e222cdd67d464a3a479fc17796",
|
||||
"sha256:3a55fc10fdcbf1a4bd3c018eea422c52cf08700cf99c28b5cb10fe97ab77a0d3",
|
||||
"sha256:3d2d8e4508e15fc05b31285c4b00ddf2e0eb94259c2dc896771966a163122a0c",
|
||||
"sha256:3fab5f4a2c64a8fb64fc13b3d139848817a64d467dd6ed60dcdd6b479e7febc9",
|
||||
"sha256:43dba99f00f1d37b2a0265a259592d05fcc8e7c19d140fe51c6e6f16faabeb1f",
|
||||
"sha256:44d51febb7a114293ffd56c6cf4736cb31cd68c0fddd6aa303ed09ea5a48e029",
|
||||
"sha256:493fe54318bed7d124ce272fc36adbf59d46729659b2c792e87c3b95649cdee9",
|
||||
"sha256:4b28e5122829181de1898c2c97f81c0b3246d49f585f22743a1246420bb8d399",
|
||||
"sha256:4cd031e63bc5f05bdcda120646a0d32f6d729486d0067f09d79c8db5368f4586",
|
||||
"sha256:528927e63a70b4d5f3f5ccc1fa988a35456eb5d15f804d276709c33fc2f19bda",
|
||||
"sha256:564c96b6076a98215af52f55efa90d8419cc2ef45d99e314fddefe816bc24f91",
|
||||
"sha256:5db385bacd0c43f24be92b60c857cf760b7f10d8234f4bd4be67b5b20a7c0b6b",
|
||||
"sha256:5ef877fa3bbfb40b388a5ae1cb00636a624690dcb9a29a65267054c9ea86d88a",
|
||||
"sha256:5f6e3cec44ba05ee5cbdebe92d052f69b63ae792e7d05f1020ac5e964394080c",
|
||||
"sha256:5fc13b44de6419d1e7a7e592a4885b323fbc2f46e1f22151e3a8ed3b8b920405",
|
||||
"sha256:60748789e028d2a46fc1c70750454f83c6bdd0d05db50f5ae83e2db500b34da5",
|
||||
"sha256:60d9b630c8025b9458a9d114e3af579a2c54bd32df601c4581bd054e85258143",
|
||||
"sha256:619ca56a5468f933d940e1bf431c6f4e13bef8e688698b067ae68eb4f9b30e3a",
|
||||
"sha256:630d3d8ea77eabd6cbcd2ea712e1c5cecb5b558d39547ac988351195db433f6c",
|
||||
"sha256:63981feca3f110ed132fd217bf7768ee8ed738a55549883628ee3da75bb9cb78",
|
||||
"sha256:66420986c9afff67ef0c5d1e4cdc2d0e5262f53ad11e4f90e5e22448df485bf0",
|
||||
"sha256:675269d407a257b8c00a6b58205b72eec8231656506c56fd429d924ca00bb350",
|
||||
"sha256:6a4a535013aeeef13c5532f802708cecae8d66c282babb5cd916379b72110cf7",
|
||||
"sha256:6a727fd083009bc83eb83d6950f0c32b3c94c8b80a9b667c87f4bd1274ca30ba",
|
||||
"sha256:6e1daf5bf6c2be39654beae83ee6b9a12347cb5aced9a29eecf12a2d25fff664",
|
||||
"sha256:6eea559077d29486c68218178ea946263b87f1c41ae7f996b1f30a983c476a5a",
|
||||
"sha256:75a810b7664c17f24bf2ffd7f92416c00ec84b49bb68e6a0d93e542406336b56",
|
||||
"sha256:772cc1b2cd963e7e17e6cc55fe0371fb9c704d63e44cacec7b9b7f523b78919e",
|
||||
"sha256:78884d155fd15d9f64f5d6124b486f3d3f7fd7cd71a78e9670a0f6f6ca06fb2d",
|
||||
"sha256:79e8d804c2ccd618417e96720ad5cd076a86fa3f8cb310ea386a3e6229bae7d1",
|
||||
"sha256:7e80d375134ddb04231a53800503752093dbb65dad8dabacce2c84cccc78e964",
|
||||
"sha256:8097b3422d020ff1c44effc40ae58e67d93e60d540a65649d2cdaf9466030791",
|
||||
"sha256:8205ee14463248d3349131bb8099efe15cd3ce83b8ef3ace63c7e976998e7124",
|
||||
"sha256:8212ff58ac6dfde49946bea57474a386cca3f7706fc72c25b772b9ca4af6b79e",
|
||||
"sha256:823e74ab6fbaa028ec89615ff6acb409e90ff45580c45920d4dfdddb069f2120",
|
||||
"sha256:84e0566f15cf4d769dade9b366b7b87c959be472c92dffb70462dd0844d7cbad",
|
||||
"sha256:896c41007931217a343eff197c34513c154267636c8056fb409eafd494c3dcdc",
|
||||
"sha256:8aa362811ccdc1f8dadcc916c6d47e554169ab79559319ae9fae7d7752d0d60c",
|
||||
"sha256:8b3b397eefecec8e8e39fa65c630ef70a24b09141a6f9fc17b3c3a50bed6b50e",
|
||||
"sha256:8ebc7e65ca4b111d928b669713865f021b7773350eeac4a31d3e70144297baba",
|
||||
"sha256:9168764133fd919f8dcca2ead66de0105f4ef5659cbb4fa044f7014bed9a1797",
|
||||
"sha256:921ae54f9ecba3b6325df425cf72c074cd469dea843fb5743a26ca7fb2ccb149",
|
||||
"sha256:92558d37d872e808944c3c96d0423b8604879a3d1c86fdad508d7ed91ea547d5",
|
||||
"sha256:951cc481c0c395c4a08639a469d53b7d4afa252529a085418b82a6b43c45c240",
|
||||
"sha256:998c01b8e71cf051c28f5d6f1187abbdf5cf45fc0efce5da6c06447cba997034",
|
||||
"sha256:9abc80fe8c1f87218db116016de575a7998ab1629078c90840e8d11ab423ee25",
|
||||
"sha256:9be4f99bee42ac107870c61dfdb294d912bf81c3c6d45538aad7aecab468b6b7",
|
||||
"sha256:9c39438c55983d48f4bb3487734d040e22dad200dab22c41e331cee145e7a50d",
|
||||
"sha256:9d7e8ce990ae17dda686f7e82fd41a055c668e13ddcf058e7fb5e9da20b57793",
|
||||
"sha256:9ea7f4174d2e4194289cb0c4e172d83e79a6404297ff95f2875cf9ac9bced8ba",
|
||||
"sha256:a18fc371e900a21d7392517c6f60fe859e802547309e94313cd8181ad9db004d",
|
||||
"sha256:a36b452abbf29f68527cf52e181fced56685731c86b52e852053e38d8b60bc8d",
|
||||
"sha256:a5b66d1b201cc71bc3081bc2f1fc36b0c1f268b773e03bbc39066651b9e18391",
|
||||
"sha256:a824d2c7a703ba6daaca848f9c3d5cb93af0505be505de70e7e66829affd676e",
|
||||
"sha256:a88c0d17d039333a41d9bf4616bd062f0bd7aa0edeb6cafe00a2fc2a804e944f",
|
||||
"sha256:aa6800adc8204ce898c8a424303969b7aa6a5e4ad2789c13f8648739830323b7",
|
||||
"sha256:aad911555286884be1e427ef0dc0ba3929e6821cbeca2194b13dc415a462c7fd",
|
||||
"sha256:afc6e35f344490faa8276b5f2f7cbf71f88bc2cda4328e00553bd451728c571f",
|
||||
"sha256:b9a4df06c35465ef4d81799999bba810c68d29972bf1c31db61bfdb81dd9d5bb",
|
||||
"sha256:bb2954155bb8f63bb19d56d80e5e5320b61d71084617ed89efedb861a684baea",
|
||||
"sha256:bbc4362e06f950c62cad3d4abf1191021b2ffaf0b31ac230fbf0526453eee75e",
|
||||
"sha256:c0145295ca415668420ad142ee42189f78d27af806fcf1f32a18e51d47dd2052",
|
||||
"sha256:c30ff468163a48535ee7e9bf21bd14c7a81147c0e58a36c1078289a8ca7af0bd",
|
||||
"sha256:c347a20d79cedc0a7bd51c4d4b7dbc613ca4e65a756b5c3e57ec84bd43505b47",
|
||||
"sha256:c43583ea8517ed2e780a345dd9960896afc1327e8cf3ac8239c167530397440d",
|
||||
"sha256:c61a2cb0085c8783906b2f8b1f16a7e65777823c7f4d0a6aaffe26dc0d358dd9",
|
||||
"sha256:c9ca89938dff18828a328af41ffdf3902405a19f4131c88e22e776a8e228c5a8",
|
||||
"sha256:cc31e13ce212e14a539d430428cd365e74f8b2d534f8bc22dd4c9c55b277b875",
|
||||
"sha256:cdabcd3beb2a6dca7027007473d8ef1c3b053347c76f685f5f060a00327b8b65",
|
||||
"sha256:cf86f72d705fc2ef776bb7dd9e5fbba79d7e1f3e258bf9377f8204ad0fc1c51e",
|
||||
"sha256:d09dc82af2d3c17e7dd17120b202a79b578d79f2b5424bda209d9966efeed114",
|
||||
"sha256:d3aa13bdf38630da298f2e0d77aca967b200b8cc1473ea05248f6c5e9c9bdb44",
|
||||
"sha256:d69d003296df4840bd445a5d15fa5b6ff6ac40496f956a221c4d1f6f7b4bc4d9",
|
||||
"sha256:d6e109a454412ab82979c5b1b3aee0604eca4bbf9a02693bb9df027af2bfa91a",
|
||||
"sha256:d8551e733626afec514b5d15befabea0dd70a343a9f23322860c4f16a9430205",
|
||||
"sha256:d8754d872a5dfc3c5bf9c0e059e8107451364a30d9fd50f1f1a85c4fb9481164",
|
||||
"sha256:d8f9a6e7fd5434817526815f09ea27f2746c4a51ee11bb3439065f5fc754db58",
|
||||
"sha256:dbcbb6db5582ea33ce46a5d20a5793134b5365110d84df4e30b9d37c6fd40ad3",
|
||||
"sha256:e0f3ef95795efcd3b2ec3fe0a5bcfb5dadf5e3996ea2117427e524d4fbf309c6",
|
||||
"sha256:e13ae74a8a3a0c2f22f450f773e35f893484fcfacb00bb4344a7e0f4f48e1f97",
|
||||
"sha256:e274f62cbd274359eff63e5c7e7274c913e8e09620f6a57aae66744b3df046d6",
|
||||
"sha256:e838bf2bb0b91ee67bf2b889a1a841e5ecac06dd7a2b1ef4e6151e2ce155c7ae",
|
||||
"sha256:e8acd55bd5b071156bae57b555f5d33697998752673b9de554dd82f5b5352727",
|
||||
"sha256:e8e5ab32cf9eb3647450bc74eb201b27c185d3857276162c101c0f8c6374e098",
|
||||
"sha256:ebcb786b9ff30b994d5969213a8430cbb984cdd7ea9fd6df06663194bd3c450c",
|
||||
"sha256:ebea2821cdb5f9fef44933617be76185b80150632736f3d76e54829ab4a3b4d1",
|
||||
"sha256:ed0ef550042a8dbcd657dfb284a8ee00f0ba269d3f2286b0493b15a5694f9fe8",
|
||||
"sha256:eda5c1e2a715a4cbbca2d6d304988460942551e4e5e3b7457b50943cd741626d",
|
||||
"sha256:f5c0ed12926dec1dfe7d645333ea59cf93f4d07750986a586f511c0bc61fe103",
|
||||
"sha256:f6016bd950be4dcd047b7475fdf55fb1e1f59fc7403f387be0e8123e4a576d30",
|
||||
"sha256:f9e0057a509e096e47c87f753136c9b10d7a91842d8042c2ee6866899a717c0d",
|
||||
"sha256:fc1c892b1ec1f8cbd5da8de287577b455e388d9c328ad592eabbdcb6fc93bee5",
|
||||
"sha256:fc2c1e1b00f88317d9de6b2c2b39b012ebbfe35fe5e7bef980fd2a91f6100a07",
|
||||
"sha256:fd822f019ccccd75c832deb7aa040bb02d70a92eb15a2f16c7987b7ad4ee8d83"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==0.24.0"
|
||||
},
|
||||
"typing-extensions": {
|
||||
"hashes": [
|
||||
"sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b",
|
||||
"sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==4.13.0"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4",
|
||||
"sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"
|
||||
],
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==3.21.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
+14
-14
@@ -2,24 +2,24 @@ Documentation
|
||||
=============
|
||||
|
||||
The jq website, manpages and some of the tests are generated from this
|
||||
directory. The manual is a YAML file in `content/manual`.
|
||||
directory. The directory holds a [Bonsai](http://tinytree.info)
|
||||
website, and the manual is a YAML file in `content/3.manual`.
|
||||
|
||||
To build the documentation (including building the jq manpage), you'll
|
||||
need `python3` and `pipenv`. You can install `pipenv` like so:
|
||||
need a working Ruby setup. The easiest way to get one is to install
|
||||
RVM and Ruby 1.9.3 like so:
|
||||
|
||||
pip install pipenv
|
||||
\curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3
|
||||
|
||||
Though, you may need to say `pip3` instead, depending on your system. Once
|
||||
you have `pipenv` installed, you can install the dependencies by running
|
||||
`pipenv sync` from the `docs/` directory.
|
||||
After that finishes installing, you'll need to make sure RVM is on
|
||||
your path by doing `source $HOME/.rvm/scripts/rvm`, or just opening a
|
||||
new shell. See <http://rvm.io> for more info on RVM.
|
||||
|
||||
Also, you may need to run `virtualenv -p /usr/bin/python3 venv/` and
|
||||
then `source venv/bin/activate`, and only then `pipenv sync`.
|
||||
Once RVM is installed, you can install all the dependencies for jq's
|
||||
documentation build by running this from the `docs` directory:
|
||||
|
||||
Once this is done, rerun `./configure --enable-docs` in the jq root directory and then
|
||||
the `Makefile` will be able to generate the jq manpage. You can just run
|
||||
`make jq.1` to build the manpage manually, and `make tests/man.test` to
|
||||
update the manual tests.
|
||||
bundle install
|
||||
|
||||
To build the website, run `pipenv run python3 build_website.py` in the `docs/` directory.
|
||||
To serve them locally, you can run `python3 -m http.server -d output`.
|
||||
When bundle manages to install the dependencies, rerun `./configure`
|
||||
in the jq root directory and then the Makefile will be able to
|
||||
generate the jq manpage.
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
require 'yaml'
|
||||
require 'bonsai'
|
||||
require 'liquid'
|
||||
require 'maruku'
|
||||
require 'json'
|
||||
require 'ronn'
|
||||
require 'tempfile'
|
||||
require 'yaml'
|
||||
|
||||
module ExtraFilters
|
||||
def markdownify(input)
|
||||
Maruku.new(input).to_html
|
||||
end
|
||||
|
||||
def sanitize(input)
|
||||
input.gsub(/[^a-zA-Z0-9_]/,"")
|
||||
end
|
||||
|
||||
def json(input)
|
||||
input.to_json
|
||||
end
|
||||
|
||||
def unique(input)
|
||||
@n = (@n || 0) + 1
|
||||
input + @n.to_s
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_filter(ExtraFilters)
|
||||
|
||||
|
||||
task :serve do
|
||||
begin
|
||||
Bonsai.log "Press Control+C to quit"
|
||||
|
||||
require 'rack'
|
||||
require 'sinatra'
|
||||
require 'watch'
|
||||
require 'launchy'
|
||||
|
||||
Bonsai.root_dir = Dir.pwd
|
||||
|
||||
server = fork {
|
||||
app = Rack::Builder.app {
|
||||
map "/jq" do
|
||||
use Bonsai::StaticPassThrough, :root => Bonsai.root_dir + "/output", :urls => ["/"]
|
||||
end
|
||||
run Bonsai::DevelopmentServer
|
||||
}
|
||||
Rack::Handler.default.run(app, :Port => 5000) do
|
||||
Launchy.open("http://localhost:5000/jq/")
|
||||
end
|
||||
}
|
||||
Watch.new("{content,templates,public}/**/*") { Bonsai::Exporter.process! }
|
||||
rescue Interrupt
|
||||
Process.kill("QUIT", server)
|
||||
Process.wait(server)
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
task :build do
|
||||
Bonsai.root_dir = Dir.pwd
|
||||
Bonsai::Exporter.publish!
|
||||
end
|
||||
|
||||
$BINARIES = {
|
||||
:osx32 => "--host=i686-apple-darwin10 CFLAGS='-m32 -g -O'",
|
||||
:osx64 => "--host=i686-apple-darwin10 CFLAGS='-m64 -g -O'",
|
||||
:win32 => "--host=i686-w64-mingw32 CFLAGS='-g -O'",
|
||||
:win64 => "--host=x86_64-w64-mingw32 CFLAGS='-g -O'",
|
||||
:linux32 => "--host=x86_64-linux-gnu CFLAGS='-m32 -g -O'",
|
||||
:linux64 => "--host=x86_64-linux-gnu CFLAGS='-m64 -g -O'"
|
||||
}
|
||||
|
||||
$BINARIES.each do |name, args|
|
||||
file "../build/#{name}" do |t|
|
||||
sh "MAKEFLAGS=-j4 ../scripts/crosscompile #{name} #{args}"
|
||||
end
|
||||
task :binaries => ["../build/#{name}"]
|
||||
end
|
||||
|
||||
task :binaries => ["output/download"] do
|
||||
$BINARIES.each do |name, args|
|
||||
FileUtils.cp_r "../build/#{name}", "output/download/"
|
||||
end
|
||||
end
|
||||
|
||||
def load_manual
|
||||
YAML::ENGINE.yamler = 'syck'
|
||||
YAML::load(File.open("content/3.manual/manual.yml"))
|
||||
end
|
||||
|
||||
def jq_version
|
||||
YAML::load(File.open("site.yml"))["jq_version"]
|
||||
end
|
||||
|
||||
task :manpage do
|
||||
Tempfile.open "manpage" do |f|
|
||||
manual = load_manual
|
||||
f.puts manual['manpage_intro']
|
||||
f.puts manual['body']
|
||||
manual['sections'].each do |section|
|
||||
|
||||
f.puts "## #{section['title'].upcase}\n"
|
||||
f.puts section['body']
|
||||
f.puts ""
|
||||
(section['entries'] || []).each do |entry|
|
||||
f.puts "### #{entry['title']}\n"
|
||||
f.puts entry['body']
|
||||
f.puts ""
|
||||
(entry['examples'] || []).each do |example|
|
||||
f.puts " jq '#{example['program']}'"
|
||||
f.puts " #{example['input']}"
|
||||
f.puts " => #{example['output'].join(", ")}"
|
||||
f.puts
|
||||
end
|
||||
end
|
||||
f.puts ""
|
||||
end
|
||||
f.puts manual['manpage_epilogue']
|
||||
f.close
|
||||
puts Ronn::Document.new(f.path).convert('roff').gsub(/<\/?code>/,"")
|
||||
end
|
||||
end
|
||||
|
||||
task :manpage_default => ["default_manpage.md"] do
|
||||
puts Ronn::Document.new("default_manpage.md").convert('roff').gsub(/<\/?code>/,"")
|
||||
end
|
||||
|
||||
task :mantests do
|
||||
load_manual['sections'].each do |section|
|
||||
(section['entries'] || []).each do |entry|
|
||||
(entry['examples'] || []).each do |example|
|
||||
puts example['program'].gsub("\n", " ")
|
||||
puts example['input']
|
||||
example['output'].each do |s| puts s end
|
||||
puts
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
$TARBALL = "../jq-#{jq_version}.tar.gz"
|
||||
file $TARBALL do
|
||||
sh "cd ..; ./configure && make dist && make distclean"
|
||||
end
|
||||
|
||||
directory "output/download/source"
|
||||
task :tarball => ["output/download/source", $TARBALL] do
|
||||
sh "cp #{$TARBALL} output/download/source"
|
||||
end
|
||||
|
||||
task :dist => [:build, :binaries, :tarball]
|
||||
@@ -1,251 +0,0 @@
|
||||
#!/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 sys
|
||||
import yaml
|
||||
|
||||
|
||||
# Prevent our markdown parser from trying to help by interpreting things in angle brackets as HTML tags.
|
||||
class EscapeHtml(Extension):
|
||||
|
||||
def extendMarkdown(self, md):
|
||||
md.preprocessors.deregister('html_block')
|
||||
md.inlinePatterns.deregister('html')
|
||||
|
||||
|
||||
class RoffWalker(object):
|
||||
|
||||
def __init__(self, tree, output=sys.stdout):
|
||||
self.tree = tree
|
||||
self.target = output
|
||||
self.f = StringIO()
|
||||
|
||||
def walk(self):
|
||||
self._walk(self.tree, parent_tag=None)
|
||||
# We don't want to start lines with \. because that can confuse man
|
||||
# For lines that start with \., we need to prefix them with \& so it
|
||||
# knows not to treat that line as a directive
|
||||
data = re.sub(r'^\\\.', r'\&.', self.f.getvalue(), flags=re.MULTILINE)
|
||||
self.target.write(data)
|
||||
|
||||
def _ul_is_special(self, root):
|
||||
if len(root) != 1:
|
||||
return False
|
||||
child = root[0]
|
||||
if child.tag != 'li':
|
||||
return False
|
||||
msg = ''.join(child.itertext()).strip()
|
||||
return msg.endswith(':')
|
||||
|
||||
def _walk_child(self, root):
|
||||
if len(root) > 0:
|
||||
self._walk(root[0], parent_tag=root.tag)
|
||||
|
||||
def _write_element(self, root, ensure_newline=True):
|
||||
if root.text is not None:
|
||||
text = self._sanitize(root.text)
|
||||
self.__write_raw(text)
|
||||
self._walk_child(root)
|
||||
self._write_tail(root, ensure_newline=ensure_newline)
|
||||
|
||||
def _write_tail(self, root, ensure_newline=False, inline=False):
|
||||
if root.tail is not None:
|
||||
if inline or root.tail != '\n':
|
||||
text = self._sanitize(root.tail)
|
||||
if text.endswith('\n'):
|
||||
ensure_newline = False
|
||||
self.__write_raw(text)
|
||||
if ensure_newline:
|
||||
self.__write_raw('\n')
|
||||
|
||||
def _walk(self, root, parent_tag=None):
|
||||
last_tag = None
|
||||
while root is not None:
|
||||
if root.tag == 'h1':
|
||||
self.__write_cmd('.TH "JQ" "1" "{}" "" ""'.format(
|
||||
date.today().strftime('%B %Y')))
|
||||
self.__write_cmd('.SH "NAME"')
|
||||
# TODO: properly parse this
|
||||
self.__write_raw(r'\fBjq\fR \- Command\-line JSON processor' +
|
||||
"\n")
|
||||
|
||||
elif root.tag == 'h2':
|
||||
self.__write_cmd('.SH "{}"'.format(''.join(
|
||||
root.itertext()).strip()))
|
||||
|
||||
elif root.tag == 'h3':
|
||||
text = ''.join(root.itertext()).strip()
|
||||
self.__write_cmd('.SS "{}"'.format(self._h3_sanitize(text)))
|
||||
|
||||
elif root.tag == 'p':
|
||||
if last_tag not in ['h2', 'h3'] and parent_tag not in ['li']:
|
||||
self.__write_cmd('.P')
|
||||
self._write_element(root, ensure_newline=(parent_tag != 'li'))
|
||||
|
||||
elif root.tag == 'a':
|
||||
self._write_element(root, ensure_newline=(parent_tag != 'li'))
|
||||
|
||||
elif root.tag == 'ul':
|
||||
if self._ul_is_special(root):
|
||||
li = root[0]
|
||||
self.__write_cmd('.TP')
|
||||
self._write_element(li)
|
||||
next = root.getnext()
|
||||
while next is not None and next.tag == 'p':
|
||||
if next.getnext() is not None and next.getnext(
|
||||
).tag == 'pre':
|
||||
# we don't want to .IP these, because it'll look funny with the code indent
|
||||
break
|
||||
self.__write_cmd('.IP')
|
||||
self._write_element(next)
|
||||
root = next
|
||||
next = root.getnext()
|
||||
else:
|
||||
self._walk_child(root)
|
||||
self._write_tail(root)
|
||||
# A pre tag after the end of a list doesn't want two of the indentation commands
|
||||
if root.getnext() is None or root.getnext().tag != 'pre':
|
||||
self.__write_cmd('.IP "" 0')
|
||||
|
||||
elif root.tag == 'li':
|
||||
self.__write_cmd(r'.IP "\(bu" 4')
|
||||
if root.text is not None and root.text.strip() != '':
|
||||
text = self._sanitize(root.text)
|
||||
self.__write_raw(text)
|
||||
self._walk_child(root)
|
||||
self._write_tail(root, ensure_newline=True)
|
||||
|
||||
elif root.tag == 'strong':
|
||||
if root.text is not None:
|
||||
text = self._sanitize(root.text)
|
||||
self.__write_raw('\\fB{}\\fR'.format(text))
|
||||
|
||||
self._write_tail(root, inline=True)
|
||||
|
||||
elif root.tag == 'em':
|
||||
if root.text is not None:
|
||||
text = self._sanitize(root.text)
|
||||
self.__write_raw('\\fI{}\\fR'.format(text))
|
||||
self._write_tail(root, inline=True)
|
||||
|
||||
elif root.tag == 'code':
|
||||
if root.text is not None:
|
||||
text = self._code_sanitize(root.text)
|
||||
self.__write_raw('\\fB{}\\fR'.format(text))
|
||||
self._write_tail(root, inline=True)
|
||||
|
||||
elif root.tag == 'pre':
|
||||
self.__write_cmd('.IP "" 4')
|
||||
self.__write_cmd('.nf\n') # extra newline for spacing reasons
|
||||
next = root
|
||||
first = True
|
||||
while next is not None and next.tag == 'pre':
|
||||
if not first:
|
||||
self.__write_raw('\n')
|
||||
text = ''.join(next.itertext(with_tail=False))
|
||||
self.__write_raw(self._pre_sanitize(text))
|
||||
first = False
|
||||
root = next
|
||||
next = next.getnext()
|
||||
self.__write_cmd('.fi')
|
||||
self.__write_cmd('.IP "" 0')
|
||||
|
||||
else:
|
||||
self._walk_child(root)
|
||||
|
||||
last_tag = root.tag
|
||||
root = root.getnext()
|
||||
|
||||
def _base_sanitize(self, text):
|
||||
text = re.sub(r'\\', r'\\e', text)
|
||||
text = re.sub(r'\.', r'\\.', text)
|
||||
text = re.sub("'", r"\'", text)
|
||||
text = re.sub('-', r'\-', text)
|
||||
return text
|
||||
|
||||
def _pre_sanitize(self, text):
|
||||
return self._base_sanitize(text)
|
||||
|
||||
def _code_sanitize(self, text):
|
||||
text = self._base_sanitize(text)
|
||||
text = re.sub(r'\s', ' ', text)
|
||||
return text
|
||||
|
||||
def _h3_sanitize(self, text):
|
||||
text = self._base_sanitize(text)
|
||||
text = re.sub(' \n|\n ', ' ', text)
|
||||
text = re.sub('\n', ' ', text)
|
||||
return text
|
||||
|
||||
def _sanitize(self, text):
|
||||
text = self._base_sanitize(text)
|
||||
text = re.sub(r'<([^>]+)>', r'\\fI\1\\fR', text)
|
||||
text = re.sub(r' +', ' ', text)
|
||||
text = re.sub('\n', ' ', text)
|
||||
return text
|
||||
|
||||
def __write_cmd(self, dat):
|
||||
print('.', dat, sep='\n', file=self.f)
|
||||
pass
|
||||
|
||||
def __write_raw(self, dat):
|
||||
print(dat, sep='', end='', file=self.f)
|
||||
pass
|
||||
|
||||
|
||||
def load_yml_file(fn):
|
||||
with open(fn) as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def dedent_body(body):
|
||||
lines = [re.sub(r'^ (\S)', r'\1', l) for l in body.split('\n')]
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def convert_manual_to_markdown():
|
||||
f = StringIO()
|
||||
manual = load_yml_file("content/manual/dev/manual.yml")
|
||||
f.write(manual.get('manpage_intro', '\n'))
|
||||
f.write(dedent_body(manual.get('body', '\n')))
|
||||
for section in manual.get('sections', []):
|
||||
f.write('## {}\n'.format(section.get('title', '').upper()))
|
||||
f.write(dedent_body(section.get('body', '\n')))
|
||||
f.write('\n')
|
||||
for entry in section.get('entries', []):
|
||||
f.write('### {}\n'.format(entry.get('title', '')))
|
||||
f.write(dedent_body(entry.get('body', '\n')))
|
||||
f.write('\n')
|
||||
if entry.get('examples') is not None:
|
||||
f.write("~~~~\n")
|
||||
first = True
|
||||
for example in entry.get('examples'):
|
||||
if not first:
|
||||
f.write('\n')
|
||||
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)))
|
||||
first = False
|
||||
f.write("~~~~\n")
|
||||
f.write('\n')
|
||||
f.write(manual.get('manpage_epilogue', ''))
|
||||
return f.getvalue()
|
||||
|
||||
|
||||
# Convert manual.yml to our special markdown format
|
||||
markdown_data = convert_manual_to_markdown()
|
||||
|
||||
# Convert markdown to html
|
||||
html_data = markdown.markdown(markdown_data,
|
||||
extensions=[EscapeHtml(), 'fenced_code'])
|
||||
|
||||
# Parse the html into a tree so we can walk it
|
||||
tr = etree.HTML(html_data, etree.HTMLParser())
|
||||
|
||||
# Convert the markdown to ROFF
|
||||
RoffWalker(tr).walk()
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import yaml
|
||||
import re
|
||||
|
||||
regex_program_pattern = re.compile(
|
||||
r'\b(?:test|match|capture|scan|split|splits|sub|gsub)\s*\(')
|
||||
|
||||
with open('content/manual/dev/manual.yml') as source, \
|
||||
open('../tests/man.test', 'w') as man, \
|
||||
open('../tests/manonig.test', 'w') as manonig:
|
||||
manual = yaml.safe_load(source)
|
||||
for section in manual.get('sections', []):
|
||||
for entry in section.get('entries', []):
|
||||
for example in entry.get('examples', []):
|
||||
program = example.get('program', '').replace('\n', ' ')
|
||||
out = manonig if regex_program_pattern.search(program) else man
|
||||
print(program, file=out)
|
||||
print(example.get('input', ''), file=out)
|
||||
for s in example.get('output', []):
|
||||
print(s, file=out)
|
||||
print('', file=out)
|
||||
@@ -1,88 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import glob
|
||||
import itertools
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape, pass_context
|
||||
from markdown import markdown
|
||||
from markupsafe import Markup
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import yaml
|
||||
|
||||
env = Environment(
|
||||
loader=FileSystemLoader('templates'),
|
||||
autoescape=select_autoescape(['html.j2']),
|
||||
)
|
||||
|
||||
|
||||
def load_yml_file(fn):
|
||||
with open(fn) as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
env.globals['url'] = 'https://jqlang.org'
|
||||
env.filters['search_id'] = lambda input: input.replace(r'`', '')
|
||||
env.filters['section_id'] = lambda input: re.sub(
|
||||
r'[^-a-zA-Z0-9_]', '', input.replace(' ', '-')).lower()
|
||||
env.filters['entry_id'] = lambda input: re.sub(
|
||||
r'^(split|first-last-nth)$',
|
||||
r'\1' + ('-1' if ';' not in input else '-2'), # avoid id conflict
|
||||
re.sub(
|
||||
r'\b([^-]+)(?:-\1)+\b',
|
||||
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['no_paragraph'] = lambda input: Markup(re.sub(r'</?p>', '', input))
|
||||
|
||||
env.globals['unique_id'] = pass_context(
|
||||
lambda ctx: str(next(ctx['unique_ctr'])))
|
||||
|
||||
|
||||
def raise_handler(message):
|
||||
raise Exception(message)
|
||||
|
||||
|
||||
env.globals['raise'] = raise_handler
|
||||
|
||||
|
||||
def generate_file(env, fname):
|
||||
path, base = os.path.split(fname)
|
||||
path = os.path.relpath(path, 'content')
|
||||
if path == '.':
|
||||
path = ''
|
||||
permalink = ''
|
||||
else:
|
||||
permalink = path + '/'
|
||||
|
||||
output_dir = os.path.join('output', path)
|
||||
output_path = os.path.join(output_dir, 'index.html')
|
||||
|
||||
template_name = re.sub(r'.yml$', '.html.j2', base)
|
||||
|
||||
ctx = load_yml_file(fname)
|
||||
ctx.update(unique_ctr=itertools.count(1),
|
||||
permalink=permalink,
|
||||
navitem=path)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
env.get_template(template_name).stream(ctx).dump(output_path,
|
||||
encoding='utf-8')
|
||||
|
||||
|
||||
def copy_public_files(root=''):
|
||||
for f in os.scandir(os.path.join('public', root)):
|
||||
src = os.path.join(root, f.name)
|
||||
dst = os.path.join('output', src)
|
||||
if f.is_dir():
|
||||
os.makedirs(dst, exist_ok=True)
|
||||
copy_public_files(src)
|
||||
else:
|
||||
shutil.copyfile(f.path, dst)
|
||||
|
||||
|
||||
os.makedirs('output', exist_ok=True)
|
||||
copy_public_files()
|
||||
|
||||
for fn in glob.glob('content/**/*.yml', recursive=True):
|
||||
generate_file(env, fn)
|
||||
@@ -0,0 +1,241 @@
|
||||
headline: Tutorial
|
||||
body:
|
||||
- text: |
|
||||
|
||||
Twitter has a JSON API, so let's play with that. This URL gets
|
||||
us the last 5 tweets about JSON:
|
||||
|
||||
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true'"
|
||||
result: |
|
||||
{"completed_in":0.108,"max_id":247677287108067328,"max_id_str":"247677287108067328","next_page":"?page=2&max_id=247677287108067328&q=json&rpp=5&include_entities=1","page":1,"query":"json","refresh_url":"?since_id=247677287108067328&q=json&include_entities=1","results":[{"created_at":"Mon, 17 Sep 2012 12:44:01 +0000","entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/XRvh1ZVw","expanded_url":"http:\/\/jase.im\/Ri7I0M","display_url":"jase.im\/Ri7I0M","indices":[112,132]}],"user_mentions":[{"screen_name":"imagemechanics","name":"Jason Cotterell","id":57271393,"id_str":"57271393","indices":[3,18]}]},"from_user":"_AaronNg","from_user_id":79771704,"from_user_id_str":"79771704","from_user_name":"NgChenChong","geo":null,"id":247677287108067328,"id_str":"247677287108067328","iso_language_code":"en","metadata":{"result_type":"recent"},"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2523558403\/ek8mo4j4beq84iw28gjl_normal.jpeg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2523558403\/ek8mo4j4beq84iw28gjl_normal.jpeg","source":"<a href="http:\/\/twitter.com\/">web<\/a>","text":"RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp:\/\/t.co\/XRvh1ZVw","to_user":null,"to_user_id":0,"to_user_id_str":"0","to_user_name":null}, ...
|
||||
|
||||
- text: |
|
||||
|
||||
There's lots of info and no whitespace, so to make it a bit more
|
||||
legible we pipe it through jq, telling jq to just spit the input
|
||||
back at us using the expression `.`:
|
||||
|
||||
|
||||
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true' | jq '.'"
|
||||
result: |
|
||||
|
||||
{
|
||||
"since_id_str": "0",
|
||||
"since_id": 0,
|
||||
"results_per_page": 5,
|
||||
"completed_in": 0.108,
|
||||
"max_id": 247677287108067330,
|
||||
"max_id_str": "247677287108067328",
|
||||
"next_page": "?page=2&max_id=247677287108067328&q=json&rpp=5&include_entities=1",
|
||||
"page": 1,
|
||||
"query": "json",
|
||||
"refresh_url": "?since_id=247677287108067328&q=json&include_entities=1",
|
||||
"results": [
|
||||
{
|
||||
"from_user_name": "NgChenChong",
|
||||
"from_user_id_str": "79771704",
|
||||
"from_user_id": 79771704,
|
||||
"from_user": "_AaronNg",
|
||||
"iso_language_code": "en",
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"to_user": null
|
||||
/* lots more fields... */
|
||||
},
|
||||
/* lots more results... */
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
- text: |
|
||||
|
||||
Let's pull out the first tweet:
|
||||
|
||||
|
||||
- command: "curl 'http://search.twitter.com/search.json?q=json&rpp=5&include_entities=true' | jq '.results[0]'"
|
||||
result: |
|
||||
{
|
||||
"from_user_name": "NgChenChong",
|
||||
"from_user_id_str": "79771704",
|
||||
"from_user_id": 79771704,
|
||||
"from_user": "_AaronNg",
|
||||
"iso_language_code": "en",
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"to_user": null
|
||||
/* lots more fields... */
|
||||
},
|
||||
|
||||
- text: |
|
||||
|
||||
For the rest of the examples, I'll leave out the `curl` command - it's not going to change.
|
||||
|
||||
|
||||
There's still a lot of info we don't care about there, so we'll
|
||||
restrict it down to the most interesting fields.
|
||||
|
||||
|
||||
- command: "jq '.results[0] | {from_user, text}'"
|
||||
result: |
|
||||
{
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"from_user": "_AaronNg"
|
||||
}
|
||||
|
||||
- text: |
|
||||
|
||||
The `|` operator in jq feeds the output of one filter
|
||||
(`.results[0]` which gets the first element of the results
|
||||
array) into the input of another (`{from_user, text}` which
|
||||
builds an object of those two fields).
|
||||
|
||||
Now let's get the rest of the tweets:
|
||||
|
||||
|
||||
|
||||
- command: "jq '.results[] | {from_user, text}'"
|
||||
result: |
|
||||
{
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"from_user": "_AaronNg"
|
||||
}
|
||||
{
|
||||
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas> -- http://t.co/Lhp92IqD",
|
||||
"from_user": "blouerat"
|
||||
}
|
||||
{
|
||||
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
|
||||
"from_user": "cebu_iphone"
|
||||
}
|
||||
{
|
||||
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and <canvas> http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
|
||||
"from_user": "dieswaytoofast"
|
||||
}
|
||||
{
|
||||
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
|
||||
"from_user": "Leolik"
|
||||
}
|
||||
|
||||
|
||||
- text: |
|
||||
|
||||
`.results[]` returns each element of the results array, one at a
|
||||
time, which are all fed into `{from_user, text}`.
|
||||
|
||||
|
||||
Data in jq is represented as streams of JSON values - every jq
|
||||
expression runs for each value in its input stream, and can
|
||||
produce any number of values to its output stream.
|
||||
|
||||
Streams are serialised by just separating JSON values with
|
||||
whitespace. This is a `cat`-friendly format - you can just join
|
||||
two JSON streams together and get a valid JSON stream.
|
||||
|
||||
If you want to get the output as a single array, you can tell jq to
|
||||
"collect" all of the answers by wrapping the filter in square
|
||||
brackets:
|
||||
|
||||
- command: "jq '[.results[] | {from_user, text}]'"
|
||||
result: |
|
||||
[
|
||||
{
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"from_user": "_AaronNg"
|
||||
},
|
||||
{
|
||||
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas> -- http://t.co/Lhp92IqD",
|
||||
"from_user": "blouerat"
|
||||
},
|
||||
{
|
||||
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
|
||||
"from_user": "cebu_iphone"
|
||||
},
|
||||
{
|
||||
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and <canvas> http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
|
||||
"from_user": "dieswaytoofast"
|
||||
},
|
||||
{
|
||||
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
|
||||
"from_user": "Leolik"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
- text: |
|
||||
|
||||
- - -
|
||||
|
||||
Next, let's try getting the URLs out of those API results as
|
||||
well. In each tweet, the Twitter API includes a field called
|
||||
"entities" which looks like this:
|
||||
|
||||
{
|
||||
"user_mentions": [],
|
||||
"urls": [{
|
||||
"indices": [83, 103],
|
||||
"display_url": "bit.ly/StniqT",
|
||||
"expanded_url": "http://bit.ly/StniqT",
|
||||
"url": "http://t.co/28Jesbio"
|
||||
}],
|
||||
"hashtags": [
|
||||
{"indices": [108, 114], "text": "Apple" },
|
||||
{"indices": [121, 129], "text": "Awesome"}
|
||||
]
|
||||
}
|
||||
|
||||
We want to pull out all of the "url" fields inside that array of url
|
||||
objects, and make a simple list of strings to go along with the
|
||||
"from_user" and "text" fields we already have.
|
||||
|
||||
|
||||
|
||||
- command: "jq '.results[] | {from_user, text, urls: [.entities.urls[].url]}'"
|
||||
result: |
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/XRvh1ZVw"
|
||||
],
|
||||
"text": "RT @imagemechanics: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas>.\nhttp://t.co/XRvh1ZVw",
|
||||
"from_user": "_AaronNg"
|
||||
}
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/Lhp92IqD"
|
||||
],
|
||||
"text": "RT @_kud: iPhone 5 website teardown: How Apple compresses video using JPEG, JSON, and <canvas> -- http://t.co/Lhp92IqD",
|
||||
"from_user": "blouerat"
|
||||
}
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/7KALdWaX"
|
||||
],
|
||||
"text": "Dynamic Forms Mobile App by pmadiset: Few Forms details are hosted on our server in the form of JSON. This JSON ... http://t.co/7KALdWaX",
|
||||
"from_user": "cebu_iphone"
|
||||
}
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/28Jesbio"
|
||||
],
|
||||
"text": "iPhone 5 website insanity - Video compressing using JPEG, JSON, and <canvas> http://t.co/28Jesbio (Oh #Apple, U So #Awesome...)",
|
||||
"from_user": "dieswaytoofast"
|
||||
}
|
||||
{
|
||||
"urls": [
|
||||
"http://t.co/M70snaIf"
|
||||
],
|
||||
"text": "RT @umutm: A very nice web-based JSON editor - http://t.co/M70snaIf",
|
||||
"from_user": "Leolik"
|
||||
}
|
||||
|
||||
|
||||
- text: |
|
||||
|
||||
Here we're making an object as before, but this time the urls
|
||||
field is being set to `[.entities.urls[].url]`, which collects
|
||||
all of the URLs defined in the entities object.
|
||||
|
||||
- text: |
|
||||
|
||||
- - -
|
||||
|
||||
Here endeth the tutorial! There's lots more to play with, go
|
||||
read [the manual](../manual/) if you're interested, and [download
|
||||
jq](../download/) if you haven't already.
|
||||
@@ -0,0 +1,90 @@
|
||||
headline: Download jq
|
||||
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, OS X and Windows.
|
||||
|
||||
The binaries should just run, but on OS X and Linux you may need
|
||||
to make them executable first using `chmod +x jq`.
|
||||
|
||||
jq is licensed under the MIT license. For all of the gory
|
||||
details, read the file `COPYING` in the source distribution.
|
||||
|
||||
|
||||
### Linux
|
||||
|
||||
* Binaries for [64-bit](linux64/jq) or [32-bit](linux32/jq) systems.
|
||||
|
||||
* For Arch users, a PKGBUILD for jq-1.1 is in the
|
||||
[AUR](https://aur.archlinux.org/packages.php?ID=63849), as
|
||||
well as a PKGBUILD for the HEAD of master
|
||||
([jq-git](https://aur.archlinux.org/packages.php?ID=63850)).
|
||||
You can install them using
|
||||
[Yaourt](https://wiki.archlinux.org/index.php/Yaourt) or
|
||||
manually by following instructions on [Arch Linux's
|
||||
Wiki](https://wiki.archlinux.org/index.php/Arch_UseRepository).
|
||||
|
||||
* jq 1.2 is [in Debian](http://packages.debian.org/jq)
|
||||
|
||||
### OS X
|
||||
|
||||
* `brew install jq` using [homebrew](http://mxcl.github.io/homebrew/)
|
||||
|
||||
* Or, grab prebuilt [64-bit binaries](osx64/jq) or [32-bit
|
||||
binaries](osx32/jq)
|
||||
|
||||
### Windows
|
||||
|
||||
* Executables for [64-bit](win64/jq.exe) or [32-bit](win32/jq.exe)
|
||||
|
||||
### From source on Linux or OS X
|
||||
|
||||
* [Source tarball for jq $JQ_VERSION](source/jq-$JQ_VERSION.tar.gz)
|
||||
|
||||
You can build it using the usual `./configure && make && sudo
|
||||
make install` rigmarole.
|
||||
|
||||
If you're interested in using the latest development version, try:
|
||||
|
||||
git clone https://github.com/stedolan/jq.git
|
||||
cd jq
|
||||
autoreconf
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
|
||||
To build it from a git clone, you'll need to install a few
|
||||
packages first:
|
||||
|
||||
* [Flex](http://www.gnu.org/software/flex/)
|
||||
* [Bison](http://www.gnu.org/software/bison/)
|
||||
* [GCC](http://gcc.gnu.org)
|
||||
* [Make](http://www.gnu.org/software/make)
|
||||
* [Autotools](http://www.gnu.org/software/automake)
|
||||
|
||||
For Linux systems, these will all be in your system's package
|
||||
manager, and if you do development on the machine they're most
|
||||
likely already installed.
|
||||
|
||||
On OS X, these are all included in Apple's command line tools, which
|
||||
can be installed from [Xcode](http://developer.apple.com/technologies/tools/).
|
||||
However, you may find that you need a newer version of Bison than the one provided
|
||||
by Apple. This can be found in [Homebrew](http://mxcl.github.io/homebrew/)
|
||||
or [MacPorts](http://macports.org/).
|
||||
|
||||
`flex` and `bison` are used to generate the lexer and parser for
|
||||
jq, and some python scripts generate the UTF8 encoding tables
|
||||
needed for JSON parsing.
|
||||
|
||||
#### Building the documentation
|
||||
|
||||
jq's documentation is compiled into static HTML using
|
||||
[Bonsai](http://www.tinytree.info). To view the documentation
|
||||
locally, run `rake serve` from the docs/ subdirectory. You'll
|
||||
need a few Ruby dependencies, which can be installed by
|
||||
following the instructions in `docs/README.md`.
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,249 +0,0 @@
|
||||
headline: Download jq
|
||||
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.
|
||||
|
||||
The binaries should just run, but on macOS and Linux you may need
|
||||
to make them executable first using `chmod +x jq`.
|
||||
|
||||
jq is licensed under the MIT license. For all of the gory
|
||||
details, read the file `COPYING` in the source distribution.
|
||||
|
||||
jq uses a C library for decimal number support. This is an ICU 1.8.1
|
||||
licensed code obtained from the ICU downloads archive.
|
||||
<https://download.icu-project.org/files/decNumber/decNumber-icu-368.zip>
|
||||
|
||||
|
||||
### Linux
|
||||
|
||||
* jq is in the official [Debian](https://packages.debian.org/jq) and
|
||||
[Ubuntu](https://packages.ubuntu.com/jq) repositories. Install using
|
||||
`sudo apt-get install jq`.
|
||||
|
||||
* jq is in the official [Fedora](https://src.fedoraproject.org/rpms/jq) repository.
|
||||
Install using `sudo dnf install jq`.
|
||||
|
||||
* jq is in the official [openSUSE](https://software.opensuse.org/package/jq) repository.
|
||||
Install using `sudo zypper install jq`.
|
||||
|
||||
* jq is in the official [Arch](https://archlinux.org/packages/?q=jq) repository.
|
||||
Install using `sudo pacman -S jq`.
|
||||
|
||||
* jq 1.7.1 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64)
|
||||
or
|
||||
[ARM64](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-arm64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-i386).
|
||||
|
||||
* jq 1.7 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.7/jq-linux-amd64)
|
||||
or
|
||||
[ARM64](https://github.com/jqlang/jq/releases/download/jq-1.7/jq-linux-arm64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.7/jq-linux-i386).
|
||||
|
||||
* jq 1.6 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux32).
|
||||
|
||||
* jq 1.5 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.5/jq-linux64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.5/jq-linux32).
|
||||
|
||||
* jq 1.4 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.4/jq-linux-x86_64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.4/jq-linux-x86).
|
||||
|
||||
* jq 1.3 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-linux-x86_64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-linux-x86).
|
||||
|
||||
### macOS
|
||||
|
||||
* Use [Homebrew](https://brew.sh/) to install jq with `brew install jq`.
|
||||
|
||||
* Use [MacPorts](https://www.macports.org) to install jq with `port install jq`.
|
||||
|
||||
* Use [Fink](https://finkproject.org) to install jq with `fink install jq`.
|
||||
|
||||
* jq 1.7.1 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-macos-amd64)
|
||||
or
|
||||
[ARM64](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-macos-arm64).
|
||||
|
||||
* jq 1.7 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.7/jq-macos-amd64)
|
||||
or
|
||||
[ARM64](https://github.com/jqlang/jq/releases/download/jq-1.7/jq-macos-arm64).
|
||||
|
||||
* jq 1.6 binary for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.6/jq-osx-amd64).
|
||||
|
||||
* jq 1.5 binary for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.5/jq-osx-amd64).
|
||||
|
||||
* jq 1.4 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.4/jq-osx-x86_64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.4/jq-osx-x86).
|
||||
|
||||
* jq 1.3 binaries for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-osx-x86_64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-osx-x86).
|
||||
|
||||
### FreeBSD
|
||||
|
||||
* `pkg install jq` as root installs a pre-built
|
||||
[binary package](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/pkgng-intro.html).
|
||||
|
||||
* `make -C /usr/ports/textproc/jq install clean` as root installs the
|
||||
[jq](https://www.freshports.org/textproc/jq/)
|
||||
[port](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ports-using.html)
|
||||
from source.
|
||||
|
||||
### Solaris
|
||||
|
||||
* `pkgutil -i jq` in [OpenCSW](https://www.opencsw.org/p/jq) for Solaris
|
||||
10+, Sparc and x86.
|
||||
|
||||
* jq 1.4 binaries for Solaris 11
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.4/jq-solaris11-64)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.4/jq-solaris11-32).
|
||||
|
||||
### Windows
|
||||
|
||||
* Use [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/)
|
||||
to install jq with `winget install jqlang.jq`.
|
||||
|
||||
* Use [scoop](https://scoop.sh/) to install jq with `scoop install jq`.
|
||||
|
||||
* Use [Chocolatey NuGet](https://chocolatey.org/) to install jq with
|
||||
`choco install jq`.
|
||||
|
||||
* jq 1.7.1 executables for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-windows-amd64.exe)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-windows-i386.exe).
|
||||
|
||||
* jq 1.7 executables for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.7/jq-windows-amd64.exe)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.7/jq-windows-i386.exe).
|
||||
|
||||
* jq 1.6 executables for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.6/jq-win64.exe)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.6/jq-win32.exe).
|
||||
|
||||
* jq 1.5 executables for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.5/jq-win64.exe)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.5/jq-win32.exe).
|
||||
|
||||
* jq 1.4 executables for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.4/jq-win64.exe)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.4/jq-win32.exe).
|
||||
|
||||
* jq 1.3 executables for
|
||||
[AMD64](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-win64.exe)
|
||||
or
|
||||
[i386](https://github.com/jqlang/jq/releases/download/jq-1.3/jq-win32.exe).
|
||||
|
||||
### Checksums and signatures
|
||||
|
||||
SHA-256 checksums are provided for all release and pre-release binaries.
|
||||
They can be found under
|
||||
[sig/v1.x/sha256sum.txt](https://github.com/jqlang/jq/tree/master/sig).
|
||||
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).
|
||||
Signatures can be found under
|
||||
[sig/v1.x/\*.asc](https://github.com/jqlang/jq/tree/master/sig).
|
||||
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).
|
||||
You can use [GnuPG](https://gnupg.org/) to verify a signature by downloading
|
||||
the signature and running `gpg --verify signature.asc`.
|
||||
|
||||
### From source on Linux, macOS, Cygwin, and other POSIX-like operating systems
|
||||
|
||||
* [Source tarball for jq 1.7.1](https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-1.7.1.tar.gz)
|
||||
* [Source tarball for jq 1.7](https://github.com/jqlang/jq/releases/download/jq-1.7/jq-1.7.tar.gz)
|
||||
* [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)
|
||||
|
||||
You can build it using the usual `./configure && make && sudo
|
||||
make install` rigmarole.
|
||||
|
||||
If you're interested in using the latest development version, try:
|
||||
|
||||
git clone --recursive https://github.com/jqlang/jq.git
|
||||
cd jq
|
||||
autoreconf -i
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
|
||||
To build it from a git clone, you'll need to install a few
|
||||
packages first:
|
||||
|
||||
* [GCC](https://gcc.gnu.org)
|
||||
* [Make](https://www.gnu.org/software/make/)
|
||||
* [Autotools](https://www.gnu.org/software/automake/)
|
||||
|
||||
For Linux systems, these will all be in your system's package
|
||||
manager, and if you do development on the machine they're most
|
||||
likely already installed.
|
||||
|
||||
On macOS, these are all included in Apple's command line tools, which can
|
||||
be installed from [Xcode](https://developer.apple.com/xcode/). However,
|
||||
you may find that you need a newer version of Bison than the one provided
|
||||
by Apple. This can be found in [Homebrew](https://brew.sh/) or
|
||||
[MacPorts](https://macports.org/).
|
||||
|
||||
If you want to generate the lexer and parser from source you can use the
|
||||
`--enable-maintainer-mode` configure flag. This requires bison to be installed.
|
||||
[Flex](https://github.com/westes/flex) and
|
||||
[Bison](https://www.gnu.org/software/bison/).
|
||||
|
||||
### Docker
|
||||
|
||||
Docker image is available from
|
||||
[GitHub Container Registry](https://github.com/jqlang/jq/pkgs/container/jq).
|
||||
|
||||
docker run -i --rm ghcr.io/jqlang/jq -n 'range(3)'
|
||||
|
||||
#### Building the documentation
|
||||
|
||||
jq's documentation is compiled into static HTML using Python.
|
||||
To build the docs, run `pipenv run python3 build_website.py`
|
||||
in the `docs/` directory. To serve them locally, you can run
|
||||
`python3 -m http.server -d output`. You'll need a few Python dependencies,
|
||||
which can be installed by following the instructions in `docs/README.md`.
|
||||
|
||||
The man page is built by `make jq.1`, or just `make`, also from
|
||||
the YAML docs, and you'll still need the Python dependencies to
|
||||
build the manpage.
|
||||
@@ -1,83 +0,0 @@
|
||||
headline: jq
|
||||
|
||||
blurb: |
|
||||
|
||||
jq is a lightweight and flexible command-line JSON processor.
|
||||
|
||||
body1: |
|
||||
|
||||
jq is like `sed` for JSON data - you can use it to slice and filter
|
||||
and map and transform structured data with the same ease that `sed`,
|
||||
`awk`, `grep` and friends let you play with text.
|
||||
|
||||
body2: |
|
||||
|
||||
jq is written in portable C, and it has zero runtime
|
||||
dependencies. You can download a single binary, `scp` it to a far away
|
||||
machine of the same type, and expect it to work.
|
||||
|
||||
body3: |
|
||||
|
||||
jq can mangle the data format that you have into the one that you
|
||||
want with very little effort, and the program to do so is often
|
||||
shorter and simpler than you'd expect.
|
||||
|
||||
tail: |
|
||||
|
||||
Go read the [tutorial](./tutorial/) for more, or the [manual](./manual/)
|
||||
for *way* more.
|
||||
|
||||
Have a question related to jq? You can seek answers on [Stack Overflow](https://stackoverflow.com/)
|
||||
by using the [jq tag](https://stackoverflow.com/questions/tagged/jq), or in the [#jq channel](https://web.libera.chat/#jq)
|
||||
on [Libera.Chat](https://libera.chat/). For more interactive discussions, feel free to join our [Discord server](https://discord.gg/yg6yjNmgAC).
|
||||
|
||||
news:
|
||||
- date: 13 December 2023
|
||||
body: |
|
||||
jq 1.7.1 released. Security (CVE-2023-50246, CVE-2023-50268) and bug fixes.
|
||||
See [release notes](https://github.com/jqlang/jq/releases/tag/jq-1.7.1) for details.
|
||||
|
||||
- date: 7 September 2023
|
||||
body: |
|
||||
After a five-year hiatus, we've returned with a revitalized [GitHub organization](https://github.com/jqlang)
|
||||
and a much-anticipated 1.7 release, thanks to our new admins and maintainers.
|
||||
Check out the [download](./download/) page for installation options and see the
|
||||
[release notes](https://github.com/jqlang/jq/releases/tag/jq-1.7) for details.
|
||||
|
||||
- date: 1 November 2018
|
||||
body: |
|
||||
jq 1.6 released. See installation options on the [download](./download/)
|
||||
page, and the [release notes](https://github.com/jqlang/jq/releases/tag/jq-1.6)
|
||||
for details.
|
||||
|
||||
- date: 15 August 2015
|
||||
body: |
|
||||
|
||||
jq 1.5 released, including new datetime, math, and regexp functions,
|
||||
try/catch syntax, array and object destructuring, a streaming parser,
|
||||
and a module system. See installation options on the
|
||||
[download](./download/) page, and the
|
||||
[release notes](https://github.com/jqlang/jq/releases/tag/jq-1.5)
|
||||
for details.
|
||||
|
||||
- date: 26 July 2015
|
||||
body: |
|
||||
|
||||
jq 1.5rc2 is available. Get it on the
|
||||
[releases](https://github.com/jqlang/jq/releases) page.
|
||||
|
||||
- date: 01 January 2015
|
||||
body: |
|
||||
|
||||
jq 1.5rc1 is available. Get it on the
|
||||
[releases](https://github.com/jqlang/jq/releases) page.
|
||||
|
||||
- date: 09 June 2014
|
||||
body: |
|
||||
|
||||
jq 1.4 (finally) released! Get it on the [download](./download/) page.
|
||||
|
||||
- date: 19 May 2013
|
||||
body: |
|
||||
|
||||
jq 1.3 released.
|
||||
@@ -0,0 +1,34 @@
|
||||
headline: jq
|
||||
|
||||
blurb: |
|
||||
|
||||
jq is a lightweight and flexible command-line JSON processor.
|
||||
|
||||
body1: |
|
||||
|
||||
jq is like `sed` for JSON data - you can use it to slice and filter
|
||||
and map and transform structured data with the same ease that `sed`,
|
||||
`awk`, `grep` and friends let you play with text.
|
||||
|
||||
body2: |
|
||||
|
||||
jq is written in portable C, and it has zero runtime
|
||||
dependencies. You can download a single binary, `scp` it to a far away
|
||||
machine, and expect it to work.
|
||||
|
||||
body3: |
|
||||
|
||||
jq can mangle the data format that you have into the one that you
|
||||
want with very little effort, and the program to do so is often
|
||||
shorter and simpler than you'd expect.
|
||||
|
||||
tail: |
|
||||
Go read the [tutorial](tutorial/) for more, or the [manual](manual/)
|
||||
for *way* more.
|
||||
|
||||
news:
|
||||
- date: 2013-05-19
|
||||
body: |
|
||||
|
||||
jq 1.3 (finally) released! Get it on the [download](download/) page.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1 +0,0 @@
|
||||
v1.7/manual.yml
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,337 +0,0 @@
|
||||
headline: Tutorial
|
||||
body:
|
||||
- text: |
|
||||
|
||||
GitHub has a JSON API, so let's play with that. This URL gets us the last
|
||||
5 commits from the jq repo.
|
||||
|
||||
- command: "curl 'https://api.github.com/repos/jqlang/jq/commits?per_page=5'"
|
||||
result: |
|
||||
[
|
||||
{
|
||||
"sha": "cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"node_id": "C_kwDOAE3WVdoAKGNmZjUzMzZlYzcxYjZmZWUzOTZhOTViYjBlNGJlYTM2NWUwY2QxZTg",
|
||||
"commit": {
|
||||
"author": {
|
||||
"name": "Mattias Wadman",
|
||||
"email": "mattias.wadman@gmail.com",
|
||||
"date": "2021-06-09T14:02:22Z"
|
||||
},
|
||||
"committer": {
|
||||
"name": "Nico Williams",
|
||||
"email": "nico@cryptonector.com",
|
||||
"date": "2022-05-26T21:04:32Z"
|
||||
},
|
||||
"message": "docs: Document repeat(exp)",
|
||||
"tree": {
|
||||
"sha": "d67d5542df1f16d1a48e1fb75749f60482cd874b",
|
||||
"url": "https://api.github.com/repos/jqlang/jq/git/trees/d67d5542df1f16d1a48e1fb75749f60482cd874b"
|
||||
},
|
||||
"url": "https://api.github.com/repos/jqlang/jq/git/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"comment_count": 0,
|
||||
"verification": {
|
||||
"verified": false,
|
||||
"reason": "unsigned",
|
||||
"signature": null,
|
||||
"payload": null
|
||||
}
|
||||
},
|
||||
"url": "https://api.github.com/repos/jqlang/jq/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"html_url": "https://github.com/jqlang/jq/commit/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"comments_url": "https://api.github.com/repos/jqlang/jq/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8/comments",
|
||||
"author": {
|
||||
...
|
||||
|
||||
- text: |
|
||||
|
||||
GitHub returns nicely formatted JSON. For servers that don't, it can be
|
||||
helpful to pipe the response through jq to pretty-print it. The simplest
|
||||
jq program is the expression `.`, which takes the input and produces it
|
||||
unchanged as output.
|
||||
|
||||
- command: "curl 'https://api.github.com/repos/jqlang/jq/commits?per_page=5' | jq '.'"
|
||||
result: |
|
||||
[
|
||||
{
|
||||
"sha": "cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"node_id": "C_kwDOAE3WVdoAKGNmZjUzMzZlYzcxYjZmZWUzOTZhOTViYjBlNGJlYTM2NWUwY2QxZTg",
|
||||
"commit": {
|
||||
"author": {
|
||||
"name": "Mattias Wadman",
|
||||
"email": "mattias.wadman@gmail.com",
|
||||
"date": "2021-06-09T14:02:22Z"
|
||||
},
|
||||
"committer": {
|
||||
"name": "Nico Williams",
|
||||
"email": "nico@cryptonector.com",
|
||||
"date": "2022-05-26T21:04:32Z"
|
||||
},
|
||||
"message": "docs: Document repeat(exp)",
|
||||
"tree": {
|
||||
"sha": "d67d5542df1f16d1a48e1fb75749f60482cd874b",
|
||||
"url": "https://api.github.com/repos/jqlang/jq/git/trees/d67d5542df1f16d1a48e1fb75749f60482cd874b"
|
||||
},
|
||||
"url": "https://api.github.com/repos/jqlang/jq/git/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"comment_count": 0,
|
||||
"verification": {
|
||||
"verified": false,
|
||||
"reason": "unsigned",
|
||||
"signature": null,
|
||||
"payload": null
|
||||
}
|
||||
},
|
||||
"url": "https://api.github.com/repos/jqlang/jq/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"html_url": "https://github.com/jqlang/jq/commit/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"comments_url": "https://api.github.com/repos/jqlang/jq/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8/comments",
|
||||
"author": {
|
||||
...
|
||||
|
||||
- text: |
|
||||
|
||||
We can use jq to extract just the first commit.
|
||||
|
||||
- command: "curl 'https://api.github.com/repos/jqlang/jq/commits?per_page=5' | jq '.[0]'"
|
||||
result: |
|
||||
{
|
||||
"sha": "cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"node_id": "C_kwDOAE3WVdoAKGNmZjUzMzZlYzcxYjZmZWUzOTZhOTViYjBlNGJlYTM2NWUwY2QxZTg",
|
||||
"commit": {
|
||||
"author": {
|
||||
"name": "Mattias Wadman",
|
||||
"email": "mattias.wadman@gmail.com",
|
||||
"date": "2021-06-09T14:02:22Z"
|
||||
},
|
||||
"committer": {
|
||||
"name": "Nico Williams",
|
||||
"email": "nico@cryptonector.com",
|
||||
"date": "2022-05-26T21:04:32Z"
|
||||
},
|
||||
"message": "docs: Document repeat(exp)",
|
||||
"tree": {
|
||||
"sha": "d67d5542df1f16d1a48e1fb75749f60482cd874b",
|
||||
"url": "https://api.github.com/repos/jqlang/jq/git/trees/d67d5542df1f16d1a48e1fb75749f60482cd874b"
|
||||
},
|
||||
"url": "https://api.github.com/repos/jqlang/jq/git/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"comment_count": 0,
|
||||
"verification": {
|
||||
"verified": false,
|
||||
"reason": "unsigned",
|
||||
"signature": null,
|
||||
"payload": null
|
||||
}
|
||||
},
|
||||
"url": "https://api.github.com/repos/jqlang/jq/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"html_url": "https://github.com/jqlang/jq/commit/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8",
|
||||
"comments_url": "https://api.github.com/repos/jqlang/jq/commits/cff5336ec71b6fee396a95bb0e4bea365e0cd1e8/comments",
|
||||
"author": {
|
||||
"login": "wader",
|
||||
"id": 185566,
|
||||
"node_id": "MDQ6VXNlcjE4NTU2Ng==",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/185566?v=4",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/wader",
|
||||
"html_url": "https://github.com/wader",
|
||||
"followers_url": "https://api.github.com/users/wader/followers",
|
||||
"following_url": "https://api.github.com/users/wader/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/wader/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/wader/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/wader/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/wader/orgs",
|
||||
"repos_url": "https://api.github.com/users/wader/repos",
|
||||
"events_url": "https://api.github.com/users/wader/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/wader/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"committer": {
|
||||
"login": "nicowilliams",
|
||||
"id": 604851,
|
||||
"node_id": "MDQ6VXNlcjYwNDg1MQ==",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/604851?v=4",
|
||||
"gravatar_id": "",
|
||||
"url": "https://api.github.com/users/nicowilliams",
|
||||
"html_url": "https://github.com/nicowilliams",
|
||||
"followers_url": "https://api.github.com/users/nicowilliams/followers",
|
||||
"following_url": "https://api.github.com/users/nicowilliams/following{/other_user}",
|
||||
"gists_url": "https://api.github.com/users/nicowilliams/gists{/gist_id}",
|
||||
"starred_url": "https://api.github.com/users/nicowilliams/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://api.github.com/users/nicowilliams/subscriptions",
|
||||
"organizations_url": "https://api.github.com/users/nicowilliams/orgs",
|
||||
"repos_url": "https://api.github.com/users/nicowilliams/repos",
|
||||
"events_url": "https://api.github.com/users/nicowilliams/events{/privacy}",
|
||||
"received_events_url": "https://api.github.com/users/nicowilliams/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"parents": [
|
||||
{
|
||||
"sha": "f2ad9517c72f6267ae317639ab56bbfd4a8653d4",
|
||||
"url": "https://api.github.com/repos/jqlang/jq/commits/f2ad9517c72f6267ae317639ab56bbfd4a8653d4",
|
||||
"html_url": "https://github.com/jqlang/jq/commit/f2ad9517c72f6267ae317639ab56bbfd4a8653d4"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
- text: |
|
||||
|
||||
For the rest of the examples, I'll leave out the `curl` command - it's not
|
||||
going to change.
|
||||
|
||||
There's a lot of info we don't care about there, so we'll restrict it down
|
||||
to the most interesting fields.
|
||||
|
||||
- command: "jq '.[0] | {message: .commit.message, name: .commit.committer.name}'"
|
||||
result: |
|
||||
{
|
||||
"message": "docs: Document repeat(exp)",
|
||||
"name": "Nico Williams"
|
||||
}
|
||||
|
||||
- text: |
|
||||
|
||||
The `|` operator in jq feeds the output of one filter (`.[0]` which gets
|
||||
the first element of the array in the response) into the input of another
|
||||
(`{...}` which builds an object out of those fields). You can access
|
||||
nested attributes, such as `.commit.message`.
|
||||
|
||||
Now let's get the rest of the commits.
|
||||
|
||||
- command: "jq '.[] | {message: .commit.message, name: .commit.committer.name}'"
|
||||
result: |
|
||||
{
|
||||
"message": "docs: Document repeat(exp)",
|
||||
"name": "Nico Williams"
|
||||
}
|
||||
{
|
||||
"message": "Mention -n in IO-section and for input/inputs",
|
||||
"name": "Nico Williams"
|
||||
}
|
||||
{
|
||||
"message": "Fix iteration problem for non decimal string\n\nWhen the string transformation to number failed, all following\ntransformation failed too.\n\nThis happend because status in decNumberFromString function is\nupdated just in error case. Reusing the DEC_CONTEXT that failed\nbefore results into error even if the string is valid number.",
|
||||
"name": "Nico Williams"
|
||||
}
|
||||
{
|
||||
"message": "docs: point to Libera.Chat instead of Freenode",
|
||||
"name": "Nico Williams"
|
||||
}
|
||||
{
|
||||
"message": "Missing \"va_end\" call. This was found by running the cppcheck static analysis where it shows as error.",
|
||||
"name": "Nico Williams"
|
||||
}
|
||||
|
||||
- text: |
|
||||
|
||||
`.[]` returns each element of the array returned in the response, one at a
|
||||
time, which are all fed into
|
||||
`{message: .commit.message, name: .commit.committer.name}`.
|
||||
|
||||
Data in jq is represented as streams of JSON values - every jq
|
||||
expression runs for each value in its input stream, and can
|
||||
produce any number of values to its output stream.
|
||||
|
||||
Streams are serialised by just separating JSON values with
|
||||
whitespace. This is a `cat`-friendly format - you can just join
|
||||
two JSON streams together and get a valid JSON stream.
|
||||
|
||||
If you want to get the output as a single array, you can tell jq to
|
||||
"collect" all of the answers by wrapping the filter in square
|
||||
brackets:
|
||||
|
||||
- command: "jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'"
|
||||
result: |
|
||||
[
|
||||
{
|
||||
"message": "docs: Document repeat(exp)",
|
||||
"name": "Nico Williams"
|
||||
},
|
||||
{
|
||||
"message": "Mention -n in IO-section and for input/inputs",
|
||||
"name": "Nico Williams"
|
||||
},
|
||||
{
|
||||
"message": "Fix iteration problem for non decimal string\n\nWhen the string transformation to number failed, all following\ntransformation failed too.\n\nThis happend because status in decNumberFromString function is\nupdated just in error case. Reusing the DEC_CONTEXT that failed\nbefore results into error even if the string is valid number.",
|
||||
"name": "Nico Williams"
|
||||
},
|
||||
{
|
||||
"message": "docs: point to Libera.Chat instead of Freenode",
|
||||
"name": "Nico Williams"
|
||||
},
|
||||
{
|
||||
"message": "Missing \"va_end\" call. This was found by running the cppcheck static analysis where it shows as error.",
|
||||
"name": "Nico Williams"
|
||||
}
|
||||
]
|
||||
|
||||
- text: |
|
||||
|
||||
- - -
|
||||
|
||||
Next, let's try getting the URLs of the parent commits out of the
|
||||
API results as well. In each commit, the GitHub API includes information
|
||||
about "parent" commits. There can be one or many.
|
||||
|
||||
"parents": [
|
||||
{
|
||||
"sha": "f2ad9517c72f6267ae317639ab56bbfd4a8653d4",
|
||||
"url": "https://api.github.com/repos/jqlang/jq/commits/f2ad9517c72f6267ae317639ab56bbfd4a8653d4",
|
||||
"html_url": "https://github.com/jqlang/jq/commit/f2ad9517c72f6267ae317639ab56bbfd4a8653d4"
|
||||
}
|
||||
]
|
||||
|
||||
We want to pull out all of the "html_url" fields inside that array of parent
|
||||
commits and make a simple list of strings to go along with the
|
||||
"message" and "author" fields we already have.
|
||||
|
||||
- command: "jq '[.[] | {message: .commit.message, name: .commit.committer.name, parents: [.parents[].html_url]}]'"
|
||||
result: |
|
||||
[
|
||||
{
|
||||
"message": "docs: Document repeat(exp)",
|
||||
"name": "Nico Williams",
|
||||
"parents": [
|
||||
"https://github.com/jqlang/jq/commit/f2ad9517c72f6267ae317639ab56bbfd4a8653d4"
|
||||
]
|
||||
},
|
||||
{
|
||||
"message": "Mention -n in IO-section and for input/inputs",
|
||||
"name": "Nico Williams",
|
||||
"parents": [
|
||||
"https://github.com/jqlang/jq/commit/c4d39c4d22f2b12225ca1b311708f7e084ad9ff8"
|
||||
]
|
||||
},
|
||||
{
|
||||
"message": "Fix iteration problem for non decimal string\n\nWhen the string transformation to number failed, all following\ntransformation failed too.\n\nThis happend because status in decNumberFromString function is\nupdated just in error case. Reusing the DEC_CONTEXT that failed\nbefore results into error even if the string is valid number.",
|
||||
"name": "Nico Williams",
|
||||
"parents": [
|
||||
"https://github.com/jqlang/jq/commit/174db0f93552bdb551ae1f3c5c64744df0ad8e2f"
|
||||
]
|
||||
},
|
||||
{
|
||||
"message": "docs: point to Libera.Chat instead of Freenode",
|
||||
"name": "Nico Williams",
|
||||
"parents": [
|
||||
"https://github.com/jqlang/jq/commit/29cf77977ef52eec708982b19bf9d2ec17443337"
|
||||
]
|
||||
},
|
||||
{
|
||||
"message": "Missing \"va_end\" call. This was found by running the cppcheck static analysis where it shows as error.",
|
||||
"name": "Nico Williams",
|
||||
"parents": [
|
||||
"https://github.com/jqlang/jq/commit/55e6e2c21829bd866bd4b18ee254b05c9020320a"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
- text: |
|
||||
|
||||
Here we're making an object as before, but this time the `parents`
|
||||
field is being set to `[.parents[].html_url]`, which collects
|
||||
all of the parent commit URLs defined in the parents object.
|
||||
|
||||
- text: |
|
||||
|
||||
- - -
|
||||
|
||||
Here endeth the tutorial! There's lots more to play with. Go
|
||||
read [the manual](../manual/) if you're interested, and [download
|
||||
jq](../download/) if you haven't already.
|
||||
@@ -0,0 +1,22 @@
|
||||
jq(1) -- Command-line JSON processor
|
||||
====================================
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
`jq` can transform JSON in various ways, by selecting, iterating,
|
||||
reducing and otherwise mangling JSON documents.
|
||||
|
||||
This version of `jq` was built without a manual, so this manpage is a
|
||||
stub. For full documentation of the `jq` language, see:
|
||||
|
||||
http://stedolan.github.com/jq
|
||||
|
||||
## BUGS
|
||||
|
||||
Presumably. Report them or discuss them at:
|
||||
|
||||
https://github.com/stedolan/jq/issues
|
||||
|
||||
## AUTHOR
|
||||
|
||||
Stephen Dolan `<mu@netsoc.tcd.ie>`
|
||||
@@ -1,60 +0,0 @@
|
||||
type: object
|
||||
required:
|
||||
- headline
|
||||
- body
|
||||
- manpage_intro
|
||||
- manpage_epilogue
|
||||
- sections
|
||||
additionalProperties: false
|
||||
properties:
|
||||
headline:
|
||||
type: string
|
||||
body:
|
||||
type: string
|
||||
manpage_intro:
|
||||
type: string
|
||||
manpage_epilogue:
|
||||
type: string
|
||||
sections:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- title
|
||||
additionalProperties: false
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
body:
|
||||
type: string
|
||||
entries:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- title
|
||||
- body
|
||||
additionalProperties: false
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
body:
|
||||
type: string
|
||||
examples:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- program
|
||||
- input
|
||||
- output
|
||||
additionalProperties: false
|
||||
properties:
|
||||
program:
|
||||
type: string
|
||||
input:
|
||||
type: string
|
||||
output:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
@@ -12,7 +12,7 @@ FileETag All
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# Cache, aggressively
|
||||
# Cache, aggressively
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
ExpiresDefault "access plus 10 days"
|
||||
@@ -25,4 +25,4 @@ FileETag All
|
||||
# Mime-types
|
||||
AddType application/vnd.ms-fontobject .eot
|
||||
AddType font/ttf .ttf
|
||||
AddType font/otf .otf
|
||||
AddType font/otf .otf
|
||||
@@ -1 +0,0 @@
|
||||
jqlang.org
|
||||
+1058
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* Bootstrap Responsive v2.1.1
|
||||
*
|
||||
* Copyright 2012 Twitter, Inc
|
||||
* Licensed under the Apache License v2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Designed and built with all the love in the world @twitter by @mdo and @fat.
|
||||
*/.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*maLine truncated
|
||||
+5224
File diff suppressed because it is too large.
Load diff
+9
@@ -0,0 +1,9 @@
|
||||
/*!
|
||||
* Bootstrap v2.1.1
|
||||
*
|
||||
* Copyright 2012 Twitter, Inc
|
||||
* Licensed under the Apache License v2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Designed and built with all the love in the world @twitter by @mdo and @fat.
|
||||
*/article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluiLine truncated
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
+2027
File diff suppressed because it is too large.
Load diff
+6
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap.js by @fat & @mdo
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
*/
|
||||
!function(e){e(function(){"use strict";e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()},e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e(function(){e("body").on("click.alert.data-api",t,n.prototype.close)})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")},e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e(function(){e("body").on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=n,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},to:function(t){var n=this.$element.find(".item.active"),r=n.parent().children(),i=r.index(n),s=this;if(t>r.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){s.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",e(r[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f=e.Event("slide",{relatedTarget:i[0]});this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u]();if(i.hasClass("active"))return;if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}},e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e(function(){e("body").on("click.carousel.data-api","[data-slide]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=!i.data("modal")&&e.extend({},i.data(),n.data());i.carousel(s),t.preventDefault()})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hLine truncated
|
||||
@@ -0,0 +1,99 @@
|
||||
@charset "utf-8";
|
||||
body {
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: #F5F5F5;
|
||||
padding: 40px 0;
|
||||
height: 100px;
|
||||
margin-top: 40px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
section {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.manual-example {
|
||||
border-top: 1px solid #E5E5E5;
|
||||
}
|
||||
|
||||
.manual-example td {
|
||||
white-space: pre-wrap;
|
||||
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
||||
}
|
||||
|
||||
.manual-example td.jqprogram {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.manual-example th {
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.tutorial-example {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tutorial-example pre {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.tutorial-example a {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
padding: 15px 8px;
|
||||
color: #777777;
|
||||
font-weight: bold;
|
||||
line-height: 10px;
|
||||
font-size: 12px;
|
||||
border-left: 1px solid #DDDDDD;
|
||||
bottom: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#blurb {
|
||||
padding-top: 40px;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
#blurb p {
|
||||
font-size: 20pt;
|
||||
}
|
||||
|
||||
#blurb .btn-group {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#multiblurb {
|
||||
line-height: 1.7;
|
||||
text-align: center;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
#multiblurb code {
|
||||
border: 0;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
h3 code {
|
||||
border: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#news {
|
||||
font-size: 12pt;
|
||||
.date {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
main {
|
||||
padding: 1rem;
|
||||
|
||||
& * {
|
||||
scroll-margin-top: 4rem;
|
||||
}
|
||||
|
||||
@media print {
|
||||
width: 100%!important;
|
||||
--bs-code-color: --bs-body-color;
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
z-index: 1050!important; /* higher than #contents */
|
||||
}
|
||||
|
||||
section[id] {
|
||||
display: flow-root;
|
||||
|
||||
> :first-child {
|
||||
.icon-link {
|
||||
opacity: 0;
|
||||
|
||||
&:focus {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .icon-link {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.offcanvas[aria-modal=true] .nav-link {
|
||||
padding: .7rem;
|
||||
}
|
||||
.offcanvas-md {
|
||||
--bs-offcanvas-width: auto;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0 .5rem 1rem;
|
||||
padding: .5rem 1rem;
|
||||
background-color: var(--bs-secondary-bg-subtle);
|
||||
border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color);
|
||||
}
|
||||
|
||||
button{
|
||||
&[aria-expanded=false] .bi-chevron-down {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&[aria-expanded=true] .bi-chevron-right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container-searchbox {
|
||||
position: relative;
|
||||
|
||||
& input:focus ~ kbd {
|
||||
display: none;
|
||||
}
|
||||
|
||||
& ul {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 100%;
|
||||
padding: 0;
|
||||
background-color: var(--bs-body-bg);
|
||||
border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color);
|
||||
}
|
||||
|
||||
& li {
|
||||
padding: .3em .6em;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
|
||||
&[aria-selected=true] {
|
||||
background-color: var(--bs-secondary-bg);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--bs-secondary-bg-subtle);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.8 KiB |
@@ -1 +0,0 @@
|
||||
<svg width="48" height="48" version="1.0" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg"><style>@media(prefers-color-scheme:dark){g[fill]{filter:invert(1)}}</style><g transform="matrix(.011 0 0 .011 1.94 12)"><g fill="#444"><circle cx="220" cy="1570" r="190"/><path d="m1330 312c-30 41-698 1492-710 1528s25 66 100 101c77 36 102 34 124 3s701-1477 716-1525c15-47-20-73-84-104s-116-44-146-3z"/></g><g fill="#111"><circle cx="2410" cy="200" r="190"/><path d="m1830 655c0 129 0 130 70 130h360v423c0 246-5 474-10 506-19 112-88 176-190 176-59 0-120-27-147-66-51-73-65-84-99-84-31 0-40 8-104 93-84 111-86 129-32 189 227 252 692 187 836-118 53-112 56-153 56-795v-514c0-64-30-100-100-100h-490c-149 0-150 0-150 160zM2867 1233c30 302 250 499 438 527 144 19 244 0 375-90v410c0 81 0 100 150 100 136 0 150-20 150-150v-1420c0-99-19-100-150-100s-139 15-139 82c-103-89-351-149-523-49s-342 278-301 690zm803-107c0 292-105 356-237 356-178 0-249-147-273-296-27-168 25-420 262-420 171 0 248 89 248 360z"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 1006 B |
Binary file not shown.
|
After Width: | Height: | Size: 8.0 KiB |
@@ -1 +0,0 @@
|
||||
<svg width="400" height="220" version="1.0" viewBox="0 0 400 220" xmlns="http://www.w3.org/2000/svg"><style>@media (prefers-color-scheme:dark){g[fill]{filter:invert(1);stroke:none}}</style><g transform="scale(.1)" stroke="#fff" stroke-width="10"><g fill="#444"><circle cx="220" cy="1570" r="190"/><path d="m1330 312c-30 41-698 1492-710 1528s25 66 100 101c77 36 102 34 124 3s701-1477 716-1525c15-47-20-73-84-104s-116-44-146-3z"/></g><g fill="#111"><circle cx="2410" cy="200" r="190"/><path d="m1830 655c0 129 0 130 70 130h360v423c0 246-5 474-10 506-19 112-88 176-190 176-59 0-120-27-147-66-51-73-65-84-99-84-31 0-40 8-104 93-84 111-86 129-32 189 227 252 692 187 836-118 53-112 56-153 56-795v-514c0-64-30-100-100-100h-490c-149 0-150 0-150 160zM2867 1233c30 302 250 499 438 527 144 19 244 0 375-90v410c0 81 0 100 150 100 136 0 150-20 150-150v-1420c0-99-19-100-150-100s-139 15-139 82c-103-89-351-149-523-49s-342 278-301 690zm803-107c0 292-105 356-237 356-178 0-249-147-273-296-27-168 25-420 262-420 171 0 248 89 248 360z"/></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,34 +0,0 @@
|
||||
(() => {
|
||||
const searchInput = document.querySelector('input#searchbox');
|
||||
const sectionIDs = JSON.parse(document.querySelector('#section-ids').innerText);
|
||||
const sanitize = (string) => string.replaceAll('<', '<').replaceAll('>', '>');
|
||||
new autoComplete({
|
||||
selector: `#${searchInput.id}`,
|
||||
wrapper: false,
|
||||
data: {
|
||||
src: Object.keys(sectionIDs),
|
||||
filter: (list) => list.sort((x, y) =>
|
||||
x.match.indexOf('<') - y.match.indexOf('<') || x.value.length - y.value.length),
|
||||
},
|
||||
searchEngine: (query, value) => {
|
||||
const index = value.toLowerCase().indexOf(query.toLowerCase());
|
||||
if (index >= 0) {
|
||||
return sanitize(value.substring(0, index)) +
|
||||
`<mark>${sanitize(value.substring(index, index + query.length))}</mark>` +
|
||||
sanitize(value.substring(index + query.length));
|
||||
}
|
||||
},
|
||||
});
|
||||
searchInput.addEventListener('selection', (event) => {
|
||||
event.target.value = event.detail.selection.value;
|
||||
location.hash = `#${sectionIDs[event.detail.selection.value]}`;
|
||||
});
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.code === 'Slash' && !event.altKey && !event.ctrlKey && !event.metaKey
|
||||
&& !event.shiftKey && !/^(INPUT|TEXTAREA)$/.test(event.target.nodeName)) {
|
||||
searchInput.focus();
|
||||
searchInput.select();
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,18 @@
|
||||
# The key value pairs found below are available within the templates.
|
||||
|
||||
:url: http://stedolan.github.io/jq
|
||||
|
||||
# This line is modified by the Makefile. To change the version number,
|
||||
# edit the Autoconf version number at the top of configure.ac
|
||||
jq_version: "1.3"
|
||||
|
||||
root: '/jq'
|
||||
footer: |
|
||||
|
||||
This website is made with [Bonsai](http://www.tinytree.info) and
|
||||
[Twitter Bootstrap](http://twitter.github.com/bootstrap/), themed
|
||||
with [Bootswatch](http://bootswatch.com).
|
||||
|
||||
jq is licensed under the MIT license (code) and the
|
||||
[CC-BY-3.0](http://creativecommons.org/licenses/by/3.0/) license
|
||||
(docs).
|
||||
Vendored
-31
@@ -1,31 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/_head.html.j2" %}
|
||||
|
||||
<body>
|
||||
{% include "shared/_navbar.html.j2" %}
|
||||
|
||||
<main id="main" class="container-lg">
|
||||
<h1>{{ headline }}</h1>
|
||||
{%- for item in body %}
|
||||
{%- if item.text %}
|
||||
{{ item.text | markdownify }}
|
||||
{%- endif %}
|
||||
|
||||
{%- if item.command %}
|
||||
{%- set resultID = unique_id() %}
|
||||
<div class="tutorial-example mb-3">
|
||||
<div class="d-flex accordion-heading me-2">
|
||||
<pre class="flex-grow-1 me-0 mb-0" tabindex="0">{{ item.command }}</pre>
|
||||
<button type="button" class="btn btn-sm btn-secondary text-body-secondary bg-secondary-subtle link-body-emphasis flex-shrink-0 d-flex align-items-center border border-start-0 d-print-none"
|
||||
data-bs-toggle="collapse" data-bs-target="#result{{ resultID }}" aria-expanded="false" aria-controls="result{{ resultID }}">Show result</button>
|
||||
</div>
|
||||
<pre id="result{{ resultID }}" class="accordion-body collapse p-3 border-top-0 d-print-block" tabindex="0">{{ item.result }}</pre>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
</main>
|
||||
|
||||
{% include "shared/_footer.html.j2" %}
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
<body id="{{slug}}">
|
||||
{% include "shared/header" %}
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="row">
|
||||
<h1>{{headline}}</h1>
|
||||
{% for item in body %}
|
||||
{% if item.text %}
|
||||
{{ item.text | replace: '$JQ_VERSION', jq_version | markdownify }}
|
||||
{% endif %}
|
||||
|
||||
{% if item.command %}
|
||||
|
||||
|
||||
{% capture resultID %}{{ "result" | unique}}{% endcapture %}
|
||||
<div class="tutorial-example">
|
||||
<div class="accordion-heading">
|
||||
<pre>{{item.command}}</pre>
|
||||
<a data-toggle="collapse" href="#{{resultID}}">Show result</a>
|
||||
</div>
|
||||
<div id="{{resultID}}" class="accordion-body collapse"><pre>{{item.result}}</pre></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "shared/footer" %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Vendored
-58
@@ -1,58 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/_head.html.j2" %}
|
||||
|
||||
<body>
|
||||
{% include "shared/_navbar.html.j2" %}
|
||||
|
||||
<main id="main" class="container-lg">
|
||||
<div class="row">
|
||||
<div class="col-md-6 text-center p-3">
|
||||
<h1><img src="/jq.svg" class="img-fluid" alt="jq" width="400" height="220"></h1>
|
||||
</div>
|
||||
<div class="col-md-6 d-flex flex-column justify-content-center text-center align-items-center">
|
||||
<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.7.1
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.7.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.7.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.7.1/jq-macos-amd64" aria-label="Link to download executable: macOS (AMD64)"><span class="bi bi-download me-2" aria-hidden="true"></span>macOS (AMD64)</a></li>
|
||||
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-macos-arm64" aria-label="Link to download executable: macOS (ARM64)"><span class="bi bi-download me-2" aria-hidden="true"></span>macOS (ARM64)</a></li>
|
||||
<li><a class="dropdown-item" href="https://github.com/jqlang/jq/releases/download/jq-1.7.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="/download/">Other platforms, older versions, and source</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-primary text-nowrap" href="https://play.jqlang.org" rel="noopener">
|
||||
Try online!
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row my-3">
|
||||
<div class="col-md-4">{{ body1 | markdownify }}</div>
|
||||
<div class="col-md-4">{{ body2 | markdownify }}</div>
|
||||
<div class="col-md-4">{{ body3 | markdownify }}</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center my-3">
|
||||
{{ tail | markdownify }}
|
||||
</div>
|
||||
|
||||
<h2>News</h2>
|
||||
<ul>
|
||||
{%- for item in news %}
|
||||
<li>
|
||||
<span class="fst-italic">{{ item.date }}</span>
|
||||
{{ item.body | markdownify }}
|
||||
</li>
|
||||
{%- endfor %}
|
||||
</ul>
|
||||
</main>
|
||||
|
||||
{% include "shared/_footer.html.j2" %}
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+51
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
<body id="{{slug}}">
|
||||
{% include "shared/header" %}
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="hero-unit">
|
||||
<img src="{{root}}/jq.png" style="width: 400px; height: 220px; float: left; margin-right: 60px">
|
||||
<div id="blurb">
|
||||
{{blurb | markdownify}}
|
||||
<div class="btn-group" style="float:right">
|
||||
<a class="btn btn-primary dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
Download jq-{{jq_version}}
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="{{root}}/download/linux64/jq">Linux (64-bit)</a></li>
|
||||
<li><a href="{{root}}/download/osx64/jq">OS X (64-bit)</a></li>
|
||||
<li><a href="{{root}}/download/">Other platforms and source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" id="multiblurb">
|
||||
<div class="span4">{{body1 | markdownify}}</div>
|
||||
<div class="span4">{{body2 | markdownify}}</div>
|
||||
<div class="span4">{{body3 | markdownify}}</div>
|
||||
</div>
|
||||
<div class="row" style="text-align:center; margin-top: 30px">
|
||||
{{tail | markdownify}}
|
||||
</div>
|
||||
<div class="row">
|
||||
<h2>News</h2>
|
||||
<div id="news">
|
||||
<ul>
|
||||
{% for item in news %}
|
||||
<li><span class="date">{{ item.date | date: '%m %B %Y' }}</span>{{item.body | markdownify}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include "shared/footer" %}
|
||||
</body>
|
||||
</html>
|
||||
Vendored
-120
@@ -1,120 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/_head.html.j2" %}
|
||||
|
||||
<body>
|
||||
{% include "shared/_navbar.html.j2" %}
|
||||
|
||||
<div class="container-lg row align-items-start mx-auto p-3">
|
||||
|
||||
<button type="button" class="d-md-none w-auto position-fixed bottom-0 end-0 p-2 m-3 bg-body-secondary border-0 text-body d-print-none"
|
||||
data-bs-toggle="offcanvas" data-bs-target="#contents" aria-controls="contents" aria-expanded="false" aria-label="Toggle table of contents">
|
||||
<span class="bi bi-list" aria-hidden="true"></span>
|
||||
</button>
|
||||
<nav id="contents" class="col-md-3 sticky-md-top p-3 overflow-y-auto offcanvas-md offcanvas-end d-print-none" style="top:4.5rem; height:calc(100dvh - 5.5rem);" aria-label="Table of contents">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h4>Contents</h4>
|
||||
<button type="button" class="btn-close d-md-none" data-bs-dismiss="offcanvas" data-bs-target="#contents" aria-label="Close table of contents"></button>
|
||||
</div>
|
||||
<ul class="offcanvas-md-body nav nav-pills flex-column">
|
||||
{%- for section in sections %}
|
||||
<li class="nav-item" data-bs-dismiss="offcanvas" data-bs-target="#contents">
|
||||
<a class="nav-link" href="#{{ section.title | section_id }}">{{ section.title }}</a>
|
||||
</li>
|
||||
{%- endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
{%- set section_ids = {} %}
|
||||
{%- macro check_section_id(id) -%}
|
||||
{%- if section_ids.__contains__(id) %}
|
||||
{{- raise('Duplicate section id: ' ~ id) }}
|
||||
{%- endif %}
|
||||
{%- set _ = section_ids.__setitem__(id, true) %}
|
||||
{%- endmacro %}
|
||||
<main id="main" class="col-md-9" data-bs-spy="scroll" data-bs-target="#contents" data-bs-threshold="0,1" data-bs-root-margin="-30% 0% -70%">
|
||||
<h1>{{ headline }}</h1>
|
||||
<p>
|
||||
<em>
|
||||
For other versions, see
|
||||
<a href="/manual/v1.7/">1.7</a>,
|
||||
<a href="/manual/v1.6/">1.6</a>,
|
||||
<a href="/manual/v1.5/">1.5</a>,
|
||||
<a href="/manual/v1.4/">1.4</a>,
|
||||
<a href="/manual/v1.3/">1.3</a> or
|
||||
<a href="/manual/dev/">development version</a>.
|
||||
</em>
|
||||
</p>
|
||||
{{ body | markdownify }}
|
||||
{%- for section in sections %}
|
||||
<section id="{{ section.title | section_id }}">{{ check_section_id(section.title | section_id) }}
|
||||
<h2>{{ section.title }} <a href="#{{ section.title | section_id }}" class="icon-link" aria-label="Link to this section: {{ section.title }}"><span class="bi bi-link-45deg" aria-hidden="true"></span></a></h2>
|
||||
{{ section.body | markdownify if section.body }}
|
||||
{%- for entry in section.entries %}
|
||||
<section id="{{ entry.title | entry_id }}">{{ check_section_id(entry.title | entry_id) }}
|
||||
<h3>
|
||||
{{ entry.title | markdownify | no_paragraph }}
|
||||
<a href="#{{ entry.title | entry_id }}" class="icon-link" aria-label="Link to this section: {{ entry.title }}"><span class="bi bi-link-45deg" aria-hidden="true"></span></a>
|
||||
</h3>
|
||||
{{ entry.body | markdownify }}
|
||||
{%- if entry.examples %}
|
||||
<div class="pb-3">
|
||||
{%- set exampleID = unique_id() %}
|
||||
<button type="button" class="btn btn-sm btn-secondary text-body-secondary bg-transparent link-body-emphasis border-0" data-bs-toggle="collapse" data-bs-target="#example{{ exampleID }}" aria-expanded="false" aria-controls="example{{ exampleID }}">
|
||||
<span class="me-1 d-print-none" aria-hidden="true"><span class="bi bi-chevron-right"></span><span class="bi bi-chevron-down"></span></span>Example{% if entry.examples | length > 1 %}s{% endif %}
|
||||
</button>
|
||||
<div id="example{{ exampleID }}" class="collapse mx-3 small d-print-block">
|
||||
{%- for example in entry.examples %}
|
||||
<table class="table table-borderless table-sm w-auto">
|
||||
<tr>
|
||||
<th class="pe-3">Command</th>
|
||||
<td class="font-monospace">jq '{{ example.program }}'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Input</th>
|
||||
<td class="font-monospace">{{ example.input }}</td>
|
||||
</tr>
|
||||
{%- if not example.output[0] %}
|
||||
<tr>
|
||||
<th>Output</th>
|
||||
<td class="fst-italic">none</td>
|
||||
</tr>
|
||||
{%- endif %}
|
||||
{%- for output in example.output %}
|
||||
<tr>
|
||||
<th>{% if loop.first %}Output{% endif %}</th>
|
||||
<td class="font-monospace">{{ output }}</td>
|
||||
</tr>
|
||||
{%- endfor %}
|
||||
<tr class="d-print-none">
|
||||
<th><a href="https://play.jqlang.org/?q={{ example.program | urlencode }}&j={{ example.input | urlencode }}" class="btn btn-outline-primary btn-sm" target="_blank" rel="noopener">Run<span class="bi bi-box-arrow-up-right ms-2" aria-hidden="true"></span></a></th>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
{%- endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif %}
|
||||
</section>
|
||||
{%- endfor %}
|
||||
</section>
|
||||
{%- endfor %}
|
||||
</main>
|
||||
|
||||
</div>
|
||||
|
||||
{% include "shared/_footer.html.j2" %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.7/dist/autoComplete.min.js"
|
||||
integrity="sha384-xbzjoN6H5XHmAqoSSR42hZVRninPGx85y+XZQGlWxVu2y91lTmr/oD80i5cjeUBv" crossorigin="anonymous"></script>
|
||||
<script id="section-ids" type="application/json">
|
||||
{
|
||||
{%- for section in sections %}
|
||||
{%- for entry in section.entries %}
|
||||
{{ entry.title | search_id | tojson }}: {{ entry.title | entry_id | tojson }},
|
||||
{%- endfor %}
|
||||
{{ section.title | search_id | tojson }}: {{ section.title | section_id | tojson }}{{ "," if not loop.last }}
|
||||
{%- endfor %}
|
||||
}
|
||||
</script>
|
||||
<script src="/js/manual-search.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+110
@@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
{% include "shared/head" %}
|
||||
<body id="{{slug}}" data-spy="scroll" data-target="#navcolumn" data-offset="100">
|
||||
{% include "shared/header" %}
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span3" id="navcolumn">
|
||||
<div class="affix">
|
||||
<h4>Contents</h4>
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
{% for section in sections %}
|
||||
<li {% if forloop.first %} class="active" {% endif %}>
|
||||
<a href="#{{section.title | sanitize}}">{{section.title}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<form class="form-search">
|
||||
<script type="text/javascript">
|
||||
var section_map = {
|
||||
{% for section in sections %}
|
||||
{% for entry in section.entries %}
|
||||
{{entry.title | json}} : {{entry.title | sanitize | json}},
|
||||
{% endfor %}
|
||||
{{section.title | json}} : {{section.title | sanitize | json}}
|
||||
{% unless forloop.last %},{% endunless %}
|
||||
{% endfor %}
|
||||
};
|
||||
var section_names = $.map(section_map, function(v,k){return k});
|
||||
$(function(){
|
||||
$('#searchbox').typeahead({source: section_names})
|
||||
$('#searchbox').change(function() {
|
||||
if ($(this).val() in section_map) {
|
||||
location.hash = '#' + section_map[$(this).val()];
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<input type="text"
|
||||
class="input-medium search-query"
|
||||
placeholder="Search"
|
||||
autocomplete="off"
|
||||
id="searchbox">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span9">
|
||||
<h1>{{headline}}</h1>
|
||||
{{ body | markdownify }}
|
||||
{% for section in sections %}
|
||||
<section id="{{section.title | sanitize}}">
|
||||
<h2>{{section.title}}</h2>
|
||||
{{section.body | markdownify}}
|
||||
{% for entry in section.entries %}
|
||||
<section id="{{entry.title | sanitize}}">
|
||||
<h3>
|
||||
{{entry.title | markdownify}}
|
||||
{% if entry.subtitle %}<small>{{entry.subtitle}}</small>{% endif %}
|
||||
</h3>
|
||||
{{entry.body | markdownify}}
|
||||
|
||||
{% if entry.examples %}
|
||||
<div>
|
||||
{% capture exampleID %}{{ "" | unique }}{% endcapture %}
|
||||
<a data-toggle="collapse" href="#example{{exampleID}}">
|
||||
<i class="icon-chevron-right"></i>
|
||||
{% if entry.examples[1] %}Examples{%else%}Example{%endif%}
|
||||
</a>
|
||||
<div id="example{{exampleID}}" class="collapse">
|
||||
|
||||
{% for example in entry.examples %}
|
||||
<table class="manual-example">
|
||||
<tr><th></th><td class="jqprogram">jq '{{example.program}}'</td></tr>
|
||||
<tr><th>Input</th><td>{{example.input}}</td></tr>
|
||||
{% unless example.output[0] %}
|
||||
<tr>
|
||||
<th>Output</th>
|
||||
<td><i>none</i></td>
|
||||
</tr>
|
||||
{% endunless %}
|
||||
{% for output in example.output %}
|
||||
<tr>
|
||||
{% if forloop.index == 1 %}
|
||||
<th>Output</th>
|
||||
{% else %}
|
||||
<th></th>
|
||||
{% endif %}
|
||||
<td>{{output}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{% include "shared/footer" %}
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
<footer class="bd-footer bg-body-tertiary">
|
||||
<div class="py-3 text-center">
|
||||
<p>
|
||||
This website is made with <a href="https://getbootstrap.com" target="_blank" rel="noopener">Bootstrap</a>,
|
||||
themed with <a href="https://bootswatch.com" target="_blank" rel="noopener">Bootswatch</a>.
|
||||
</p>
|
||||
<p>
|
||||
jq is licensed under the MIT license (code) and the
|
||||
<a href="https://creativecommons.org/licenses/by/3.0/" target="_blank" rel="noopener">CC-BY-3.0</a> license (docs).
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
<footer>
|
||||
<div class="container">
|
||||
{{ footer | markdownify }}
|
||||
</div>
|
||||
</footer>
|
||||
Vendored
-28
@@ -1,28 +0,0 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{ headline }}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta property="og:title" content="{{ headline }}">
|
||||
<meta property="og:description" content="jq is a lightweight and flexible command-line JSON processor">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:image" content="{{ url }}/icon.png">
|
||||
<meta property="og:url" content="{{ url }}/{{ permalink }}">
|
||||
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/icon.png" type="image/png">
|
||||
<link rel="canonical" href="{{ url }}/{{ permalink }}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.3.1/dist/cosmo/bootstrap.min.css"
|
||||
integrity="sha384-dulfW0vmzZ638jigSgZXvDxMmd70GCnIv6oa+riKq6Kk4E0MKf7qmBfwP02wltv5" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css"
|
||||
integrity="sha384-Ay26V7L8bsJTsX9Sxclnvsn+hkdiwRnrjZJXqKmkIDobPgIIWBOVguEcQQLDuhfN" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="/css/style.css" type="text/css">
|
||||
<script>
|
||||
(function() {
|
||||
function setTheme(mediaQuery) {
|
||||
document.documentElement.setAttribute('data-bs-theme',
|
||||
document.documentElement.style.colorScheme = mediaQuery.matches ? 'dark' : 'light');
|
||||
}
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
setTheme(mediaQuery); mediaQuery.addEventListener('change', setTheme);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
<head>
|
||||
<meta charset=UTF-8>
|
||||
<title>{{headline}}</title>
|
||||
<link rel="stylesheet" href="{{root}}/bootstrap/css/bootstrap.css" type="text/css">
|
||||
<link rel="stylesheet" href="{{root}}/css/base.css" type="text/css">
|
||||
<!--[if IE]>
|
||||
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
|
||||
<script src="{{root}}/bootstrap/js/bootstrap.js"></script>
|
||||
|
||||
</head>
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="brand" href="{{root}}/">jq</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
{% for item in navigation %}
|
||||
<li {% if item.permalink == permalink %} class="active" {% endif %}>
|
||||
<a href="{{root}}{{item.permalink}}">{{item.name}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li><a href="https://github.com/stedolan/jq/issues">Issues</a></li>
|
||||
<li><a href="https://github.com/stedolan/jq">Source</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
<div class="container visually-hidden-focusable">
|
||||
<a class="d-inline-flex p-2" href="#main">Skip to main content</a>
|
||||
{%- if navitem.startswith('manual') %}
|
||||
<a class="d-inline-flex p-2 m-1" href="#contents">Skip to table of contents</a>
|
||||
{%- endif %}
|
||||
</div>
|
||||
<header class="navbar navbar-expand-md sticky-top bg-body-tertiary d-print-none">
|
||||
<nav class="container-lg" aria-label="Page navigation">
|
||||
<button type="button" class="navbar-toggler" data-bs-toggle="offcanvas" data-bs-target="#navbar-collapse"
|
||||
aria-controls="navbar-collapse" aria-expanded="false" aria-label="Toggle page navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/" aria-label="Top page"><img src="/jq.svg" alt="jq logo" style="height:1.5rem"></a>
|
||||
<div id="navbar-collapse" class="offcanvas offcanvas-start navbar-collapse w-auto" aria-labelledby="navbar-title">
|
||||
<div class="offcanvas-header">
|
||||
<h3 id="navbar-title" class="me-3">jq</h3>
|
||||
<button type="button" class="d-md-none btn-close" data-bs-dismiss="offcanvas" aria-label="Close page navigation"></button>
|
||||
</div>
|
||||
<ul class="offcanvas-body navbar-nav me-auto text-nowrap">
|
||||
<li class="nav-item d-md-none"><a class="nav-link{% if not navitem %} active{% endif %}"{% if not navitem %} aria-current="page"{% endif %} href="/">Top page</a></li>
|
||||
{%- for item in ['tutorial', 'download', 'manual'] %}
|
||||
<li class="nav-item"><a class="nav-link{% if item == navitem %} active{% endif %}"{% if item == navitem %} aria-current="page"{% endif %} href="/{{ item }}/">{{ item | capitalize }}</a></li>
|
||||
{%- endfor %}
|
||||
<li class="nav-item"><a class="nav-link" href="https://github.com/jqlang/jq" target="_blank" rel="noopener">GitHub</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="https://github.com/jqlang/jq/issues" target="_blank" rel="noopener">Issues</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="https://play.jqlang.org" rel="noopener">Try online!</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="https://raw.githubusercontent.com/jqlang/jq/master/NEWS.md" target="_blank" rel="noopener">News</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{%- if navitem.startswith('manual') %}
|
||||
<div class="container-searchbox form-control p-0 d-none d-md-flex d-print-none border" style="width:16rem">
|
||||
<span class="bi bi-search my-auto ms-2 me-1" aria-hidden="true"></span>
|
||||
<input type="text" id="searchbox" class="form-control border-0 px-1" placeholder="Search manual" role="combobox"
|
||||
aria-label="Search manual" aria-keyshortcuts="/" aria-expanded="false" autocomplete="off" spellcheck="false">
|
||||
<kbd class="mx-1 my-auto text-body bg-body rounded border" style="padding:.1rem .2rem" aria-hidden="true">/</kbd>
|
||||
</div>
|
||||
{%- endif %}
|
||||
<a class="d-md-none bi bi-github fs-4 text-body" href="https://github.com/jqlang/jq" target="_blank" rel="noopener" aria-label="GitHub"></a>
|
||||
</nav>
|
||||
</header>
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import jsonschema
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit("Usage: {} MANUAL_FILE ...".format(sys.argv[0]))
|
||||
|
||||
with open("manual_schema.yml", "r") as schema_file:
|
||||
manual_schema = yaml.safe_load(schema_file)
|
||||
|
||||
for path in sys.argv[1:]:
|
||||
with open(path, "r") as manual_file:
|
||||
manual_data = yaml.safe_load(manual_file)
|
||||
try:
|
||||
jsonschema.validate(instance=manual_data, schema=manual_schema)
|
||||
except jsonschema.exceptions.ValidationError as e:
|
||||
print("Failed to validate:", path, file=sys.stderr)
|
||||
sys.exit(e)
|
||||
@@ -0,0 +1,626 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "execute.h"
|
||||
|
||||
#include "opcode.h"
|
||||
#include "bytecode.h"
|
||||
|
||||
#include "forkable_stack.h"
|
||||
#include "frame_layout.h"
|
||||
|
||||
#include "jv_alloc.h"
|
||||
#include "jq_parser.h"
|
||||
#include "locfile.h"
|
||||
#include "jv.h"
|
||||
#include "jv_aux.h"
|
||||
#include "parser.h"
|
||||
#include "builtin.h"
|
||||
|
||||
struct jq_state {
|
||||
struct forkable_stack data_stk;
|
||||
struct forkable_stack frame_stk;
|
||||
struct forkable_stack fork_stk;
|
||||
jv path;
|
||||
int subexp_nest;
|
||||
int debug_trace_enabled;
|
||||
int initial_execution;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
FORKABLE_STACK_HEADER;
|
||||
jv val;
|
||||
} data_stk_elem;
|
||||
|
||||
void stack_push(jq_state *jq, jv val) {
|
||||
assert(jv_is_valid(val));
|
||||
data_stk_elem* s = forkable_stack_push(&jq->data_stk, sizeof(data_stk_elem));
|
||||
s->val = val;
|
||||
}
|
||||
|
||||
jv stack_pop(jq_state *jq) {
|
||||
data_stk_elem* s = forkable_stack_peek(&jq->data_stk);
|
||||
jv val = s->val;
|
||||
if (!forkable_stack_pop_will_free(&jq->data_stk)) {
|
||||
val = jv_copy(val);
|
||||
}
|
||||
forkable_stack_pop(&jq->data_stk);
|
||||
assert(jv_is_valid(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
struct forkpoint {
|
||||
FORKABLE_STACK_HEADER;
|
||||
struct forkable_stack_state saved_data_stack;
|
||||
struct forkable_stack_state saved_call_stack;
|
||||
int path_len, subexp_nest;
|
||||
uint16_t* return_address;
|
||||
};
|
||||
|
||||
|
||||
void stack_save(jq_state *jq, uint16_t* retaddr){
|
||||
struct forkpoint* fork = forkable_stack_push(&jq->fork_stk, sizeof(struct forkpoint));
|
||||
forkable_stack_save(&jq->data_stk, &fork->saved_data_stack);
|
||||
forkable_stack_save(&jq->frame_stk, &fork->saved_call_stack);
|
||||
fork->path_len =
|
||||
jv_get_kind(jq->path) == JV_KIND_ARRAY ? jv_array_length(jv_copy(jq->path)) : 0;
|
||||
fork->subexp_nest = jq->subexp_nest;
|
||||
fork->return_address = retaddr;
|
||||
}
|
||||
|
||||
void stack_switch(jq_state *jq) {
|
||||
struct forkpoint* fork = forkable_stack_peek(&jq->fork_stk);
|
||||
forkable_stack_switch(&jq->data_stk, &fork->saved_data_stack);
|
||||
forkable_stack_switch(&jq->frame_stk, &fork->saved_call_stack);
|
||||
}
|
||||
|
||||
void path_append(jq_state* jq, jv component) {
|
||||
if (jq->subexp_nest == 0 && jv_get_kind(jq->path) == JV_KIND_ARRAY) {
|
||||
int n1 = jv_array_length(jv_copy(jq->path));
|
||||
jq->path = jv_array_append(jq->path, component);
|
||||
int n2 = jv_array_length(jv_copy(jq->path));
|
||||
assert(n2 == n1 + 1);
|
||||
} else {
|
||||
jv_free(component);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t* stack_restore(jq_state *jq){
|
||||
while (!forkable_stack_empty(&jq->data_stk) &&
|
||||
forkable_stack_pop_will_free(&jq->data_stk)) {
|
||||
jv_free(stack_pop(jq));
|
||||
}
|
||||
while (!forkable_stack_empty(&jq->frame_stk) &&
|
||||
forkable_stack_pop_will_free(&jq->frame_stk)) {
|
||||
frame_pop(&jq->frame_stk);
|
||||
}
|
||||
|
||||
if (forkable_stack_empty(&jq->fork_stk)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct forkpoint* fork = forkable_stack_peek(&jq->fork_stk);
|
||||
uint16_t* retaddr = fork->return_address;
|
||||
forkable_stack_restore(&jq->data_stk, &fork->saved_data_stack);
|
||||
forkable_stack_restore(&jq->frame_stk, &fork->saved_call_stack);
|
||||
int path_len = fork->path_len;
|
||||
if (jv_get_kind(jq->path) == JV_KIND_ARRAY) {
|
||||
assert(path_len >= 0);
|
||||
jq->path = jv_array_slice(jq->path, 0, path_len);
|
||||
} else {
|
||||
assert(path_len == 0);
|
||||
}
|
||||
jq->subexp_nest = fork->subexp_nest;
|
||||
forkable_stack_pop(&jq->fork_stk);
|
||||
return retaddr;
|
||||
}
|
||||
|
||||
|
||||
static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uint16_t* pc) {
|
||||
uint16_t level = *pc++;
|
||||
uint16_t idx = *pc++;
|
||||
fr = frame_get_level(stk, fr, level);
|
||||
if (idx & ARG_NEWCLOSURE) {
|
||||
int subfn_idx = idx & ~ARG_NEWCLOSURE;
|
||||
assert(subfn_idx < frame_self(fr)->bc->nsubfunctions);
|
||||
struct closure cl = {frame_self(fr)->bc->subfunctions[subfn_idx],
|
||||
forkable_stack_to_idx(stk, fr)};
|
||||
return cl;
|
||||
} else {
|
||||
return *frame_closure_arg(fr, idx);
|
||||
}
|
||||
}
|
||||
|
||||
void print_error(jv value) {
|
||||
assert(!jv_is_valid(value));
|
||||
jv msg = jv_invalid_get_msg(value);
|
||||
if (jv_get_kind(msg) == JV_KIND_STRING) {
|
||||
fprintf(stderr, "jq: error: %s\n", jv_string_value(msg));
|
||||
}
|
||||
jv_free(msg);
|
||||
}
|
||||
#define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
|
||||
|
||||
jv jq_next(jq_state *jq) {
|
||||
jv cfunc_input[MAX_CFUNCTION_ARGS];
|
||||
|
||||
uint16_t* pc = stack_restore(jq);
|
||||
assert(pc);
|
||||
|
||||
int backtracking = !jq->initial_execution;
|
||||
jq->initial_execution = 0;
|
||||
while (1) {
|
||||
uint16_t opcode = *pc;
|
||||
|
||||
if (jq->debug_trace_enabled) {
|
||||
dump_operation(frame_current_bytecode(&jq->frame_stk), pc);
|
||||
printf("\t");
|
||||
const struct opcode_description* opdesc = opcode_describe(opcode);
|
||||
data_stk_elem* param = 0;
|
||||
int stack_in = opdesc->stack_in;
|
||||
if (stack_in == -1) stack_in = pc[1];
|
||||
for (int i=0; i<stack_in; i++) {
|
||||
if (i == 0) {
|
||||
param = forkable_stack_peek(&jq->data_stk);
|
||||
} else {
|
||||
printf(" | ");
|
||||
param = forkable_stack_peek_next(&jq->data_stk, param);
|
||||
}
|
||||
if (!param) break;
|
||||
jv_dump(jv_copy(param->val), 0);
|
||||
//printf("<%d>", jv_get_refcnt(param->val));
|
||||
//printf(" -- ");
|
||||
//jv_dump(jv_copy(jq->path), 0);
|
||||
}
|
||||
|
||||
if (backtracking) printf("\t<backtracking>");
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
if (backtracking) {
|
||||
opcode = ON_BACKTRACK(opcode);
|
||||
backtracking = 0;
|
||||
}
|
||||
pc++;
|
||||
|
||||
switch (opcode) {
|
||||
default: assert(0 && "invalid instruction");
|
||||
|
||||
case LOADK: {
|
||||
jv v = jv_array_get(jv_copy(frame_current_bytecode(&jq->frame_stk)->constants), *pc++);
|
||||
assert(jv_is_valid(v));
|
||||
jv_free(stack_pop(jq));
|
||||
stack_push(jq, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case DUP: {
|
||||
jv v = stack_pop(jq);
|
||||
stack_push(jq, jv_copy(v));
|
||||
stack_push(jq, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case DUP2: {
|
||||
jv keep = stack_pop(jq);
|
||||
jv v = stack_pop(jq);
|
||||
stack_push(jq, jv_copy(v));
|
||||
stack_push(jq, keep);
|
||||
stack_push(jq, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case SUBEXP_BEGIN: {
|
||||
jv v = stack_pop(jq);
|
||||
stack_push(jq, jv_copy(v));
|
||||
stack_push(jq, v);
|
||||
jq->subexp_nest++;
|
||||
break;
|
||||
}
|
||||
|
||||
case SUBEXP_END: {
|
||||
assert(jq->subexp_nest > 0);
|
||||
jq->subexp_nest--;
|
||||
jv a = stack_pop(jq);
|
||||
jv b = stack_pop(jq);
|
||||
stack_push(jq, a);
|
||||
stack_push(jq, b);
|
||||
break;
|
||||
}
|
||||
|
||||
case POP: {
|
||||
jv_free(stack_pop(jq));
|
||||
break;
|
||||
}
|
||||
|
||||
case APPEND: {
|
||||
jv v = stack_pop(jq);
|
||||
uint16_t level = *pc++;
|
||||
uint16_t vidx = *pc++;
|
||||
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
||||
jv* var = frame_local_var(fp, vidx);
|
||||
assert(jv_get_kind(*var) == JV_KIND_ARRAY);
|
||||
*var = jv_array_append(*var, v);
|
||||
break;
|
||||
}
|
||||
|
||||
case INSERT: {
|
||||
jv stktop = stack_pop(jq);
|
||||
jv v = stack_pop(jq);
|
||||
jv k = stack_pop(jq);
|
||||
jv objv = stack_pop(jq);
|
||||
assert(jv_get_kind(objv) == JV_KIND_OBJECT);
|
||||
if (jv_get_kind(k) == JV_KIND_STRING) {
|
||||
stack_push(jq, jv_object_set(objv, k, v));
|
||||
stack_push(jq, stktop);
|
||||
} else {
|
||||
print_error(jv_invalid_with_msg(jv_string_fmt("Cannot use %s as object key",
|
||||
jv_kind_name(jv_get_kind(k)))));
|
||||
jv_free(stktop);
|
||||
jv_free(v);
|
||||
jv_free(k);
|
||||
jv_free(objv);
|
||||
goto do_backtrack;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ON_BACKTRACK(RANGE):
|
||||
case RANGE: {
|
||||
uint16_t level = *pc++;
|
||||
uint16_t v = *pc++;
|
||||
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
||||
jv* var = frame_local_var(fp, v);
|
||||
jv max = stack_pop(jq);
|
||||
if (jv_get_kind(*var) != JV_KIND_NUMBER ||
|
||||
jv_get_kind(max) != JV_KIND_NUMBER) {
|
||||
print_error(jv_invalid_with_msg(jv_string_fmt("Range bounds must be numeric")));
|
||||
jv_free(max);
|
||||
goto do_backtrack;
|
||||
} else if (jv_number_value(jv_copy(*var)) >= jv_number_value(jv_copy(max))) {
|
||||
/* finished iterating */
|
||||
goto do_backtrack;
|
||||
} else {
|
||||
jv curr = jv_copy(*var);
|
||||
*var = jv_number(jv_number_value(*var) + 1);
|
||||
|
||||
stack_save(jq, pc - 3);
|
||||
stack_push(jq, jv_copy(max));
|
||||
stack_switch(jq);
|
||||
stack_push(jq, curr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: loadv/storev may do too much copying/freeing
|
||||
case LOADV: {
|
||||
uint16_t level = *pc++;
|
||||
uint16_t v = *pc++;
|
||||
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
||||
jv* var = frame_local_var(fp, v);
|
||||
if (jq->debug_trace_enabled) {
|
||||
printf("V%d = ", v);
|
||||
jv_dump(jv_copy(*var), 0);
|
||||
printf("\n");
|
||||
}
|
||||
jv_free(stack_pop(jq));
|
||||
stack_push(jq, jv_copy(*var));
|
||||
break;
|
||||
}
|
||||
|
||||
// Does a load but replaces the variable with null
|
||||
case LOADVN: {
|
||||
uint16_t level = *pc++;
|
||||
uint16_t v = *pc++;
|
||||
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
||||
jv* var = frame_local_var(fp, v);
|
||||
if (jq->debug_trace_enabled) {
|
||||
printf("V%d = ", v);
|
||||
jv_dump(jv_copy(*var), 0);
|
||||
printf("\n");
|
||||
}
|
||||
jv_free(stack_pop(jq));
|
||||
stack_push(jq, *var);
|
||||
*var = jv_null();
|
||||
break;
|
||||
}
|
||||
|
||||
case STOREV: {
|
||||
uint16_t level = *pc++;
|
||||
uint16_t v = *pc++;
|
||||
frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level);
|
||||
jv* var = frame_local_var(fp, v);
|
||||
jv val = stack_pop(jq);
|
||||
if (jq->debug_trace_enabled) {
|
||||
printf("V%d = ", v);
|
||||
jv_dump(jv_copy(val), 0);
|
||||
printf("\n");
|
||||
}
|
||||
jv_free(*var);
|
||||
*var = val;
|
||||
break;
|
||||
}
|
||||
|
||||
case PATH_BEGIN: {
|
||||
jv v = stack_pop(jq);
|
||||
stack_push(jq, jq->path);
|
||||
|
||||
stack_save(jq, pc - 1);
|
||||
stack_switch(jq);
|
||||
|
||||
stack_push(jq, jv_number(jq->subexp_nest));
|
||||
stack_push(jq, v);
|
||||
|
||||
jq->path = jv_array();
|
||||
jq->subexp_nest = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case PATH_END: {
|
||||
jv v = stack_pop(jq);
|
||||
jv_free(v); // discard value, only keep path
|
||||
|
||||
int old_subexp_nest = (int)jv_number_value(stack_pop(jq));
|
||||
|
||||
jv path = jq->path;
|
||||
jq->path = stack_pop(jq);
|
||||
|
||||
stack_save(jq, pc - 1);
|
||||
stack_push(jq, jv_copy(path));
|
||||
stack_switch(jq);
|
||||
|
||||
stack_push(jq, path);
|
||||
jq->subexp_nest = old_subexp_nest;
|
||||
break;
|
||||
}
|
||||
|
||||
case ON_BACKTRACK(PATH_BEGIN):
|
||||
case ON_BACKTRACK(PATH_END): {
|
||||
jv_free(jq->path);
|
||||
jq->path = stack_pop(jq);
|
||||
goto do_backtrack;
|
||||
}
|
||||
|
||||
case INDEX: {
|
||||
jv t = stack_pop(jq);
|
||||
jv k = stack_pop(jq);
|
||||
path_append(jq, jv_copy(k));
|
||||
jv v = jv_get(t, k);
|
||||
if (jv_is_valid(v)) {
|
||||
stack_push(jq, v);
|
||||
} else {
|
||||
print_error(v);
|
||||
goto do_backtrack;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case JUMP: {
|
||||
uint16_t offset = *pc++;
|
||||
pc += offset;
|
||||
break;
|
||||
}
|
||||
|
||||
case JUMP_F: {
|
||||
uint16_t offset = *pc++;
|
||||
jv t = stack_pop(jq);
|
||||
jv_kind kind = jv_get_kind(t);
|
||||
if (kind == JV_KIND_FALSE || kind == JV_KIND_NULL) {
|
||||
pc += offset;
|
||||
}
|
||||
stack_push(jq, t); // FIXME do this better
|
||||
break;
|
||||
}
|
||||
|
||||
case EACH:
|
||||
stack_push(jq, jv_number(-1));
|
||||
// fallthrough
|
||||
case ON_BACKTRACK(EACH): {
|
||||
int idx = jv_number_value(stack_pop(jq));
|
||||
jv container = stack_pop(jq);
|
||||
|
||||
int keep_going, is_last = 0;
|
||||
jv key, value;
|
||||
if (jv_get_kind(container) == JV_KIND_ARRAY) {
|
||||
if (opcode == EACH) idx = 0;
|
||||
else idx = idx + 1;
|
||||
int len = jv_array_length(jv_copy(container));
|
||||
keep_going = idx < len;
|
||||
is_last = idx == len - 1;
|
||||
if (keep_going) {
|
||||
key = jv_number(idx);
|
||||
value = jv_array_get(jv_copy(container), idx);
|
||||
}
|
||||
} else if (jv_get_kind(container) == JV_KIND_OBJECT) {
|
||||
if (opcode == EACH) idx = jv_object_iter(container);
|
||||
else idx = jv_object_iter_next(container, idx);
|
||||
keep_going = jv_object_iter_valid(container, idx);
|
||||
if (keep_going) {
|
||||
key = jv_object_iter_key(container, idx);
|
||||
value = jv_object_iter_value(container, idx);
|
||||
}
|
||||
} else {
|
||||
assert(opcode == EACH);
|
||||
print_error(jv_invalid_with_msg(jv_string_fmt("Cannot iterate over %s",
|
||||
jv_kind_name(jv_get_kind(container)))));
|
||||
keep_going = 0;
|
||||
}
|
||||
|
||||
if (!keep_going) {
|
||||
jv_free(container);
|
||||
goto do_backtrack;
|
||||
} else if (is_last) {
|
||||
// we don't need to make a backtrack point
|
||||
jv_free(container);
|
||||
path_append(jq, key);
|
||||
stack_push(jq, value);
|
||||
} else {
|
||||
stack_save(jq, pc - 1);
|
||||
stack_push(jq, container);
|
||||
stack_push(jq, jv_number(idx));
|
||||
stack_switch(jq);
|
||||
path_append(jq, key);
|
||||
stack_push(jq, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
do_backtrack:
|
||||
case BACKTRACK: {
|
||||
pc = stack_restore(jq);
|
||||
if (!pc) {
|
||||
return jv_invalid();
|
||||
}
|
||||
backtracking = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case FORK: {
|
||||
stack_save(jq, pc - 1);
|
||||
stack_switch(jq);
|
||||
pc++; // skip offset this time
|
||||
break;
|
||||
}
|
||||
|
||||
case ON_BACKTRACK(FORK): {
|
||||
uint16_t offset = *pc++;
|
||||
pc += offset;
|
||||
break;
|
||||
}
|
||||
|
||||
case CALL_BUILTIN: {
|
||||
int nargs = *pc++;
|
||||
jv top = stack_pop(jq);
|
||||
cfunc_input[0] = top;
|
||||
for (int i = 1; i < nargs; i++) {
|
||||
cfunc_input[i] = stack_pop(jq);
|
||||
}
|
||||
struct cfunction* func = &frame_current_bytecode(&jq->frame_stk)->globals->cfunctions[*pc++];
|
||||
top = cfunction_invoke(func, cfunc_input);
|
||||
if (jv_is_valid(top)) {
|
||||
stack_push(jq, top);
|
||||
} else {
|
||||
print_error(top);
|
||||
goto do_backtrack;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CALL_JQ: {
|
||||
uint16_t nclosures = *pc++;
|
||||
uint16_t* retaddr = pc + 2 + nclosures*2;
|
||||
frame_ptr new_frame = frame_push(&jq->frame_stk,
|
||||
make_closure(&jq->frame_stk, frame_current(&jq->frame_stk), pc),
|
||||
retaddr);
|
||||
pc += 2;
|
||||
frame_ptr old_frame = forkable_stack_peek_next(&jq->frame_stk, new_frame);
|
||||
assert(nclosures == frame_self(new_frame)->bc->nclosures);
|
||||
for (int i=0; i<nclosures; i++) {
|
||||
*frame_closure_arg(new_frame, i) = make_closure(&jq->frame_stk, old_frame, pc);
|
||||
pc += 2;
|
||||
}
|
||||
|
||||
pc = frame_current_bytecode(&jq->frame_stk)->code;
|
||||
break;
|
||||
}
|
||||
|
||||
case RET: {
|
||||
uint16_t* retaddr = *frame_current_retaddr(&jq->frame_stk);
|
||||
if (retaddr) {
|
||||
// function return
|
||||
pc = retaddr;
|
||||
frame_pop(&jq->frame_stk);
|
||||
} else {
|
||||
// top-level return, yielding value
|
||||
jv value = stack_pop(jq);
|
||||
stack_save(jq, pc - 1);
|
||||
stack_push(jq, jv_null());
|
||||
stack_switch(jq);
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_BACKTRACK(RET): {
|
||||
// resumed after top-level return
|
||||
goto do_backtrack;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jq_init(struct bytecode* bc, jv input, jq_state **jq, int flags) {
|
||||
jq_state *new_jq;
|
||||
new_jq = jv_mem_alloc(sizeof(*new_jq));
|
||||
memset(new_jq, 0, sizeof(*new_jq));
|
||||
new_jq->path = jv_null();
|
||||
forkable_stack_init(&new_jq->data_stk, sizeof(data_stk_elem) * 100);
|
||||
forkable_stack_init(&new_jq->frame_stk, 1024);
|
||||
forkable_stack_init(&new_jq->fork_stk, 1024);
|
||||
|
||||
stack_push(new_jq, input);
|
||||
struct closure top = {bc, -1};
|
||||
frame_push(&new_jq->frame_stk, top, 0);
|
||||
stack_save(new_jq, bc->code);
|
||||
stack_switch(new_jq);
|
||||
if (flags & JQ_DEBUG_TRACE) {
|
||||
new_jq->debug_trace_enabled = 1;
|
||||
} else {
|
||||
new_jq->debug_trace_enabled = 0;
|
||||
}
|
||||
new_jq->initial_execution = 1;
|
||||
*jq = new_jq;
|
||||
}
|
||||
|
||||
void jq_teardown(jq_state **jq) {
|
||||
jq_state *old_jq = *jq;
|
||||
if (old_jq == NULL)
|
||||
return;
|
||||
*jq = NULL;
|
||||
|
||||
while (stack_restore(old_jq)) {}
|
||||
|
||||
assert(forkable_stack_empty(&old_jq->fork_stk));
|
||||
assert(forkable_stack_empty(&old_jq->data_stk));
|
||||
assert(forkable_stack_empty(&old_jq->frame_stk));
|
||||
forkable_stack_free(&old_jq->fork_stk);
|
||||
forkable_stack_free(&old_jq->data_stk);
|
||||
forkable_stack_free(&old_jq->frame_stk);
|
||||
|
||||
jv_free(old_jq->path);
|
||||
jv_mem_free(old_jq);
|
||||
}
|
||||
|
||||
struct bytecode* jq_compile_args(const char* str, jv args) {
|
||||
assert(jv_get_kind(args) == JV_KIND_ARRAY);
|
||||
struct locfile locations;
|
||||
locfile_init(&locations, str, strlen(str));
|
||||
block program;
|
||||
struct bytecode* bc = 0;
|
||||
int nerrors = jq_parse(&locations, &program);
|
||||
if (nerrors == 0) {
|
||||
for (int i=0; i<jv_array_length(jv_copy(args)); i++) {
|
||||
jv arg = jv_array_get(jv_copy(args), i);
|
||||
jv name = jv_object_get(jv_copy(arg), jv_string("name"));
|
||||
jv value = jv_object_get(arg, jv_string("value"));
|
||||
program = gen_var_binding(gen_const(value), jv_string_value(name), program);
|
||||
jv_free(name);
|
||||
}
|
||||
jv_free(args);
|
||||
program = builtins_bind(program);
|
||||
nerrors = block_compile(program, &locations, &bc);
|
||||
}
|
||||
if (nerrors) {
|
||||
fprintf(stderr, "%d compile %s\n", nerrors, nerrors > 1 ? "errors" : "error");
|
||||
}
|
||||
locfile_free(&locations);
|
||||
return bc;
|
||||
}
|
||||
|
||||
struct bytecode* jq_compile(const char* str) {
|
||||
return jq_compile_args(str, jv_array());
|
||||
}
|
||||
Loaded 100 of 396 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user